进程在读取时挂起

6
以下代码通过管道从其他进程读取消息。所有进程都正确打印出所有消息,但是它们永远不会继续执行 while 循环。尝试在 Eclipse 中进行调试,读取所有消息后,它将停止在该 while 循环处。
索引是分配给每个进程的编号。第一个进程的索引为 0。消息本身只是发送消息的进程的索引。
while((n = read(fd[index][0], &mymsg, sizeof(int))) == sizeof(int))
        printf("process%d  has received a message from process%d\n", index, mymsg);

有什么想法是为什么会发生这种情况吗?

以下是每个进程如何向另一个进程写入:

// Write to other process
if(write(fd[index2][1], &index, sizeof(int)) != sizeof(int))
    sys_error(2);

这将重复五次。fd是每个进程的读写端口的表格。


不清楚为什么这不是您预期的行为。在什么条件下,代码应该继续执行 while 循环? - David Schwartz
@DavidSchwartz 如果它没有读取任何字节或返回错误。 - sj755
你是否有特别的理由期望这些事情中的任何一个发生?如果没有,为什么它应该退出while循环?(文件描述符是非阻塞的吗?) - David Schwartz
@DavidSchwartz 每个进程通过管道向一个随机选择的进程发送5条消息。我已经发布了写入操作发生的代码。 - sj755
再问一遍,你是否有任何特别的原因认为它应该读取零字节或返回错误?我还没有听到任何理由说明它应该退出while循环。你的代码似乎正在按照编码要求执行,不断从连接中读取直到出现错误。由于没有发生错误,所以它会继续读取。(它怎么知道另一个进程不会发送消息给它呢?) - David Schwartz
@DavidSchwartz 我想这意味着真正的问题是,我该如何让我的进程知道它不会再收到另一条消息了。 - sj755
1个回答

8

调用read()函数会一直阻塞,直到有更多的数据出现。这段引用来自pipe的man手册

如果一个进程试图从空管道中读取数据,则read(2)将一直阻塞,直到有数据可用。如果一个进程试图向已满的管道中写入数据(见下文),则write(2)将一直阻塞,直到从管道中读取了足够的数据以允许写入完成。可以使用fcntl(2) F_SETFL操作启用O_NONBLOCK打开文件状态标志,从而实现非阻塞I/O。

在进入while循环之前,对每个文件描述符进行以下操作:

fcntl(fd, F_SETFL, O_NONBLOCK);

然而,你确实应该了解阻塞与非阻塞I/O,包括阅读pipe、read、fcntl等命令的手册。


我可以看一些示例代码吗?我对那个函数不太熟悉。 - sj755
@seljuq70:你试过查看fctntl手册吗?我刚刚在Google上输入了“fcntl F_SETFL O_NONBLOCK”,并且得到了一些带有示例代码的结果。无论如何,我编辑了我的答案以添加更多信息。 - kbyrd
1
@seljuq70 你如何知道进程应该何时停止阻塞?是在接收固定数量的消息后吗?是在经过一定的时间后吗?还是在接收到具有特定值的消息后呢?先决定它应该做什么,然后编写代码来实现。但看起来你不知道它应该如何知道,所以它不起作用并不令人意外。 - David Schwartz
@DavidSchwartz 它不知道会收到多少条消息。我想让每个进程做的就是打印出它将要接收到的所有消息。这就是问题所在,它不知道会接收到多少消息。 - sj755
1
@seljuq70 嗯,这正是它正在做的事情。但是,当然,该过程永远不会完成,因为它无法知道是否会收到更多的消息。您的设计没有给该进程收集此信息的可能性。您必须决定*进程将如何知道,然后您必须编写代码来实现它。但是现在,它正在执行您声称想要的操作。(它下周可能会收到另一条消息。所以它正在等待那个。) - David Schwartz
显示剩余6条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接