Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/62.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C Semop:当减少一组信号量时,所有信号量都会立即减少,还是在第一次失败时会阻塞?_C_Unix_Semaphore - Fatal编程技术网

C Semop:当减少一组信号量时,所有信号量都会立即减少,还是在第一次失败时会阻塞?

C Semop:当减少一组信号量时,所有信号量都会立即减少,还是在第一次失败时会阻塞?,c,unix,semaphore,C,Unix,Semaphore,因此,如果我有一个信号量集semid,带有num\u of sems信号量和一个sembuf*deleter\u searchers\u down struct sembuf *deleter_searchers_down = malloc(sizeof (*deleter_searchers_down) * num_of_sems); for (i = 0; i < num_of_sems; ++i) { (del

因此,如果我有一个信号量集
semid
,带有
num\u of sems
信号量和一个sembuf
*deleter\u searchers\u down

struct sembuf *deleter_searchers_down 
                        = malloc(sizeof (*deleter_searchers_down) * num_of_sems);
for (i = 0; i < num_of_sems; ++i) {
            (deleter_searchers_down + i)->sem_op = -1;
            (deleter_searchers_down + i)->sem_num = i;
            (deleter_searchers_down + i)->sem_flg = SEM_UNDO;
        }
semop(semid, deleter_searchers_down, num_of_sems);
struct sembuf*deleter\u searchers\u down
=malloc(sizeof(*删除搜索者)*总搜索数);
对于(i=0;isem\u op=-1;
(删除搜索者向下+i)->sem\u num=i;
(删除搜索者向下+i)->sem\u flg=sem\u UNDO;
}
semop(semid、删除搜索者、SEM数量);

对semop的调用将尝试一次降低集合中的所有信号量,或者在尝试降低第一个信号量(0)并在其他一些进程之后继续该特定信号量时,它将阻塞?

在所有更新都可以作为一个整体进行之前,不会发生任何更新

POSIX规范可以更清楚地说明这一点,尽管它确实说
semop
是原子的

在Linux上,glibc中的
semop(3)
semop(2)
的简单包装器。
semop(2)
手册页依次显示

sop
中包含的一组操作是按数组顺序执行的,并且是原子式的,也就是说,这些操作要么作为一个完整的单元执行,要么根本不执行

HP-UX
semop(2)
手册页更加清晰:

信号量 数组操作是原子的,因为没有任何信号量操作 将一直执行,直到中的所有信号量上出现阻塞条件为止 阵列已被删除


信号量完全按照你说的做,也就是说,当信号量降低时,如果信号量为0,则会阻止进程。请仔细阅读问题-semop会尝试降低所有的集合并阻止所有的零一,还是会阻止第一个(第一个?)遇到0你可以指定IPC_NOWAIT在失败时立即返回。请参阅:@RedX链接相关,IPC_NOWAIT不相关。问题是,是否立即执行了阵列中不导致阻塞的操作之一,或者是否延迟了该操作,并且在解除阻塞进程时一次完成所有操作(导致阵列中稍后的操作之一首先导致阻塞)谢谢-这是否意味着尝试关闭semid的进程将阻塞第一个数组元素0,并且semop()将撤消所有以前的数组元素down()?这取决于实现。例如,LinuxIPC/sem.c(function
try\u atomic\u semop
)中的代码与您描述的类似。它将尝试这些操作,如果其中任何一个操作被阻止,更改将被撤消。但有一点很重要:更新是在保持信号量集上的锁的同时完成的。因此,不一致状态对任何其他任务都是不可见的:希望更改信号量的任务必须首先获取锁,并且在信号量上阻塞的任务已经处于休眠状态。因此,最终操作是真正的原子操作。好的-谢谢-最后一点:调用semop的进程不可能(实现)阻止所有0的信号量?我不确定我是否正确理解了这个问题,请随意更正。如果多个信号量为0且无法获取,则对
semop
的调用将被阻止,直到这成为可能<代码>semop在整个操作完成之前不会返回。如果您的问题是关于浪费CPU时间,那么在最近的Linux内核中,当在信号量等待队列中时,任务是不可调度的:当另一个任务调用
semop
并更改信号量集时,它将休眠并被唤醒。我的意思是,调用semop的进程是否可能(如给出的示例所示)阻止所有为0的信号量-这不仅仅是在它遇到的第一个(按数组顺序)为0的信号量上。因此,与其撤消操作以阻止所有为0的对象并等待所有对象,不如在所有对象都可用时,不重做,而只是返回。但这与信号量的作用相矛盾(如果在semid中有其他进程升级sem,很容易想到反例)。