Тот же дескриптор файла после 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 () одновременно с двумя разными файловыми дескрипторами, указывающими на один и тот же файл?

person omx    schedule 13.05.2015    source источник
comment
этот связанный вопрос может оказаться полезным.   -  person Diego    schedule 14.05.2015


Ответы (1)


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

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

В случае fork вы должны помнить, что значение дескриптора файла содержится внутри процесса. У многих процессов есть действительный fd 3, но не все они относятся к одному и тому же объекту. С fork у вас есть дубликат 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 поскольку операция предназначена только для чтения, я не понимаю, какой «конфликт» вы себе представляете.

person Community    schedule 13.05.2015
comment
Спасибо за четкое объяснение, я не учел, что нумерация файловых дескрипторов была локальной для процесса. - person omx; 14.05.2015