vfork() 与 pipe() 的用法

vfork() usage with pipe()

我从手册页了解到 vfork() 子进程使用与父进程相同的资源。

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
        int     fd[2], nbytes;
        pid_t   childpid;
        char    string[] = "Hello, world!\n";
        char    readbuffer[80];

        pipe(fd);

        if((childpid = vfork()) == -1)
        {
                perror("fork");
                exit(1);
        }

        if(childpid == 0)
        {
                /* Child process closes up input side of pipe */
                close(fd[0]);

                /* Send "string" through the output side of pipe */
                write(fd[1], string, (strlen(string)+1));
                exit(0);
        }
        else
        {
                /* Parent process closes up output side of pipe */
                close(fd[1]);

                /* Read in a string from the pipe */
                nbytes = read(fd[0], readbuffer, sizeof(readbuffer));
                printf("Received string: %s", readbuffer);
        }

        return(0);
}

据我了解

close(fd[0]); // In child
write(fd[1], string, (strlen(string)+1));

上面的代码行在子进程中应该导致 error no 13 SIGPIPE 因为我们正在关闭管道 read end fd[ 0]。但这并没有发生 安装输出是 Received string: Hello, world! 谁能给我解释一下原因吗?

vfork() function was part of POSIX 2004, but is not part of POSIX 2008, which is the current edition (aka POSIX 2016)。 vfork() 能做的事情非常非常有限。手册说:

The vfork() function shall be equivalent to fork(), except that the behavior is undefined if the process created by vfork() either modifies any data other than a variable of type pid_t used to store the return value from vfork(), or returns from the function in which vfork() was called, or calls any other function before successfully calling _exit() or one of the exec family of functions.

您不能从 child 调用 close();你不能打电话给 write().

TL;DR — 不要使用 vfork()

如果您对界面的复杂性感到勇敢和满意,您可以研究 posix_spawn() 函数及其从 posix_spawn_ 开始的 20 多个函数的支持团队。 OTOH,经典 Unix 的“fork() 然后在 child 中执行操作”范例有很多优点;它比 posix_spawn 函数更容易理解,最终也更灵活。也不是所有平台都必须实现 posix_spawn()