gpt4 book ai didi

c - 使用 UNIX 管道进行进程同步-饥饿

转载 作者:太空宇宙 更新时间:2023-11-04 03:58:08 25 4
gpt4 key购买 nike

通过使用 UNIX 管道进行进程同步,我们是否会陷入饥饿?例如:

void pipesem_wait(struct pipesem *sem)
{
char onebyte = 'A';
if ( read( sem->rfd, &onebyte, sizeof( onebyte ) ) != sizeof( onebyte ) ) {
perror( "read from pipe" );
exit( 1 );
}
}

这就是我们从管道中读取的方式..当多个进程想要从这个管道读取时,是否确定所有请求都将以特定的(例如 FIFO)顺序处理,或者即使它可能永远不会发生,仍然有可能出现饥饿?

最佳答案

您不能保证多个读取进程中的哪一个会读取数据,但您可以保证恰好其中一个进程会读取每个字节。管道实际上只是内核中的共享缓冲区,具有不同的文件句柄来读取和写入它 - 如果多个进程共享这些句柄,则由调度程序决定哪个进程获取数据。

因此,如果您的意思是饥饿,因为在一个或多个进程中不会读取任何数据,那很有可能 - 如果数据写入速度足够慢,以至于一个进程可以像写入数据一样快地消耗它,那么其他进程可能看不到任何数据。另一方面,它可能会在所有进程之间进行循环——这只取决于调度是如何发生的。您不能依赖任何一种情况,行为可能取决于 Unix 风格,甚至是该风格的版本和运行它的硬件。

但是,您可以相信所有数据都已被消耗而不会丢失任何数据,并且您可以相信数据会以 FIFO 顺序读出。但是,假设写入 "ABC" 完成,进程 1 读取它,然后写入 "DEF" 完成,进程 2 读取它。无法保证这些进程将被调度,以便进程 1 在进程 2 之前完成处理其输入。因此,尽管从管道读取数据的顺序是 FIFO,但之后又取决于进程的调度方式。

正如下面的第一位评论者所指出的,还值得一提的是,只要您在 PIPE_BUF 下方编写值(value),对管道的 write() 调用就是原子的数据(例如,在我的 Linux 系统上是 512 字节 - 在 limits.h 中检查你的等价物)。这保证了数据 block 不会与写入同一管道的任何其他进程的数据交错。如果您超出此限制,则标准不会指定 write() 是否是原子的。还要记住,对于大块数据,您可能会得到部分写入,您应该始终处理这种情况。参见 the SO question and answer that the commenter linked获取更多信息。

但是,您似乎一次一个字节地读取数据,所以我推测您也一次只写入一个字节并将其用作某种进程同步机制。您可能想考虑使用带有 pthreads 条件变量的共享内存,这可能是实现相同目标的更优雅的方式 - 我有一些旧的演示代码,我有 put online here .

注意:如果可移植性对您很重要,那么您可能希望坚持使用管道 - 我怀疑它们更有可能在最广泛的平台上工作。 pthreads 方法应该是相当可移植的,但共享内存可能不那么便携。

简而言之,如果您使用它来从池中唤醒工作进程并且您不关心使用的是哪个进程,则管道可以作为一种 IPC 机制正常工作。但是,如果您希望唤醒一个特定的进程,则需要为每个工作人员使用一个管道或其他一些机制。例如,使用 pthreads 条件变量,您可以通过调用 pthread_cond_broadcast() 而不是 pthread_cond_signal() 来唤醒等待的每个 进程。

这是否回答了您的问题?

关于c - 使用 UNIX 管道进行进程同步-饥饿,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14611901/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com