免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 2219 | 回复: 8
打印 上一主题 下一主题

用信号量进行ipc的问题 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2007-11-05 16:32 |只看该作者 |倒序浏览
因为建立信号量的时候我想对信号量赋初值.
代码类似于

semid = semget(,,IPC_CREAT|0666);
semctl(semid,,SETVAL,semopts);

在两个进程中都有这样的代码.
这样有个问题,当第一个进程建立好semaphore并初始化后,第二个进程可能会在启动后重新初始化semaphore的值.
请问怎样能让第二个进程知道semaphore已经初始化完成,然后它就不用再去初始化semaphore?

论坛徽章:
0
2 [报告]
发表于 2007-11-05 19:19 |只看该作者
就是如何判断已经有一个进程用同一个key调用过semget了?

论坛徽章:
0
3 [报告]
发表于 2007-11-05 20:01 |只看该作者
   semid = semget(mykey, 2, PERMS | IPC_CREAT | IPC_EXCL);

   if ((semid == -1) && (errno != EEXIST))         /* real error, so return */

      return -1;

论坛徽章:
0
4 [报告]
发表于 2007-11-05 20:09 |只看该作者
USP (Unix Systems Programming: Communication, Concurrency, and Threads) 15.2节有详细说明和举例。


  1. /* initsemset.c */

  2. /* A function that creates and initializes a semaphore set
  3.    containing a single semaphore.
  4. */

  5. #include <errno.h>
  6. #include <signal.h>
  7. #include <stdio.h>
  8. #include <time.h>
  9. #include <sys/sem.h>
  10. #include <sys/stat.h>

  11. #define PERMS (S_IRUSR | S_IWUSR)
  12. #define TEN_MILLION 10000000L
  13. int initelement(int semid, int semnum, int semvalue);

  14. int initsemset(key_t mykey, int value, sig_atomic_t *readyp) {
  15.    int semid;
  16.    struct timespec sleeptime;

  17.    sleeptime.tv_sec = 0;
  18.    sleeptime.tv_nsec = TEN_MILLION;
  19.    semid = semget(mykey, 2, PERMS | IPC_CREAT | IPC_EXCL);
  20.    if ((semid == -1) && (errno != EEXIST))         /* real error, so return */
  21.       return -1;
  22.    if (semid >= 0) {          /* we created the semaphore, so initialize it */
  23.       if (initelement(semid, 0, value) == -1)
  24.          return -1;
  25.       *readyp = 1;
  26.       return semid;
  27.    }
  28.    if ((semid = semget(mykey, 2, PERMS)) == -1)           /* just access it */
  29.       return -1;
  30.    while (*readyp == 0)                            /* wait for initialization */
  31.       nanosleep(&sleeptime, NULL);
  32.    return semid;
  33. }
复制代码


使用:

  1. static sig_atomic_t ready = 0;
  2. initsemset(key, value, &ready);
复制代码



  1. /* initelement.c */

  2. #include <sys/sem.h>

  3. int initelement(int semid, int semnum, int semvalue) {
  4.    union semun {
  5.       int val;
  6.       struct semid_ds *buf;
  7.       unsigned short *array;
  8.    } arg;
  9.    arg.val = semvalue;
  10.    return semctl(semid, semnum, SETVAL, arg);
  11. }
复制代码

[ 本帖最后由 westgarden 于 2007-11-5 20:27 编辑 ]

论坛徽章:
0
5 [报告]
发表于 2007-11-05 21:04 |只看该作者
明白了。还有个问题,为什么我CTRL C终止这两个进程后再重启,这个key对应的信号量没有被清除?

论坛徽章:
0
6 [报告]
发表于 2007-11-05 21:46 |只看该作者
man ipcs
man ipcrm

论坛徽章:
0
7 [报告]
发表于 2007-11-05 21:51 |只看该作者
原帖由 iterator 于 2007-11-5 21:04 发表
明白了。还有个问题,为什么我CTRL C终止这两个进程后再重启,这个key对应的信号量没有被清除?

System V 的信号量是内核持续性的,系统重启才被清除,或用ipcs手动清除。

论坛徽章:
0
8 [报告]
发表于 2007-11-06 10:52 |只看该作者
这个问题搞定了,多谢.又遇到一个问题.
因为我是让两个进程共享一段环型队列.那么对于其中一个进程有个初始的读位置,另一个进程有个初始的写位置.(都是0).
如果这两个进程都不退出,那都没有问题.
但一旦有个进程退出(比如说写进程退出),而这时读进程的当前读位置不一定是0.
当写进程再次启动时它仍只会从0位置开始写,因为它不知道读进程的当前读位置,这样就造成了数据的错误.

论坛徽章:
0
9 [报告]
发表于 2007-11-06 12:19 |只看该作者
正常退出前保存当前读/写位置。
如果是非正常退出就有点麻烦。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP