unix XSI IPC-信号量同步例程
原理不多讲,可能查看unix 高级环境编程,只提一些注意点
信号量系统限制
信号量最大值 32767
最多信号量集 128
每个集中最多含有250信号量
难理解的是标志位SEM_UNDO
以下是个人愚见:
首先是了解一下"信号量调整值",每一个信号量都会对应有一个调整值,并且对信号量进行操作的时候进行维护。如果设置了SEM_UNDO则立即更新,如果没有何时更新,我也不知道,可能是系统调度吧;
在进行退出,无论是正常还是异常,内核都会遍历一次进程的调整值,进行处理,具体怎样处理有待研究;
个人经验:如果在V 和 P 操作上, 如果需要阻塞的,最好标志位上赋SEM_UNDO,如果不阻塞那就不需要,这样会少点意想不到的错误
网上解释:
每一个独立的信号灯操作可能都需要维护一个调整动作。 Linux 至少为每一个进程
的每一个信号灯数组都维护一个 sem_undo 的数据结构。如果请求的进程没有,就在需
要的时候为它创建一个。这个新的 sem_undo 数据结构同时在进程的 task_struct 数据
结构和信号灯队列的 semid_ds 数据结构的队列中排队。对信号灯队列中的信号灯执行
操作的时候,和这个操作值相抵消的值加到这个进程的 sem_undo 数据结构的调整队列
这个信号灯的条目上。所以,如果操作值为 2 ,那么这个就在这个信号灯的调整条目上
增加 -2 。
当进程被删除,比如退出的时候, Linux 遍历它的 sem_undo 数据结构组,并
实施对于信号灯数组的调整。如果删除信号灯,它的 sem_undo 数据结构仍旧停留在进
程的 task_struct 队列中,但是相应的信号灯数组标识符标记为无效。这种情况下,清除
信号灯的代码只是简单地废弃这个 sem_undo 数据结构。
存在则打开,不存在则新建,//0666是权限//设置这个信号量集中包含几个信号量,设为1 int semque_id = semget(key, 1,IPC_CREAT|0666); if(semque_id == -1) { perror("msgget\n"); exit(1); } return semque_id; } void set_sem(int semque_id, int val) { //此联合体需要自己去创建,在初始化信号量时需要这个联合体; union semun sem_union; sem_union.val = val; if(semctl(semque_id, 0, SETVAL, sem_union) == -1) { perror("semctl_set\n"); exit(1); } }
test.c
#include #include #include #include #include #include #include void v_sem(int); void p_sem(int); int open_semque(void); void set_sem(int, int); #if 1 union semun { int val; struct semid_ds buf; unsigned short *array; }; #endif int main(int argc,char** argv) { int ret; int semque_id; semque_id = open_semque(); //set_sem(semque_id, 1); ret = semctl(semque_id, 0, GETVAL); printf("信号集中第一个信号量的值为:%d\n",ret); fputs("执行操作V\n",stdout); v_sem(semque_id); ret = semctl(semque_id, 0, GETVAL); printf("信号集中第一个信号量的值为:%d\n",ret); int second = 10; while(second) { sleep(1); printf("%ds\n",second); ret = semctl(semque_id, 0, GETVAL); printf("信号集中第一个信号量的值为:%d\n",ret); second--; } fputs("执行操作P\n",stdout); p_sem(semque_id); ret = semctl(semque_id, 0, GETVAL); printf("信号集中第一个信号量的值为:%d\n",ret); //semctl(semque_id, 0, IPC_RMID); return 0; } int open_semque(void) { key_t key = ftok("./",100); if(key == -1) { perror("ftok\n"); exit(1); } int semque_id = semget(key, 1,IPC_CREAT|0666); if(semque_id == -1) { perror("msgget\n"); exit(1); } return semque_id; } void set_sem(int semque_id, int val) { union semun sem_union; sem_union.val = val; if(semctl(semque_id, 0, SETVAL, sem_union) == -1) { perror("semctl_set\n"); exit(1); } } void p_sem(int semque_id) { struct sembuf arry[1]; arry[0].sem_num = 0; arry[0].sem_op = 1; //arry[0].sem_flg = SEM_UNDO; int ret; //需要通过结构体struct sembuf进行赋值 if(ret = semop(semque_id, arry, 1)) { perror("semop\n"); exit(1); } } void v_sem(int semque_id) { struct sembuf arry[1]; arry[0].sem_num = 0; arry[0].sem_op = -1; //arry[0].sem_flg = IPC_NOWAIT; arry[0].sem_flg = SEM_UNDO; int ret; if(ret = semop(semque_id, arry, 1)) { perror("semop\n"); exit(1); } }
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。
暂时没有评论,来抢沙发吧~