c - 在不调用 semctl() 的情况下先调用 semget() 再调用 semop() 是否正确?

标签 c ipc semaphore

我正在研究 Beej's Guide to 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 */
            }
        }

这是我无法理解的。一旦 semget() 创建信号量并使用有效的信号量 ID 成功返回,信号量本身就未初始化并处于不确定状态。 semget 的手册页证实了这一点。

Semaphore initialization

The values of the semaphores in a newly created set are indeterminate. (POSIX.1-2001 and POSIX.1-2008 are explicit on this point, although POSIX.1-2008 notes that a future version of the standard may require an implementation to initialize the semaphores to 0.) Although Linux, like many other implementations, initializes the semaphore values to 0, a portable application cannot rely on this: it should explicitly initialize the semaphores to the desired values.

Initialization can be done using semctl(2) SETVAL or SETALL operation. Where multiple peers do not know who will be the first to initialize the set, checking for a nonzero sem_otime in the associated data structure retrieved by a semctl(2) IPC_STAT operation can be used to avoid races.

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

If sem_op is a positive integer, the operation adds this value to the semaphore value (semval). Furthermore, if SEM_UNDO is specified for this operation, the system subtracts the value sem_op from the semaphore adjustment (semadj) value for this semaphore. This operation can always proceed—it never forces a thread to wait. The calling process must have alter permission on the semaphore set.

但是如果没有初始化,semval 是不确定的。因此,向其添加 1 仍然会使它不确定。

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

最佳答案

你的理解是正确的,代码不可移植。 POSIX.1-2008 specification of semget不需要初始化信号量:

Upon creation, the semid_ds data structure associated with the new semaphore identifier is initialized as follows:

  • In the operation permissions structure sem_perm.cuid, sem_perm.uid, sem_perm.cgid, and sem_perm.gid shall be set to the effective user ID and effective group ID, respectively, of the calling process.

  • The low-order 9 bits of sem_perm.mode shall be set to the low-order 9 bits of semflg.

  • The variable sem_nsems shall be set to the value of nsems.

  • The variable sem_otime shall be set to 0 and sem_ctime shall be set to the current time, as described in IPC General Description.

  • The data structure associated with each semaphore in the set need not be initialized. The semctl() function with the command SETVAL or SETALL can be used to initialize each semaphore.

关于c - 在不调用 semctl() 的情况下先调用 semget() 再调用 semop() 是否正确?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40635042/

相关文章:

c - ? : unexpected behaviour - although condition is true, ?部分未执行

c - 基本的unix服务器-客户端IPC(消息队列)问题

python /POpen/gpg : Supply passphrase and encryption text both through stdin or file descriptor

asp.net - 负载平衡的 ASP.NET Web 应用程序中的跨服务器通信

Python2.6.5 : Is there python equivalent of Java Semaphore tryAcquire

c - 如何检测 C 中的 sem_open 错误

c - Eclipse CDT 预处理器在条件下获取语句

c - 有没有办法在C中列出所有当前正在运行的进程

c - 为什么这个程序有不同的结果,temp=*a 和 *a= temp 不是同一件事吗?

C++ 持有多个线程