Тот же файловый дескриптор после fork()

Я пытаюсь понять, что означает дублирование дескриптора файла после вызова fork() и его возможные последствия для конкуренции.

В "Интерфейсе программирования Linux" 24.2.1 (p517):

Когда выполняется fork(), дочерний элемент получает дубликаты всех файловых дескрипторов родителя. Эти дубликаты создаются способом dup(), что означает, что соответствующие дескрипторы в родительском и дочернем элементах ссылаются на одно и то же описание открытого файла.

Когда я запускаю этот же код:

#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <sys/wait.h>

int main(void) {
    char* fl = "/tmp/test_fd";
    int fd;
    fd = open(fl, O_CREAT|O_TRUNC|O_WRONLY, 0666);
    if(!fork()) {
        printf("cfd=%d\n", fd);
        _exit(0);
    } else {
        int status;
        printf("ffd=%d\n", fd);
        wait(&status);
        close(fd);
        unlink(fl);
    }
}

Я получаю один и тот же файловый дескриптор (число?) Для обоих процессов: ffd=3 и cfd=3. Но когда запустить этот код с помощью dup():

#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>

int main(void) {
    char* fl = "/tmp/test_fd";
    int cfd, ffd;
    ffd = open(fl, O_CREAT|O_TRUNC|O_WRONLY, 0666);
    cfd = dup(ffd);
    printf("ffd=%d\n", ffd);
    printf("cfd=%d\n", cfd);
    close(ffd);
    unlink(fl);
}

Я получаю разные файловые дескрипторы: ffd=3 и cfd=4.

Затем у меня есть следующие вопросы:

  1. Что означает, что fork() создает копию файловых дескрипторов родителя?
  2. Есть ли конфликт, когда два процесса (отец и ребенок) выполняют операцию, например, fstat (), одновременно над одним и тем же файловым дескриптором?
  3. А как насчет двух процессов, выполняющих fstat () одновременно с двумя разными файловыми дескрипторами, указывающими на один и тот же файл?

1 ответ

Решение

Когда вы видите фразу "дублировать дескриптор файла", вы должны понимать это как "создать новый дескриптор файла, который указывает на то же самое, на что указывает другой".

Поэтому, когда вы дублируете fd 3, вы получаете fd 4. Это не одно и то же число, но они идентифицируют один и тот же объект.

В случае с fork вы должны помнить, что значение дескриптора файла содержится в процессе. Многие процессы имеют действительный fd 3, но они не все ссылаются на один и тот же объект. В форке у вас есть дубликат fd 3, который также является fd 3, но в другом процессе, поэтому эти 3 не являются идентичными; они идентичны, потому что форк сделал копию.

Вы можете закрыть fd и открыть другой файл в дочернем процессе, и у вас останутся два процесса, в которых действует fd 3, но они больше не являются копиями одного и того же. Или вы можете сделать так, чтобы потомок дублировал fd 3, чтобы получить fd 4, затем закройте fd 3, и тогда вы бы получили fd 3 в родительском и fd 4 в дочернем, ссылаясь на тот же объект.

Одно и то же число в другом процессе ничего не значит.

Также обратите внимание, что объект, на который ссылается дескриптор файла, не является файлом. Между дескриптором файла и файлом есть нечто, называемое открытым описанием файла. Обе команды fork и dup открывают доступ к описанию открытого открытого файла. Основным следствием совместного использования является то, что когда текущая позиция файла (устанавливается lseek или продвинутый read а также write), затрагиваются все связанные файловые дескрипторы, и когда флаги (например, O_NONBLOCK), затрагиваются все связанные файловые дескрипторы.

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

fstat будучи операцией только для чтения, я не вижу, какую "конкуренцию" вы себе представляете.

Другие вопросы по тегам