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

时间:2011-07-11 03:47:38

标签: c linux multithreading ubuntu-10.04

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创建的子进程不与其父进程共享变量。然后,为什么父母可以写入一个文件描述符,子进程可以通过读取另一个文件描述符来获取数据。这是因为它们是由内部的管道功能以某种方式控制的吗?

3 个答案:

答案 0 :(得分:17)

文件描述符(包括管道)在fork上重复 - 子进程以相同的文件描述符表结束,包括stdin / out / err和管道,因为父进程在fork之前。

  

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

这并不完全正确 - 变量的更改不会与父项共享,但父项之后父项所拥有的值对孩子来说都是可见的。

在任何情况下,管道都存在于操作系统内,而不在进程内。因此,写入管道一端的数据对于另一端持有FD的任何其他过程都是可见的。 (如果多个进程尝试读取数据,则尝试read()数据的第一个进程会获取该数据,并且任何其他进程都会丢失。)

答案 1 :(得分:5)

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

答案 2 :(得分:1)

你是对的 - 普通变量不是在父母和孩子之间共享。

但是,管道不是变量。它们是专门用于将两个独立进程连接在一起的伪文件。当您写入管道时,您不会更改当前进程中的变量 - 您将数据发送到操作系统并要求它将该数据提供给下一个进程以从管道读取。

就像你写一个真实的磁盘文件一样 - 除了数据没有写入磁盘之外,它只是在管道的另一端可用。