Истинный клон дескриптора файла

Почему нет реального механизма клонирования дескрипторов файлов, когда это возможно, как это делается для файлов на диске.

POSIX:

После успешного возврата из одного из этих системных вызовов старые и новые файловые дескрипторы могут использоваться взаимозаменяемо. Они ссылаются на одно и то же описание открытого файла (см. Open(2)) и, таким образом, совместно используют смещение файла и флаги состояния файла; например, если смещение файла изменяется с помощью lseek(2) для одного из дескрипторов, смещение также изменяется для другого.

Окна:

Дублирующая ручка относится к тому же объекту, что и оригинальная ручка. Поэтому любые изменения объекта отражаются через обе ручки. Например, если вы дублируете дескриптор файла, текущая позиция файла всегда одинакова для обоих дескрипторов. Чтобы дескрипторы файлов имели разные позиции, используйте функцию CreateFile для создания файловых дескрипторов, которые имеют общий доступ к одному и тому же файлу.

Причины для примитива клона:

  • При работе с файловым архивом я хочу, чтобы каждый файл в архиве был доступен независимо. Файловый архив должен вести себя как виртуальная файловая система.

  • Проверка типа файла. Возможность клонировать смещения файлов позволяет читать небольшую часть файла, не затрагивая исходную позицию.

1 ответ

Решение

Вам следует учесть следующее: дескриптор файла - это просто смещение в массиве указателей объектов "файл" (буквально так они называются) на стороне ядра. Поэтому, когда вы дублируете файловый дескриптор, ядро ​​просто скопирует значение указателя файла из одного места в массиве в другое и увеличит счетчик ссылок на указанный объект.

Таким образом, ваша проблема не в дублировании файловых дескрипторов, а в управлении смещениями файлов. Ответ прост: сделай сам. То есть, явно сопоставьте текущее смещение файла с каждым файловым дескриптором на стороне приложения.

Конечно, самые простые системные файлы доступа к вызовам read() а также write() использовать поддерживаемую ядром переменную смещения файла, если она доступна (и она доступна, только если вы имеете дело с "обычными" файлами произвольного доступа). Но более продвинутые системные вызовы доступа к файлам будут ожидать, что требуемое смещение файла будет предоставлено приложением при каждом вызове. Те включают pread()/pwrite(), preadv()/pwritev() а также aio_read()/aio_write (последнее, вероятно, лучший подход для написания приложений с параллельным доступом, подобных тому, который вы описали).

В Windows ReadFile()/WriteFile(), ReadFileScatter()/WriteFileGather() а также ReadFileEx()/WriteFileEx() аналогично ожидайте, что передается смещение файла при каждом вызове (через lpOverlapped аргумент).

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