在fork之后,父进程和子进程是否共享通过管道创建的文件描述符?

12
int main()
{
    int data_processed;
    int file_pipes[2];
    const char some_data[] = "123";
    char buffer[BUFSIZ + 1];
    pid_t fork_result;

    memset(buffer, '\0', sizeof(buffer));

    if (pipe(file_pipes) == 0) {
        fork_result = fork();
        if (fork_result == -1) {
            fprintf(stderr, "Fork failure");
            exit(EXIT_FAILURE);
        }

// We've made sure the fork worked, so if fork_result equals zero, we're in the child process.

        if (fork_result == 0) {
            data_processed = read(file_pipes[0], buffer, BUFSIZ);
            printf("Read %d bytes: %s\n", data_processed, buffer);
            exit(EXIT_SUCCESS);
        }

// Otherwise, we must be the parent process.

        else {
            data_processed = write(file_pipes[1], some_data,
                                   strlen(some_data));
            printf("Wrote %d bytes\n", data_processed);
        }
    }
    exit(EXIT_SUCCESS);
}

据我理解,由fork创建的子进程不与其父进程共享变量。那么,为什么这里父进程可以写入一个文件描述符,并且子进程可以通过读取另一个文件描述符来获取数据呢?这是因为它们在内部由pipe函数进行控制吗?

3个回答

19

文件描述符,包括管道,在 fork 时会被复制 -- 子进程最终得到与父进程相同的文件描述符表,包括标准输入/输出/错误和管道。

根据我的理解,由 fork 创建的子进程不与其父进程共享变量。

这并不完全正确 -- 对变量的更改不会与父进程共享,但是在 fork 之前父进程拥有的值在子进程之后都是可见的。

无论如何,管道存在于操作系统中,而不是进程内部。因此,写入管道一端的数据对于持有另一端 FD 的任何其他进程都是可见的。(如果多个进程尝试读取数据,则首先尝试 read() 数据的进程将获得它,其他进程则会错过。)


8

变量不是共享的,例如,如果您在子进程中写入file_pipes [0] = 999,它不会反映在父进程中。文件描述符是共享的(子进程中的FD号码x指的是与父进程中的FD号码x相同的东西)。这就是为什么(例如)您可以重定向执行其他命令的shell脚本的输出(因为它们共享相同的标准输出文件描述符)。


1

你是对的 - 普通变量并没有在父进程和子进程之间共享。

然而,管道不是变量。它们是一种特殊设计用来连接两个独立进程的伪文件。当你写入一个管道时,你并没有改变当前进程中的变量 - 你是将数据发送给操作系统,并要求它将该数据提供给下一个进程从管道中读取。

这就像当你写入真正的磁盘文件一样 - 只是数据并没有写入磁盘,而是仅在管道的另一端提供。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接