您好,登录后才能下订单哦!
原理不多讲,可能查看unix 高级环境编程,只提一些注意点
信号量系统限制
难理解的是标志位SEM_UNDO
以下是个人愚见:
首先是了解一下"信号量调整值",每一个信号量都会对应有一个调整值,并且对信号量进行操作的时候进行维护。如果设置了SEM_UNDO则立即更新,如果没有何时更新,我也不知道,可能是系统调度吧;
在进行退出,无论是正常还是异常,内核都会遍历一次进程的调整值,进行处理,具体怎样处理有待研究;
个人经验:如果在V 和 P 操作上, 如果需要阻塞的,最好标志位上赋SEM_UNDO,如果不阻塞那就不需要,这样会少点意想不到的错误
网上解释:
每一个独立的信号灯操作可能都需要维护一个调整动作。 Linux 至少为每一个进程
http://3521632.blog.163.com/blog/static/110237933201032041353708/
以下例程
第一:先执行init.c初始化,让信号量集的第1个信号量值为1,当然电脑索引是从0开始的;
第二:再执行多个test.c
intit.c
- #include <sys/types.h>
- #include <sys/ipc.h>
- #include <sys/sem.h>
- #include <stdlib.h>
- #include <unistd.h>
- #include <stdio.h>
- #include <string.h>
- 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);
- return 0;
- }
- int open_semque(void)
- {
//创建一个键- key_t key = ftok("./",100);
- if(key == -1)
- {
- perror("ftok\n");
- exit(1);
- }
- //创建信号量集,
- //IPC_CREAT 存在则打开,不存在则新建,
- //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 <sys/types.h>
- #include <sys/ipc.h>
- #include <sys/sem.h>
- #include <stdlib.h>
- #include <unistd.h>
- #include <stdio.h>
- #include <string.h>
- 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);
- }
- }
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。