unix XSI IPC-信号量同步例程

网友投稿 587 2022-09-23

unix XSI IPC-信号量同步例程

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小时内删除侵权内容。

上一篇:unix 共享储存及信号量例程
下一篇:8个Python面试必考的题目,小编也被坑过 ToT(python面试题史上最全)
相关文章

 发表评论

暂时没有评论,来抢沙发吧~