在不调用 semctl() 的情况下先调用 semget() 再调用 semop() 是否正确?
Is it correct to call semget() followed by semop() without calling semctl()?
我正在研究 Beej's Guide to Unix IPC 中的信号量示例程序。
示例程序包含以下信号量初始化代码。我只是从中发布与问题相关的片段。要查看完整代码,请访问我在上面提供的link。
/*
** 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()
创建信号量并且 returns 使用有效的信号量 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.
免责声明
这不应该是一个答案,但随着它不断增长,它不适合评论...
技术领域
Tim answers 你的问题在技术领域非常好(这就是 SO 的全部内容)。然而,今晚我感觉 哲学 我认为你怀疑的来源可能更微妙:我认为你的问题更多是关于 上下文和作者 比是关于代码。
一大堆个人意见
根据您发布的内容:
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.
您正在阅读标题为“Beej 的 Unix IPC 指南”的指南。当您阅读这样的标题时,应该会弹出一些非常重要的事情:
这是一个人对某事的看法 - 这是他做事的方式。具体来说,一个名叫 Brian Hall 的人的昵称是 "Beej".
它明确表示它是用于 Unix(Linux 实际上,见下文)。
如果您阅读 Beej's resume(PDF),您会发现从他所掌握的知识领域来看,他不是一个简单的程序员。他是一个 修补匠 ,修补匠为所欲为。这就是为什么他们是聪明人 - 他们犯了很多错误,因此,他们比其他人学到了很多东西。
因此,作者可以做任何他想做的事,也可以在论文中写任何他想写的东西——包括使用特定平台 features/bugs/traps/standards/etc。有一个 part in the article 明确告诉您文章的 POSIXey 性质和编译此代码的平台 运行 :
1.1. Audience
If you know C or C++ and are pretty good using a Unix environment (or other POSIXey environment that supports these system calls) these documents are for you.
(...)
1.2. Platform and Compiler
The examples in this document were compiled under Linux using gcc. They should compile anywhere a good Unix compiler is available.
再次,更多的个人意见:他说他正在使用 Linux 和 gcc。因此,标题可以改写为:
不可靠的黑客指南 Linux 使用 GCC 进行 IPC 编程
这听起来很像 Rusty Russell 的文章标题! (顺便说一句,另一个修补匠)。反正这样的标题,你真的会关心POSIX吗?
我正在研究 Beej's Guide to Unix IPC 中的信号量示例程序。
示例程序包含以下信号量初始化代码。我只是从中发布与问题相关的片段。要查看完整代码,请访问我在上面提供的link。
/*
** 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()
创建信号量并且 returns 使用有效的信号量 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
, andsem_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 ofsemflg
.The variable
sem_nsems
shall be set to the value ofnsems
.The variable
sem_otime
shall be set to 0 andsem_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.
免责声明
这不应该是一个答案,但随着它不断增长,它不适合评论...
技术领域
Tim answers 你的问题在技术领域非常好(这就是 SO 的全部内容)。然而,今晚我感觉 哲学 我认为你怀疑的来源可能更微妙:我认为你的问题更多是关于 上下文和作者 比是关于代码。
一大堆个人意见
根据您发布的内容:
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.
您正在阅读标题为“Beej 的 Unix IPC 指南”的指南。当您阅读这样的标题时,应该会弹出一些非常重要的事情:
这是一个人对某事的看法 - 这是他做事的方式。具体来说,一个名叫 Brian Hall 的人的昵称是 "Beej".
它明确表示它是用于 Unix(Linux 实际上,见下文)。
如果您阅读 Beej's resume(PDF),您会发现从他所掌握的知识领域来看,他不是一个简单的程序员。他是一个 修补匠 ,修补匠为所欲为。这就是为什么他们是聪明人 - 他们犯了很多错误,因此,他们比其他人学到了很多东西。
因此,作者可以做任何他想做的事,也可以在论文中写任何他想写的东西——包括使用特定平台 features/bugs/traps/standards/etc。有一个 part in the article 明确告诉您文章的 POSIXey 性质和编译此代码的平台 运行 :
1.1. Audience
If you know C or C++ and are pretty good using a Unix environment (or other POSIXey environment that supports these system calls) these documents are for you.
(...)
1.2. Platform and Compiler
The examples in this document were compiled under Linux using gcc. They should compile anywhere a good Unix compiler is available.
再次,更多的个人意见:他说他正在使用 Linux 和 gcc。因此,标题可以改写为:
不可靠的黑客指南 Linux 使用 GCC 进行 IPC 编程
这听起来很像 Rusty Russell 的文章标题! (顺便说一句,另一个修补匠)。反正这样的标题,你真的会关心POSIX吗?