После fork родительский и дочерний процессы совместно используют дескриптор файла, созданный pipe? - PullRequest
9 голосов
/ 11 июля 2011
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 ]

17 голосов
/ 11 июля 2011

Файловые дескрипторы, включая каналы, дублируются на fork - дочерний процесс заканчивается той же таблицей файловых дескрипторов, включая stdin / out / err и каналы, как родительский процесс непосредственно перед форком.

Насколько я понимаю, дочерний процесс, созданный fork, не делит переменные со своим родительским процессом.

Это не совсем так - изменения переменные не передаются родительскому элементу, но значения, которые родительский элемент имел непосредственно перед разветвлением, впоследствии видны дочернему элементу.

В любом случае каналы существуют внутри операционной системы, а не внутрипроцесс.Таким образом, данные, записанные на один конец канала, становятся видимыми для любого другого процесса, содержащего FD для другого конца.(Если более одного процесса пытается прочитать данные, первый процесс, пытающийся read() получить данные, получает и другие процессы пропускают.)

5 голосов
/ 11 июля 2011

Переменные не являются общими, например, если вы напишите file_pipes[0] = 999 в дочернем элементе, он не будет отражен в родительском.Файловые дескрипторы являются общими (номер FD x в дочернем элементе означает то же самое, что номер FD x в родительском элементе).Вот почему (например) вы можете перенаправить вывод сценария оболочки, который выполняет другие команды (поскольку они используют один и тот же стандартный дескриптор выходного файла).

1 голос
/ 11 июля 2011

Вы правы - обычные переменные не делятся между родителем и ребенком.

Однако трубы не являются переменными. Это псевдо-файл, специально разработанный для соединения двух независимых процессов. Когда вы пишете в канал, вы не изменяете переменную в текущем процессе - вы отправляете данные в операционную систему и просите ее сделать эти данные доступными для следующего процесса для чтения из канала.

Это похоже на запись в настоящий файл на диске - за исключением того, что данные не записываются на диск, они просто становятся доступными на другом конце канала.

...