我的教授有一个函数的示例代码,该函数通过 fork 来充当管道。但他如何确保父进程在子进程之前执行,而不必使用互斥体呢?
void
runpipe(int pfd[])
{
int pid;
switch (pid = fork()) {
case 0: /* child */
dup2(pfd[0], 0);
close(pfd[1]); /* the child does not need this end of the pipe */
execvp(cmd2[0], cmd2);
perror(cmd2[0]);
default: /* parent */
dup2(pfd[1], 1);
close(pfd[0]); /* the parent does not need this end of the pipe */
execvp(cmd1[0], cmd1);
perror(cmd1[0]);
case -1:
perror("fork");
exit(1);
}
}
最佳答案
通常, child 先跑还是 parent 先跑并不重要。
如果父级 execvp()
首先开始写入管道,一旦管道变满,写入就会阻塞,直到子级读取一些数据。
如果子级 execvp()
首先开始从管道读取,则读取同样会阻塞,直到父级写入一些数据。
顺便说一句,父进程将在 fork()
之后首先在现代 Linux 内核(例如 3.16.0)上运行,尽管不应依赖这一点。 (此外,父级的时间片可能会在 fork()
之后用完,看起来像是子级先运行。)某些 2.4 内核反而先运行子级。
子级关闭管道的写入端而父级关闭管道的读取端的原因是为了确保管道的每一端只有一个文件描述符保持打开状态。 (请记住,fork(2)
会复制文件描述符。)这意味着一旦父级关闭写入端,子级将看到文件结尾。如果子进程关闭读取端,并且父进程随后尝试写入管道,则父进程将收到 SIGPIPE
。
关于c - 为什么这个 Forking 示例不需要互斥锁?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29104479/