#c# #.net #windows #filesystems #dokan
#c# #.net #Windows #файловые системы #докан
Вопрос:
Я использую код C #, расположенный по следующим ссылкам, для реализации проекта Ram-disk.
В качестве резюме, приведенный выше код использует простую древовидную структуру для хранения каталогов, подкаталогов и файлов. В корне находится MemoryFolder
объект, который хранит ноль или более объектов «MemoryFolder» и / или MemoryFile
объектов. Каждый MemoryFolder
объект, в свою очередь, хранит ноль или более MemoryFolder
объектов и / или MemoryFile
объектов и так далее до неограниченной глубины.
Однако код не является потокобезопасным. Какой самый элегантный способ реализации потокобезопасности? Кроме того, как следует применять следующий неисчерпывающий список требований к многопоточности для типичной файловой системы с помощью соответствующей стратегии блокировки?
-
Одновременное создание двух разных папок (каждая другим потоком) в одной и той же родительской папке может происходить одновременно, если это позволяет потокобезопасная реализация. В противном случае следует реализовать некоторую стратегию блокировки, чтобы разрешить только последовательное создание.
-
Ни одна из прямых или косвенных родительских папок папки, содержащей определенный файл (который в данный момент читается другим потоком), распространяющийся вплоть до корневой папки, не может быть перемещена или удалена другим потоком, пока
ReadFile
поток не завершит свое выполнение. -
Что касается каждого уникального файла, разрешает одновременный доступ для нескольких
ReadFile
потоков, но ограничивает доступ к одномуWriteFile
потоку. -
Если два отдельных
ReadFile
потока (запущенных почти одновременно), каждый из разных приложений пытается создать папку с тем же именем (при условии, что папка еще не существует до запуска обоих потоков), первый поток, который попадает на Ram-диск, всегда завершается успешно, а второй всегда завершается неудачей. Другими словами, порядок выполнения потоков является детерминированным. -
Метод вычисления общего дискового пространства
GetDiskFreeSpace
, выполняемый в отдельном потоке, не должен завершать свое выполнение, пока всеWriteFile
потоки, которые уже выполняются, не завершат его выполнение. Все последующиеWriteFile
потоки, которые не начали выполняться, блокируются до техGetDiskFreeSpace
пор, пока поток не завершит свое выполнение.
Ответ №1:
Самый простой способ сделать это — защитить все дерево с помощью ReaderWriterLockSlim. Это позволяет одновременный доступ для нескольких читателей или эксклюзивный доступ для одного автора. Любой метод, который каким-либо образом изменит структуру, должен будет получить блокировку записи, и никаким другим потокам не будет разрешено читать или записывать в структуру, пока этот поток не снимет блокировку записи.
Любой поток, который хочет прочитать структуру, должен получить блокировку чтения. Несколько считывателей могут получить блокировку чтения одновременно, но если поток хочет получить блокировку записи, что означает ожидание, пока не будут сняты все существующие блокировки чтения.
Возможно, есть способ сделать эту структуру данных свободной от блокировки. Однако это может быть довольно сложно. Блокировка чтения / записи предоставит вам желаемую функциональность, и я подозреваю, что это будет достаточно быстро.
Если вы хотите поделиться этим между процессами, это уже другая история. Это ReaderWriterLockSlim
не работает во всех процессах. Однако вы могли бы реализовать нечто подобное, используя комбинацию примитивов синхронизации, или создать драйвер устройства (или службу), который обслуживает запросы, тем самым сохраняя все это в одном процессе.