c - 为什么这个 Forking 示例不需要互斥锁?

标签 c pipe exec fork dup2

我的教授有一个函数的示例代码,该函数通过 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/

相关文章:

c# - 从 C 包含文件生成 C# 包装器

c - 为什么将取消引用的指针推送到 Stack 输出 null 在这里?

linux - 如何从文件传递命令行参数

pipe - 如何在管道命令行中使用第一个程序的返回码

android - 使用 getRuntime().exec() 命令执行 ffmpeg 命令

c - 如何读取空白分隔的信息,包括一个可能有空白的字段?

c - 是否有一种干净的可移植方式来处理 "build"包含文件名

bash - 我如何在 Bash 中添加流?

grails - groovy的ProcessGroovyMethods(UNIXProcess)导致的错误结果

c - 如何用C代码编写shell '&'?