使用重定向 I/O 与子进程通信时出现死锁
Posted
技术标签:
【中文标题】使用重定向 I/O 与子进程通信时出现死锁【英文标题】:Deadlock when communicating with child process with redirected I/O 【发布时间】:2018-06-24 12:38:48 【问题描述】:我正在编写一个程序以编程方式与 SPIN 模型检查器的交互式模块进行通信。为此,我需要重定向 SPIN 的 I/O,从我的程序中启动它,然后反复读取和写入它。为了进行测试,我使用了以下只有一个输入和一个输出的短程序,而不是 spin:
#include <string>
#include <iostream>
using std::cin;
using std::cout;
using std::string;
void sprint(string s);
int main()
std::string s = "empty";
cin >> s;
cout << "\n\tthe text is: " << s;
return 0;
我的程序,主要来自this answer,是:
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <cstring>
#include <unistd.h>
#include <errno.h>
#include <iostream>
#define PIPE_READ 0
#define PIPE_WRITE 1
#define maxReadSize 2048
using std::cout;
using std::cin;
using std::string;
int createChild(const char* szCommand, const char* aArguments, const char* szMessage);
int main()
createChild("./inout" , "inout", "hello");
return 0;
int createChild(const char* szCommand, const char* aArguments, const char* szMessage)
int cStdinPipe[2];
int cStdoutPipe[2];
int nChild;
char nChar;
int nResult;
if (pipe(cStdinPipe) < 0)
return -1;
if (pipe(cStdoutPipe) < 0)
close(cStdinPipe[PIPE_READ]);
close(cStdinPipe[PIPE_WRITE]);
return -1;
nChild = fork();
if (0 == nChild)
// child continues here
cout.flush();
close(cStdinPipe[PIPE_WRITE]);
// redirect stdin
if (dup2(cStdinPipe[PIPE_READ], STDIN_FILENO) == -1)
exit(errno);
// redirect stdout
if (dup2(cStdoutPipe[PIPE_WRITE], STDOUT_FILENO) == -1)
exit(errno);
// all these are for use by parent only
close(cStdinPipe[PIPE_READ]);
close(cStdoutPipe[PIPE_READ]);
close(cStdoutPipe[PIPE_WRITE]);
// run child process image
nResult = execlp(szCommand, aArguments, NULL);
// if we get here at all, an error occurred, but we are in the child
// process, so just exit
exit(nResult);
else if (nChild > 0)
// parent continues here
string messageFromChild = "";
string messageFromParent = "";
char readBuffer[maxReadSize];
int bytesWritten = 0;
int bytesRead = 0;
// close unused file descriptors, these are for child only
close(cStdinPipe[PIPE_READ]);
close(cStdoutPipe[PIPE_WRITE]);
// write to child
if (NULL != szMessage)
bytesWritten = write(cStdinPipe[PIPE_WRITE], szMessage, strlen(szMessage));
// read from child
bytesRead = read(cStdoutPipe[PIPE_READ], readBuffer, maxReadSize);
cout << "\nChild says: " << readBuffer << "\n";
// done with these in this example program, you would normally keep these
// open of course as long as you want to talk to the child
close(cStdinPipe[PIPE_WRITE]);
close(cStdoutPipe[PIPE_READ]);
std::cout << "\n\nParent ending";
else
// failed to create child
close(cStdinPipe[PIPE_READ]);
close(cStdinPipe[PIPE_WRITE]);
close(cStdoutPipe[PIPE_READ]);
close(cStdoutPipe[PIPE_WRITE]);
return nChild;
运行此程序会导致死锁,其中子进程卡在cin
上,而父进程卡在read()
上。删除其中任何一个调用都会导致两个程序运行到终止并正常退出。 write()
和 cout
都可以正常工作。
【问题讨论】:
现在卡在select()
【参考方案1】:
问题出在read()
和write()
如何处理各种流/文件/管道。我的write()
无法与已完成写入的read()
通信。 Read()
依赖于 EOF
,它仅在管道的写入端关闭后发送。当然,一旦关闭,它就永远消失了,我无法重新打开它来发送另一条消息。
因此,我切换到命名管道 (fifo
),以便在每次写入后重新打开管道。
【讨论】:
以上是关于使用重定向 I/O 与子进程通信时出现死锁的主要内容,如果未能解决你的问题,请参考以下文章