在不调用semctl()的情况下调用semget()后跟semop()是否正确?

Lon*_*ner 4 c semaphore ipc

我正在通过Beej的Unix IPC指南中的信号量示例程序.

示例程序包含以下信号量初始化代码.我只发布一个与问题相关的片段.要查看完整代码,请访问我上面提供的链接.

/*
** initsem() -- more-than-inspired by W. Richard Stevens' UNIX Network
** Programming 2nd edition, volume 2, lockvsem.c, page 295.
*/
int initsem(key_t key, int nsems)  /* key from ftok() */
{
    int i;
    union semun arg;
    struct semid_ds buf;
    struct sembuf sb;
    int semid;

    semid = semget(key, nsems, IPC_CREAT | IPC_EXCL | 0666);

    if (semid >= 0) { /* we got it first */
        sb.sem_op = 1; sb.sem_flg = 0;
        arg.val = 1;

        printf("press return\n"); getchar();

        for(sb.sem_num = 0; sb.sem_num < nsems; sb.sem_num++) { 
            /* do a semop() to "free" the semaphores. */
            /* this sets the sem_otime field, as needed below. */
            if (semop(semid, &sb, 1) == -1) {
                int e = errno;
                semctl(semid, 0, IPC_RMID); /* clean up */
                errno = e;
                return -1; /* error, check errno */
            }
        }
Run Code Online (Sandbox Code Playgroud)

这是我无法理解的.一旦semget()创建信号量并使用有效的信号量ID成功返回,信号量本身就是未初始化且处于不确定状态.这可以通过手册页确认semget.

信号量初始化

新创建的集合中的信号量值是不确定的.(POSIX.1-2001和POSIX.1-2008在这一点上是明确的,尽管POSIX.1-2008指出该标准的未来版本可能需要一个实现来将信号量初始化为0.)虽然Linux,像许多其他实现,将信号量值初始化为0,便携式应用程序不能依赖于此:它应该将信号量显式初始化为所需的值.

可以使用semctl(2)SETVAL或SETALL操作完成初始化.在多个对等体不知道谁将是第一个初始化该集合的情况下,检查由semctl(2)IPC_STAT操作检索的关联数据结构中的非零sem_otime可以用于避免竞争.

但是在上面的代码semctl()中没有调用来初始化信号量.相反,semop()sem_op= 调用1,根据手册页进行semop以下操作.

如果sem_op是正整数,则操作会将此值添加到信号量值(semval).此外,如果为此操作指定了SEM_UNDO,系统将从此信号量的信号量调整(semadj)值中减去值sem_op.此操作始终可以继续 - 它永远不会强制线程等待.调用进程必须对信号量集具有alter权限.

但没有初始化,semval是不确定的.所以添加1它仍然使它不确定.

这段代码不正确还是我的理解不正确?如果我的理解不正确,你能解释一下为什么这段代码是正确的吗?

Tim*_*Tim 5

您的理解是正确的,代码不可移植.该的POSIX.1-2008规范semget不需要旗语进行初始化:

在创建时,与新信号量标识符相关联的semid_ds数据结构初始化如下:

  • 在该操作权限结构sem_perm.cuid,sem_perm.uid, sem_perm.cgid,和sem_perm.gid应分别设置为有效用户ID和有效组ID,调用进程的.

  • 低位9位sem_perm.mode应设置为低位9位semflg.

  • 变量sem_nsems应设置为值nsems.

  • 变量sem_otime应设置为0,并sem_ctime应设置为当前时间,如IPC一般说明中所述.

  • 不需要初始化与集合中的每个信号量相关联的数据结构.的semctl()与该命令SETVAL或SETALL功能可用于初始化每个信号量.

  • 应该注意的是,"不需要初始化"并不意味着,禁止实现它的初始化.因此,发布的代码可能只是一直工作,因为它总是在系统上运行,将数据初始化为0.但下一个系统,代码被移植到,可能不会这样做,然后代码崩溃或行为不端以简单的方式. (2认同)