Почему ReadDirectoryChangesW не предоставляет способа сопоставить две стороны операции переименования

Брайан Деллисанти спросил, почему ReadDirectoryChangesW не предоставлял способа связать две стороны операции переименования.

Я предполагаю, что реализация всегда генерировала два события одно за другим, так что «очевидно» способ их связать — сохранить старое имя при получении FILE_ACTION_RENAMED_OLD_NAME, а когда FILE_ACTION_RENAMED_NEW_NAME следует сразу после, у вас есть обе стороны. Но это никогда не было записано как правило, что два события всегда появляются подряд. Это означало, что при появлении новых файловых систем они могли не соблюдать неформальное правило. Если два файла переименовываются одновременно, возможно ли, что два набора событий переименования окажутся перемешаны? Ничего не было записано, чтобы это запретить, так что, полагаю, это возможно.

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

На практике я не нашел много кода, который бы отслеживал переименования. Как правило, они трактовали FILE_ACTION_RENAMED_OLD_NAME как удаление, а FILE_ACTION_RENAMED_NEW_NAME как создание. А те, кто действительно отслеживал переименования, предполагали, что переименования не перемешиваются. (Не то чтобы у них был большой выбор.)

Я не думаю, что предоставление идентификаторов файлов для двух сторон операции переименования было целью ReadDirectoryChangesExW и ReadDirectoryNotifyExtendedInformation. Это просто приятный побочный эффект: дополнительная информация в ReadDirectoryNotifyExtendedInformation также дает вам детали, необходимые для надежного связывания событий.

Я думал, вам было бы полезно, если я укажу на этот трюк — и на этом всё.

Рэймонд участвует в эволюции Windows более 30 лет. В 2003 году он начал веб-сайт под названием The Old New Thing, который стал популярнее, чем он когда-либо мог представить, что до сих пор вызывает у него дрожь. Веб-сайт породил книгу с тем же названием The Old New Thing (Addison Wesley, 2007). Иногда он появляется в аккаунте Windows Dev Docs в Twitter, рассказывая истории, не несущие полезной информации.

Обсуждение закрыто. Войдите в систему, чтобы редактировать/удалять существующие комментарии.

Этот блог всегда заставляет меня сомневаться в допущениях, которые я считал верными десятилетиями. Является ли файловая система по своей сути однопоточной? Если у меня дюжина потоков переименовывает файлы, скажем, на устройстве с включенным кэшированием записи, будут ли уведомления по-прежнему сериализованы? (Зависит ли такое поведение от файловой системы?)

Думаю, это во многом сводится к деталям реализации. Они должны быть потокобезопасными и, вероятно, параллелизируют простые операции. Но рассмотрите уровень хранения под файловой системой. Это может быть NVMe-диск с поддержкой тысяч параллельных операций в аппаратных очередях. А может быть IDE-диск, поддерживающий одну операцию за раз и требующий физического перемещения головы. В файловых системах это может быть что-то вроде Ext2 с отдельными индексными дескрипторами (inode), которые можно обрабатывать независимо, или что-то вроде FAT, где существует список кластеров на уровне тома, и параллельные операции выглядят как рецепт для коррупции данных. Но кэш всегда возможен, и параллельные чтения не проблема.

Если посмотреть внутрь ядра Linux, вы увидите, что файловая система не однопоточная; но операции, создающие имена файлов, сначала блокируют каталог. Так что каждый каталог в основном обрабатывается последовательно.

Теоретически может существовать файловая система на основе B-деревьев или H-деревьев, нарушающая это предположение и при этом работающая; но я не встречал такую.

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

Единственное, что меня действительно интересует, — почему ReadDirectoryChanges и связанные с ним функции никогда не позаботились о предоставлении уведомлений о закрытии файла.

Потому что закрытие файла не меняет каталог.

Если бы ReadDirectoryChangesExW гарантировал выдачу этих двух сообщений подряд без перемешивания, жизнь была бы проще.

Почему в уровнях вакансий Microsoft нумерация начинается с верхних 50-х, вместо того чтобы начинаться с адекватного номера, например, с 1?

Windows на AArch64 также поддерживает горячую патчинг, но это гораздо проще, чем на x86.

Получайте уведомления, когда публикуются новые записи.

Вы уверены, что хотите удалить это?