[英]Issue with dup2
我正在尝试一个简单的程序,其中来自子进程的 STDOUT 被定向到父进程。 如果我不分叉多次并在循环中调用child_process
和parent_process
,该程序就可以工作。 但是,当我在 fork 和child_process
和parent_process
周围放置一个 for 循环时, dup2
function 返回-1
,因此程序失败。 我究竟做错了什么?
此代码在child_process
和parent_process
周围有一个for
循环,并且与dup2
有问题
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#define BUFSIZE 256
void child_process(int pipe_pair[2]){
// closes the child's STDOUT descriptor and replaces it with
// the write pipe linked to the parent's read pipe
if (dup2(pipe_pair[1], STDOUT_FILENO) == -1){
// if dup2 fails, perror writes to stderr so this reports
// appropriately either way as the child and parent share stderr
perror("dup2");
// parent will know if the child failed since we return 1
// (ideally return errno so that calling processes know the error code)
exit(EXIT_FAILURE);
}
// duplicated by dup2 above, no longer needed
close(pipe_pair[1]);
// close read end as we will never read from stdout
close(pipe_pair[0]);
// printf writes to stdout by default
// we could also use fprintf(stdout, ...)
printf("Hello, parent!\n");
// make sure the write buffer is flushed before we exit
fflush(stdout);
// close to make sure read() returns 0 in the parent
close(STDOUT_FILENO);
// child exits
exit(EXIT_SUCCESS);
}
void parent_process(int pipe_pair[2], pid_t cpid){
// cstatus will store the return of the child process
// buf will hold the child's writes to stdout --
// {0} initializes the array elements to 0x00
int cstatus;
char buf[BUFSIZE] = {0};
close(pipe_pair[1]); // we won't write to stdout
// read until closed, or error (0 or -1, respectively)
for (int n = 0; (n = read(pipe_pair[0], buf, BUFSIZE)) > 0;){
printf("Received %d bytes from child process: ", n);
// (needed otherwise write() may output before
// printf since stdio output to stdout is line buffered)
fflush(stdout);
// writes just what we read so no need to reset buf
write(STDOUT_FILENO, buf, n);
printf("\n");
fflush(stdout);
}
// close read pipe
close(pipe_pair[0]);
// waits for child process with pid 'cpid' to
// return and stores the exit code in cstatus
waitpid(cpid, &cstatus, 0);
printf("Child exit status was: %d\n", cstatus);
// terminate parent
//exit(EXIT_SUCCESS);
}
int main(int argc, char **argv){
// cpid stores the process id of the child process
// stdout_pipe array = pipe descriptor pair --
// [0] is the read end, [1] is the write end
pid_t cpid;
int stdout_pipe[2];
// call that creates the two unidirectional pipe streams
// and stores the descriptors in the array
if (pipe(stdout_pipe) == -1){
perror("pipe");
exit(EXIT_FAILURE);
}
// fork happens here, cpid will have the child's
// process id or -1 if the call fails
for (int i=0; i<3; i++) {
cpid = fork();
if (cpid == -1){
perror("fork");
exit(EXIT_FAILURE);
}
// child (fork returns 0 in the child and the child ID for the parent)
if (cpid == 0)
child_process(stdout_pipe);
// else when cpid is not 0 or -1 we're in the parent
else
parent_process(stdout_pipe, cpid);
}
// we shouldn't get here, but return int from main for correctness
return 0;
}
问题是这个块在循环之外:
if (pipe(stdout_pipe) == -1){
perror("pipe");
exit(EXIT_FAILURE);
}
第一次调用parent_process
会关闭 pipe 描述符,并且不会为循环的第二次迭代重新打开它们,因此没有什么可以dup
。
最简单的解决方案是将pipe
调用移入循环。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.