我尝试让2个过程的孩子进行交流:
void demo() {
int pipes[2];
int create_pipe_status = pipe(pipes);
int status;
pid_t fork_id = fork();
if(!fork_id) {
//parent
status = dup2(pipes[1], STDOUT_FILENO);
close(pipes[0]);
close(pipes[1]);
}
pid_t fork_id2 = fork();
if(!fork_id2){
//child
status = dup2(pipes[0], STDIN_FILENO);
close(pipes[0]);
close(pipes[1]); //keep
}
wait(NULL);
wait(NULL);
}
当我尝试关闭与管道关联的文件描述符时,出现错误EBADF
(错误的文件描述符)errno
。
我怎么了
首先,现有流程调用fork()
,然后此原始流程及其派生的子fork()
流程再次调用,总共产生四个流程。即,这些过程是:
fork()
。fork()
。fork()
。结果,代码块(即第二个if
块)由子进程的子进程执行:
if(!fork_id2){
//child
status = dup2(pipes[0], STDIN_FILENO);
close(pipes[0]);
close(pipes[1]);
}
子进程的此子进程尝试关闭pipe[0]
并关闭pipe[1]
。但是,子进程(即子进程的子进程的父进程)已经关闭pipe[0]
和pipe[1]
。这就是错误的文件描述符错误的来源,即两次关闭文件描述符。
请注意,即使原始进程的第二个子进程也执行了此代码块,它也不会受到此问题的困扰,因为原始进程fork()
在第二次调用时并未关闭管道文件描述符,因此两个文件当原始进程的第二个子描述符关闭描述符时,它们仍处于打开状态。
我猜你实际想要的是两个从现有流程中创建两个子流程。如果是这样,则仅将第二个调用限制fork()
到父进程(即原始进程):
void demo() {
int pipes[2];
int create_pipe_status = pipe(pipes);
int status;
pid_t fork_id = fork();
if (!fork_id) { // 1st child
status = dup2(pipes[1], STDOUT_FILENO);
assert(!close(pipes[0]));
assert(!close(pipes[1]));
} else {
// parent
pid_t fork_id2 = fork();
if (!fork_id2) { // 2nd child
status = dup2(pipes[0], STDIN_FILENO);
assert(!close(pipes[0]));
assert(!close(pipes[1]));
} else { // parent
assert(!close(pipes[0]));
assert(!close(pipes[1]));
}
}
wait(NULL);
wait(NULL);
}