Как один и тот же fd в разных процессах может указывать на один и тот же файл?

25

Скажем, у меня есть процесс 1 и процесс 2 . Оба имеют дескриптор файла, соответствующий целому числу 4.

Однако в каждом процессе дескриптор файла 4 указывает на совершенно другой файл в таблице открытых файлов ядра:

введите описание изображения здесь

Как это возможно? Разве файловый дескриптор не должен быть индексом записи в таблице открытых файлов?

Pithikos
источник
1
Хороший вопрос! Я предполагаю, что файловые дескрипторы переведены, так что fd 4в обоих процессах относительно его собственного числа открытых fd. Fd 0-2(stdin, stdout, sdterr) всегда открываются для нового процесса, а номера не зарезервированы только для этого процесса.
@ jw013 Я думал, это звучит знакомо. \ @Pithikos Как это не дубликат?
Михаил Мрозек
1
Это плохая диаграмма - она ​​должна показывать, что дескриптор файла 4 означает четвертую запись (ну, в-пятых, она отсчитывается от нуля) в таблице дескрипторов файлов слева, а не запись, которая содержит «4». Фактическая «4» живет в вашей переменной пространства пользователя, содержащей число. Диаграмма в другом вопросе намного лучше.
Random832
2
@ Random832 Ну, если бы я знал, какая диаграмма верна, я бы, наверное, никогда не задавал этот вопрос.
Питикос

Ответы:

35

Файловый дескриптор, т. Е. 4В вашем примере, является индексом таблицы дескрипторов файлов для конкретного процесса , а не таблицы открытых файлов. Сама запись дескриптора файла содержит индекс к записи в глобальной таблице открытых файлов ядра, а также флаги дескриптора файла.

jw013
источник
2
Для записи, в большинстве систем есть только один «флаг дескриптора файла», флаг close-on-exec. Все остальные состояния "per-fd" (включая смещение и режим доступа) являются частью записи таблицы открытых файлов.
Random832
24

Каждый процесс имеет свою собственную таблицу дескрипторов файлов. Файловый дескриптор 4 в процессе 1234 указывает внутри таблицы процесса 1234. Файловый дескриптор 4 в процессе 5678 указывает внутри таблицы процесса 5678. Случай, с которым вы должны быть знакомы, - это файловые дескрипторы 0, 1 и 2, которые для каждого процесса представляют собой стандартный ввод, стандартный вывод и стандартную ошибку, указывающие, куда они были перенаправлены.

Процесс может открыть один и тот же файл более одного раза. Это может происходить по совпадению, например, когда стандартный вывод процесса и стандартная ошибка перенаправляются на один и тот же терминал или в один и тот же файл. Базовые записи таблицы файлов (например, Linuxstruct file ) несут больше информации о файле; они также содержат режимы открытия (например, чтение или запись) и другое состояние (например, флаги, например, close-on-exec). Например, процесс может иметь терминал, открытый для чтения только по файловому дескриптору 0, и тот же терминал, открытый для записи только по файловому дескриптору 2. Записи файловых таблиц также содержат позицию процесса в файле; процесс может захотеть использовать lseekдве разные позиции в одном и том же файле, и поэтому он будет использовать dupдля получения двух дескрипторов этого файла.

Жиль "ТАК - перестань быть злым"
источник
2
Это не совсем правильно. Согласно man-странице / спецификациям, dupв точности соответствует тому, что написано на банке: оба результирующих дескриптора указывают на одну и ту же запись таблицы файлов и, таким образом, имеют одинаковое смещение. Для того, чтобы получить 2 разных записи в таблице файлов, я уверен, что вам нужен openфайл дважды.
jw013
@ Жиль "Файловый дескриптор 4 в 1234 точках процесса внутри таблицы 1234 процесса". Какой стол вы имеете в виду? Из того, что я знаю, единственная таблица в этом процессе - это таблица дескрипторов файлов, где каждая запись указывает на одну таблицу открытых файлов ядра .
Питикос
См. Unix.stackexchange.com/questions/195057/… для более точного описания.
Жиль "ТАК - перестань быть злым"
8

Каждый процесс имеет свою собственную таблицу дескрипторов файлов. Вот и все.

Все это очень хорошо описано в сетевом программировании UNIX Ричарда Стивенса, если вы хотите глубоко изучить его.

Михал Шрайер
источник
На какую таблицу вы ссылаетесь?
Питикос
1
таблица дескрипторов файлов
Михал Шрайер
7

Разве дополнительный уровень косвенности не решит вашу проблему? («Все проблемы в компьютерном программировании могут быть решены с помощью дополнительного уровня косвенности», - считает один мудрый седобородый). То есть маленькое целое число в каждом процессе заканчивается как индекс в массиве индексов пространства ядра для каждого процесса в «Таблицу открытых файлов».

Брюс Эдигер
источник
2
Источник мудрый старик , вероятно , Дэвид Уилер. Похоже, он также сказал: « Но это обычно создает другую проблему». :)
jw013