这种情况不是因为平台进程接受不到signal,而是收到了signal信号而且正确执行了sem_post操作(你可以在signal handler中加入打印调试语句看看),因为你的刷屏幕操作线程执行时间太长了,导致连续执行好几次屏幕操作,这是种恶性循环(因为gps软件每次数据准备好就发送个signal,而你的 signal在每次捕捉到signal后就执行一次sem_post,然而你的刷屏幕操作时间太长了当执行完一次刷屏幕操作后再次调用sem_wait的时候已经有多个信号量资源了也就是消费跟不上生产,信号量post次数比wait次数多)
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <pthread.h>
#include <semaphore.h>
sem_t lock
int gps_data = 0
/* fflush screen thread */
void *gps_data_process (void *arg)
{
while (1)
{
/* wait gps data is ready */
/* second run sem_wait will by more semaphore it will not block */
sem_wait(&lock)
/* ok data is ready */
printf("Data is [%d]\n", gps_data)
/* simulate a long procees time */
sleep(100)
}
}
/* SIGUSR1 handler */
void gps_data_request(int sig)
{
if (sig == SIGUSR1)
{
/* ok gps data is ready so request process */
sem_post(&lock)
}
}
int main(int argc, char **argv)
{
pthread_t tid
struct sigaction action
/* initialize semaphore */
if (sem_init(&lock, 0, 0) == -1)
{
perror("sem_init")
exit(1)
}
action.sa_handler = gps_data_request
sigemptyset(&action.sa_mask)
action.sa_flags = 0
/* caught signal SIGUSR1 */
if (sigaction(SIGUSR1, &action, NULL))
{
perror("sigaction")
exit(1)
}
/* create a thread */
if (pthread_create(&tid, NULL, gps_data_process, NULL) == -1)
{
perror("pthread_create")
exit(1)
}
while (1)
{
printf("[GPS]>>>")
/* gps get data ready */
scanf("%d", &gps_data)
if (gps_data)
{
/* simulate gps program send signal to platform process */
raise(SIGUSR1)
}
sleep(1)
}
return 0
}
Linux信号量(semaphore)是一种互斥机制。即对某个互斥资源的访问会收到信号量的保护,在访问之前需要获得信号量。在操作完共享资源后,需释放信号量,以便另外的进程来获得资源。获得和释放应该成对出现。
获得信号量集,需要注意的是,获得的是一个集合,而不是一个单一的信号量。
#include
#include
#include
1: int semget(key_t key,int nsems,int semflg)
key:系统根据这个值来获取信号量集。
nsems:此信号集包括几个信号量。
semflg:创建此信号量的属性。 (IPC_CREAT | IPC_EXCL | S_IRUSR | S_IWUSR)
成功则返回该信号量集的ID。
注:
既指定IPC_CREAT又指定IPC_EXCL时,如果系统中该信号量集已经存在,则马上返回。
如果需要获得存在的信号量,则将此参数置0.
2: int semctl(int semid,int senum,int cmd....)
semid:信号量ID。
senum:对信号量集中的第几个信号量进行控制。(从0开始)
cmd:需要进行的操作。(SETVAL是其中的一个)。
根据cmd的不同可能存在第四个参数,cmd=SETVAL时,表示同时信号量可以被获得几次,如第四个参数
num=1表示只能被获得一次,既被信号量保护的资源只能同时被一个程序使用。
该系统调用,是在对信号量初始化时用的。
-3: “3”前面加了"-"表示当需要使用互斥资源时应该做这步。
int semop(int semid,struct sembuf *sem,int num_elements)
struct sembuf {
unsigned short sem_num //该信号量集中的第几个信号量。
int sem_op//需要获得还是释放信号量
int sem_flg//相关动作
}
num_elements:需要对该信号量集中的多少个信号量进行处理。
获得信号量时,将sembuf结构提初始化为:
sem_num = 0//该信号量集中的首个信号量
sem_op = -1//获得信号量
sem_flag = IPC_NOWAIT //如果不能获得信号量,马上返回。
semop(semid,_sem,1)
同理释放信号量时,将sem_op设为1.
以上是对信号量的简单处理
信号量在进程是以有名信号量进行通信的,在线程是以无名信号进行通信的,因为线程linux还没有实现进程间的通信,所以在sem_init的第二个参数要为0,而且在多线程间的同步是可以通过有名信号量也可通过无名信号,但是一般情况线程的同步是无名信号量,无名信号量使用简单,而且sem_t存储在进程空间中,有名信号量必须LINUX内核管理,由内核结构struct ipc_ids 存储,是随内核持续的,系统关闭,信号量则删除,当然也可以显示删除,通过系统调用删除,消息队列,信号量,内存共享,这几个都是一样的原理。,只不过信号量分为有名与无名
无名使用 <semaphore.h>,
有名信号量<sys/sem.h>
无名信号量不能用进程间通信,
//无名与有名的区别,有名需要KEY值与IPC标识
所以sem_init的第二个参数必须为0,,,,
欢迎分享,转载请注明来源:夏雨云
评论列表(0条)