我需要fork一个进程,将输出(stdout和stderr)重定向到缓冲区。我的代码似乎适用于大多数二进制文件,但不是全部。例如,我可以使用ls -R/proc /这样一个非常长的“ls”来运行我的代码,并且它工作得很完美。当我运行mke2fs进程时,我的代码不再工作。当我重定向输出时,fork和wait处理不能用于mke2fs
如果我在fork中运行mke2fs并等待它,它就能正常工作。现在,如果我添加重定向的东西,我的程序永远不会完成运行。
我写了一个小主,以测试这个特定的麻烦:
#include <sys/wait.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
pid_t pid;
int status = -42;
int pipefd_out[2];
int pipefd_err[2];
char buf_stderr[1024];
char buf_stdout[1024];
int count;
int ret;
pipe(pipefd_out);
pipe(pipefd_err);
memset (buf_stdout, 0, 1024);
memset (buf_stderr, 0, 1024);
pid = fork();
if (pid == -1)
{
fprintf (stderr, "Error when forking process : /usr/sbin/mke2fs\n");
return 1;
}
if (pid == 0)
{
close(pipefd_out[0]);
close(pipefd_err[0]);
dup2(pipefd_out[1], 1);
dup2(pipefd_err[1], 2);
close(pipefd_out[1]);
close(pipefd_err[1]);
char **args;
args = malloc (sizeof (1024));
args[0] = strdup("/usr/sbin/mke2fs");
args[1] = strdup("/dev/sda4");
args[2] = strdup("-t");
args[3] = strdup("ext4");
args[4] = NULL;
execvp ("/usr/sbin/mke2fs", args);
/*
args = malloc (sizeof (1024));
args[0] = strdup("/bin/ls");
args[1] = strdup("-R");
args[2] = strdup("/proc/irq");
args[3] = NULL;
execvp ("/bin/ls", args);
*/
perror ("execv");
fprintf (stderr, "Error when execvp process /usr/sbin/mke2fs\n");
return 1;
}
close(pipefd_out[1]);
close(pipefd_err[1]);
if (waitpid(pid, &status, 0) == -1)
{
fprintf (stderr, "Error when waiting pid : %d\n", pid);
return 1;
}
do
{
count = read(pipefd_out[0], buf_stdout, sizeof(buf_stdout));
}
while (count != 0);
do
{
count = read(pipefd_err[0], buf_stderr, sizeof(buf_stderr));
}
while (count != 0);
ret = WEXITSTATUS(status);
FILE* file = NULL;
file = fopen("/root/TUTU", "w");
if (file != NULL)
{
fwrite(buf_stdout, 1, sizeof(buf_stdout), file);
fwrite(buf_stderr, 1, sizeof(buf_stdout), file);
fclose(file);
}
return 0;
}
如果我运行ps的,我可以看到我的孩子进程在运行:
# ps | grep sda4
936 root 2696 S {mke2fs} /dev/sda4 -t ext4
我无法理解为什么我有这种奇怪的行为。不知道它的相关,但mke2fs的输出是不经典的。这个过程似乎在计算过程中更新输出,而不是打印输出并提示提示。这是一种进度条。不知道我的解释是否真的很清楚。
谢谢, 伊娃。
由于父级尝试读取所有孩子的标准输出,然后读取其所有标准错误,所以仍然存在潜在的死锁。如果stderr管道在程序完成之前填满,则在母公司仍在尝试读取标准输出时,将阻止写入标准错误。 “捕获标准输出和标准错误”不是一件简单的工作。 –
@Wumpus Q. Wumbley:的确,我得到这个问题是因为我读stdout然后stderr。我想我可能会尝试使用pthread在同一时间读取它们。 – ArthurLambert