dup2 问题
Issue with dup2
我正在尝试一个简单的程序,其中来自子进程的 STDOUT 被定向到父进程。如果我不分叉多次并在循环中调用 child_process
和 parent_process
,该程序就可以工作。但是,当我在 fork 和 child_process
和 parent_process
周围放置一个 for 循环时,dup2
函数 returns -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
关闭管道描述符,并且不会在循环的第二次迭代中重新打开它们,因此 dup
.
没有任何内容
最简单的解决方案是将 pipe
调用移入循环。
我正在尝试一个简单的程序,其中来自子进程的 STDOUT 被定向到父进程。如果我不分叉多次并在循环中调用 child_process
和 parent_process
,该程序就可以工作。但是,当我在 fork 和 child_process
和 parent_process
周围放置一个 for 循环时,dup2
函数 returns -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
关闭管道描述符,并且不会在循环的第二次迭代中重新打开它们,因此 dup
.
最简单的解决方案是将 pipe
调用移入循环。