【问题标题】:Why does my program freeze in the middle of a pipe read?为什么我的程序在管道读取过程中冻结?
【发布时间】:2011-10-12 01:15:28
【问题描述】:

我正在为需要一组 N 个子进程在基于 Unix 的系统上与其父进程通信的类编写 C++ 程序。为此,我在 fork 进程之前声明了两个由 N 个管道组成的数组,一个用于每个通信方向:

int pipesToParent[N][2];
int pipesToChild[N][2];

... // for int i = 0 to N-1, pipe(pipesToParent[i]), pipe(pipesToChild[i]),
    // fork(), yada yada, I included error checking and everything.

int pipesToChild[N][2];

父进程的大部分代码都在一个while循环中;在这个循环的开始附近,它从特定进程中读取一条消息:

read(pipesToParent[processToServe][READ_END], charArray, BUF_SIZE);

它第一次通过循环,从进程 X 读取消息,它工作正常。然后它被指示对进程 Y 执行相同的操作,其中的消息包含与进程 X 完全相同类型的数据(我让每个进程在将其写入其管道时计算其消息),然后该进程就停止了。它没有退出,它只是在那条线上保持冻结状态。我已经尝试了我能想到的一切来弄清楚我发送的消息可能有什么问题,但看起来一切都很好。这是怎么回事?

(对不起,如果我的详细信息不充分;我不知道我还必须包括什么以及我可以删除哪些内容以粘贴会重现问题的内容。)

预计到达时间:

子进程有自己的内部while循环,它从自己的管道中读取:

read(pipesToChild[thisProcessNumber][READ_END], charArray, BUF_SIZE);

如果父母准备好了,它会发送消息:

write(pipesToParent[thisProcessNumber][WRITE_END], message, BUF_SIZE);

一些修补表明,进程 Y 与父进程非常相似,一次正常地通过此循环,然后在第二次读取时卡住了。冲洗究竟会做什么,如果我以这种方式写入/读取管道,我可以这样做吗? (如果相关,我已经#included cstdlib,但不是 cstdio。)

【问题讨论】:

  • 要么你没有正确设置你的管道,要么进程 Y 没有真正写入数据,要么你有一个deadlock,或者其他错误。没有更多代码很难确定。
  • 可能是进程 Y 出于某种原因没有向管道写入消息。从管道读取的进程将在等待数据显示在管道中时阻塞。我会确保 Y 真的在写入管道。
  • 来自手册页,“请注意,默认情况下,输出 popen() 流是完全缓冲的。”写完后你 fflush() 吗?
  • 我对使用类似数组的 C++ 设计持怀疑态度。您可能应该考虑每个进程都有一个与之关联的包含相关管道信息的结构,然后使用该结构的数组。除非在您的 C++ 课程中使用结构/类还为时过早,否则人们会想知道它们是如何教您的。
  • 由于我们看不到您是如何设置孩子的,以及您是否关闭了足够多的文件描述符,因此很难通过远程控制来诊断您的问题。冻结可能是因为您的父进程正在从一个打开的文件描述符中读取,但该文件描述符不是 Y 写入其数据的那个。

标签: c++ pipe


【解决方案1】:

对我来说似乎是死锁 - 你的两个进程都在等待另一个进程 写一些东西——但他们都没有真正写任何东西,所以一切都停止了。确保您的通信设计是无死锁的(例如,客户端持续刷新并仅在读取 READY 通信时写入,而服务器仅在写入 READ 通信后读取)。您也可以考虑使用非阻塞管道。

据我所知,使用 pipe() 调用创建的管道是无缓冲的——唯一涉及的缓冲区是管道缓冲区,但由于这是在目标应用程序中完成读取的同一个缓冲区,因此它不会产生通信问题。仅当您将文件描述符映射到类似 C 的 FILE 指针时才会发生应用程序级别,但似乎并非如此。

如果您仍然认为一切正常,请发布显示此行为的最小可编译代码,以便我可以说更多。

编辑:

既然您接受了答案,如果您还提到哪个解决方案(如果有)解决了您的问题,那就太好了。

【讨论】:

  • 对不起,我直到这么晚才回复。原来我正在阅读一个 ifstream 正在搞砸其他事情的地方。我找到了一种不同的方法来检查程序当时正在做的事情,问题就解决了。 (对不起,如果这令人困惑。-_-)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-03-03
相关资源
最近更新 更多