免费注册 查看新帖 |

Chinaunix

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

[求助] 关于freebsd中system V信号灯的问题(顶) [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2004-08-26 10:30 |只看该作者 |倒序浏览
问题:关于freebsd中system V信号灯实现的问题
环境:Freebsd4.10, gcc3.3
来源:unp2 p254页 建立信号量的问题

在这页中,有一个例程 (图11.7)其中初始化信号灯的部分,我摘录如下。



  1. #define SVSEM_MODE  (SEM_R | SEM_A | SEM_R>;>;3 | SEM_R>;>;6)
  2. #define CRSEM_MODE        IPC_CREAT | IPC_EXCL | SVSEM_MODE

  3. static int createSemaphore()
  4. {
  5.         union semun                arg;
  6.         struct semid_ds        seminfo;

  7.         key_t logkey = ftok(FILE_PASSWORD_LOCK, 0);                        // 建立ipc标识
  8.         if ( logkey == -1 )
  9.         {
  10.                 log_msg("error on ftok");
  11.                 return -1;                                                                        // 没有找到文件或没有权限读取它
  12.         }               
  13.        
  14.         semid = semget(logkey, 1, CRSEM_MODE);                                // 新建信号量               
  15.         if ( semid >;= 0 )
  16.         {
  17.                         /* 4success, we're the first so initialize */
  18.                 arg.val = 1;
  19.                 if ( -1 == semctl(semid, 0, SETVAL, arg) )
  20.                 {
  21.                         log_msg("error on setctl");
  22.                         return -1;
  23.                 }
  24.         }
  25.         else if (errno == EEXIST)
  26.         {
  27.                         /* 4someone else has created; make sure it's initialized */
  28.                 semid = semget(logkey, 1, SVSEM_MODE);
  29.                 if ( -1 == semid )
  30.                 {
  31.                         return -1;
  32.                 }
  33.                
  34.                 arg.buf = &
  35.                 int i;
  36.                 for (i = 0; i < MAX_TRIES; i++) {
  37.                         if ( -1 == semctl(semid, 0, IPC_STAT, arg) )
  38.                         {
  39.                                 log_msg("set value in max tries error");
  40.                                 return -1;
  41.                         }
  42.                        
  43.                         if (arg.buf->;sem_otime != 0)   // 就是这里,freebsd4上不起作用
  44.                                 goto init;
  45.                         sleep(1);
  46.                 }
  47.                 log_msg("timeout error");       
  48.                 return -1;                                                                        //semget OK, but semaphore not initialized

  49.         }
  50.         else
  51.         {
  52.                 return -1;                                                                        // semget error
  53.         }
  54. init:
  55.         initflag = 1;
  56.         postop.sem_num = 0;                /* and init the two semop() structures */
  57.         postop.sem_op  = 1;
  58.         postop.sem_flg = SEM_UNDO;
  59.         waitop.sem_num = 0;
  60.         waitop.sem_op  = -1;
  61.         waitop.sem_flg = SEM_UNDO;
  62.        
  63.         return 0;
  64. }
复制代码


问题在于,当信号灯已经建立后,这段程序会检查信号灯是否已经被初始化。在程序中,如果 sem_otime == 0 ,则等待创建信号灯的进程完成它的初始化工作,如果sem_otime != 0,则信号灯已经被初始化完成。

在我的程序中,发现除了创建信号灯的进程外,其它进程都拿不到这个锁。debug后发现,sem_otime总是==0,所以在这里死锁。

我觉得在freebsd4中,sem_otime总是为0。系统在初始化信号灯时,没有正确的初始化这个变量,没有按照system V的标准来实现。大家看看我的理解是否有误?

除了freebsd, 别的系统我还没有测试过,不知道结果是否有普遍性

论坛徽章:
0
2 [报告]
发表于 2004-08-27 08:50 |只看该作者

[求助] 关于freebsd中system V信号灯的问题(顶)

贴子沉了,自己顶。用freebsd的兄弟看看是不是这样的情况,还是我的理解有问题?多谢啦

论坛徽章:
0
3 [报告]
发表于 2004-08-27 09:37 |只看该作者

[求助] 关于freebsd中system V信号灯的问题(顶)

sem_otime是最后semop()调用的时间,初始化时总是为0。

为什么你认为sem_otime != 0可以用来判断初始化?说一说。

论坛徽章:
0
4 [报告]
发表于 2004-08-27 17:28 |只看该作者

[求助] 关于freebsd中system V信号灯的问题(顶)

多谢aXe的回复。

在这个程序中,semget首先试图建立信号灯。如果已经被建立,那么错误信息为 EEXIST


  1. semid = semget(logkey, 1, CRSEM_MODE);            // 新建信号量      
  2.    if ( semid >;= 0 )
  3.    {
  4.          /* 4success, we're the first so initialize */
  5.       arg.val = 1;
  6.       if ( -1 == semctl(semid, 0, SETVAL, arg) )
  7.       {
  8.          log_msg("error on setctl");
  9.          return -1;
  10.       }
  11.    }
  12.    else if (errno == EEXIST)
复制代码



按照您说的
sem_otime是最后semop()调用的时间,初始化时总是为0

如果信号灯已经被初始化,那么 sem_otime != 0

为什么你认为sem_otime != 0可以用来判断初始化?说一说

所以我据此来判断是否初始化。如果没有被初始化,则等待创建信号灯的进程完成初始化。

正如我在1楼所说,在freebsd4中没有达到此中效果,所以猜想freebsd4中的实现会不会有一点问题。我想我的理解可能会有错误,请aXe和各位兄弟指点一二。

论坛徽章:
0
5 [报告]
发表于 2004-08-27 22:54 |只看该作者

[求助] 关于freebsd中system V信号灯的问题(顶)

如果已经存在,并且你得到了正确的id,这个时候表示已经初始化完成了。

论坛徽章:
0
6 [报告]
发表于 2004-08-28 09:37 |只看该作者

[求助] 关于freebsd中system V信号灯的问题(顶)

[quote]原帖由 "aXe"]如果已经存在,并且你得到了正确的id,这个时候表示已经初始化完成了。[/quote 发表:


aXe您好。按照steven在unp2上所说,由于system信号灯被创建后,还需要 用semctl来初始化信号量,而semget与semctl不是原子操作, 所以可能会存在这样的情况:

进程1创建了信号灯,此时os阻塞进程1。进程2取得信号灯,由于进程1还没有初始化信号量,所以会发生问题。

关于这个问题的描述,我在1楼已经说明了在unpv2的页数,可以查阅。

但是按照改进过的方法,即check o_time时,在freebsd4中却会阻塞,即使进程1已经完成了信号量的创建及初始化。

所以我发贴子请教各位前辈,是否freebsd4中的实现有些问题。

论坛徽章:
0
7 [报告]
发表于 2004-08-30 09:03 |只看该作者

[求助] 关于freebsd中system V信号灯的问题(顶)

自己顶一下

论坛徽章:
0
8 [报告]
发表于 2004-08-30 17:25 |只看该作者

[求助] 关于freebsd中system V信号灯的问题(顶)

但是按照改进过的方法,即check o_time时,在freebsd4中却会阻塞,即使进程1已经完成了信号量的创建及初始化。

你是说执行
if (arg.buf->;sem_otime != 0)   // 就是这里,freebsd4上不起作用

这句后进程睡眠了吗?
我在rh9.0上测试没有问题。

论坛徽章:
0
9 [报告]
发表于 2004-08-30 18:03 |只看该作者

[求助] 关于freebsd中system V信号灯的问题(顶)

这个判断始终为false,所以会 sleep
所以我推测freebsd实现上有问题

论坛徽章:
0
10 [报告]
发表于 2004-08-31 09:39 |只看该作者

[求助] 关于freebsd中system V信号灯的问题(顶)

第一个创建的进程初始化完后,这个判断当然始终是false。这样避免竞争的前提是假设在MAXTRIS秒钟之内,第一个创建的进程会调用semop至少一次,这时判断就为true了。如果第一个创建的进程一直没有调用semop,那么这个判断始终为false,所以会一直sleep ,没错,可是也没有办法。要不为什么说semget和初始化的semctl是信号量的弱点呢。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP