子进程被满管道阻塞,无法读取父进程
Child process is blocked by full pipe, cannot read in parent process
我大致创建了以下代码来调用子进程:
// pipe meanings
const int READ = 0;
const int WRITE = 1;
int fd[2];
// Create pipes
if (pipe(fd))
{
throw ...
}
p_pid = fork();
if (p_pid == 0) // in the child
{
close(fd[READ]);
if (dup2(fd[WRITE], fileno(stdout)) == -1)
{
throw ...
}
close(fd[WRITE]);
// Call exec
execv(argv[0], const_cast<char*const*>(&argv[0]));
_exit(-1);
}
else if (p_pid < 0) // fork has failed
{
throw
}
else // in th parent
{
close(fd[WRITE]);
p_stdout = new std::ifstream(fd[READ]));
}
现在,如果子进程没有向标准输出写入太多内容,我可以等待它完成,然后从p_stdout
读取标准输出。如果写入太多,则写入阻塞,父进程将永远等待它。为了解决这个问题,我试图在父进程中等待WNOHANG
,如果它没有完成,使用readsome
从p_stdout读取所有可用的输出,睡一点,然后再试一次。不幸的是,readsome
从不读取任何内容:
while (true)
{
if (waitid(P_PID, p_pid, &info, WEXITED | WNOHANG) != 0)
throw ...;
else if (info.si_pid != 0) // waiting has succeeded
break;
char tmp[1024];
size_t sizeRead;
sizeRead = p_stdout->readsome(tmp, 1024);
if (sizeRead > 0)
s_stdout.write(tmp, sizeRead);
sleep(1);
}
问题是:为什么这不能工作,我如何解决它?
edit:如果只有子进程,简单地使用read
而不是readsome
可能会工作,但是该进程有多个子进程,并且需要在其中一个终止时立即做出反应。
正如sarnold建议的那样,您需要更改调用的顺序。先阅读,后等待。即使你的方法有效,你也可能错过最后的阅读。也就是说,在读取最后一组写入的字节之前退出循环。
问题可能是ifstream是非阻塞的。我从来都不喜欢iostreams,即使在我的c++项目中,我总是喜欢C的studio函数的简单性(例如FILE*, fprintf等)。解决这个问题的一种方法是读取描述符是否可读。您可以使用select来确定该管道上是否有数据等待。如果你要从多个子节点读取数据,你将需要select,所以最好现在就学习它。
对于一个快速的可读函数,尝试这样做(请注意,我没有尝试编译这个):
bool isreadable(int fd, int timeoutSecs)
{
struct timeval tv = { timeoutSecs, 0 };
fd_set readSet;
FD_ZERO(&readSet);
return select(fds, &readSet, NULL, NULL, &tv) == 1;
}
然后在父代码中,做如下操作:
while (true) {
if (isreadable(fd[READ], 1)) {
// read fd[READ];
if (bytes <= 0)
break;
}
}
wait(pid);
我建议重写代码,直到在管道上调用 read(2)
返回0
以表示文件结束时,它才调用waitpid(2)
。一旦你从你的read调用中得到文件结束返回值,你就知道子进程已经死亡了,你最终可以为它waitpid(2)
了。
SIGCHLD
信号处理程序中异步执行等待调用。
相关文章:
- 在进程中对同一管道进行读取和写入时C++管道出现问题
- 如何读取特定地址的进程内存?
- 如何使用带有矢量的 winapi 读取进程内存从另一个进程读取缓冲区?
- 读取进程内存多级指针(DLL 注入)
- 读取进程内存作弊引擎值
- c++ 读取进程内存基址 + 偏移量不起作用
- 内核模式驱动程序可以在任何进程上执行读取进程内存吗?
- C++ - 读取进程内存到缓冲区,写入进程内存(同一缓冲区上的新值)将缓冲区恢复为旧值
- 读取进程内存 C++ 不会读取
- C++如何使用读取进程内存查找进程内存中使用的最后一个(偏移量 - 地址)
- 读取进程内存无法正常工作,使用 UTF16 字符串
- 读取进程C++的内存
- 读取进程内存上的错误 299
- 读取进程内存问题未更新
- 读取进程内存更快
- 进程的读取进程内存不会返回所有内容
- C++ 读取进程内存到字符 * 替代
- 函数读取进程内存不断返回ERROR_PARTIAL_COPY
- 使用Blackbone读取进程内存
- 读取C++进程内存