Кооперация процессов при работе с файлами


Когда различные пользователи работают вместе над проектом, они часто нуждаются в разделении файлов. Разделяемый файл — разделяемый ресурс. Как и в случае любого со­вместно используемого ресурса, процессы должны синхронизировать до­ступ к совместно используемым файлам, каталогам, чтобы избежать ту­пиковых ситуаций, дискриминации отдельных процессов и снижения производительности системы.

Например, если несколько пользователей одновременно редактиру­ют какой-либо файл и не принято специальных мер, то результат будет непредсказуем и зависит оттого, в каком порядке осуществлялись записи в файл. Между двумя операциями read одного процесса другой процесс может модифицировать данные, что для многих приложений неприемле­мо. Простейшее решение данной проблемы — предоставить возможность одному из процессов захватить файл, то есть блокировать доступ к разде­ляемому файлу других процессов на все время, пока файл остается откры­тым для данного процесса. Однако это было бы недостаточно гибко и не соответствовало бы характеру поставленной задачи.

Рассмотрим вначале грубый подход, то есть временный захват поль­зовательским процессом файла или записи (части файла между указан­ными позициями).

Системный вызов, позволяющий установить и проверить блокиров­ки на файл, является неотъемлемым атрибутом современных многополь­зовательских ОС. В принципе, было бы логично связать синхронизацию доступа к файлу как к единому целому с системным вызовом open (т. е., например, открытие файла в режиме записи или обновления могло бы оз­начать его монопольную блокировку соответствующим процессом, а от­крытие в режиме чтения — совместную блокировку). Так поступают во многих операционных системах (начиная с ОС Multics). В ОС Unix это не так, что имеет исторические причины.

В первой версии системы Unix, разработанной Томпсоном и Ричи, механизм захвата файла отсутствовал. Применялся очень простой подход к обеспечению параллельного (от нескольких процессов) доступа к фай­лам: система позволяла любому числу процессов одновременно открывать один и тот же файл в любом режиме (чтения, записи или обновления) и не предпринимала никаких синхронизационных действий. Вся ответст­венность за корректность совместной обработки файла ложилась на ис­пользующие его процессы, и система даже не предоставляла каких-либо особых средств для синхронизации доступа процессов к файлу. Однако впоследствии для того, чтобы повысить привлекательность системы для коммерческих пользователей, работающих с базами данных, в версию V системы были включены механизмы захвата файла и записи, базирующи­еся на системном вызове fcntl.

Допускается два варианта синхронизации:с ожиданием, когда требование блокировки может привести к откладыванию процесса до того момента, когда это требование может быть удовлетворено, и без ожидания, когда процесс немедленно оповещается об удовлетворении требования блокировки или о невозможности ее удовлетворения в дан­ный момент.

 

Более тонкий подход заключается в прозрачной для пользователя блокировке отдельных структур ядра, отвечающих за работу с файлами части пользовательских данных. Например, в ОС Unix во время систем­ного вызова, осуществляющего ту или иную операцию с файлом, как пра­вило, происходит блокирование индексного узла, содержащего адреса блоков данных файла. Может показаться, что организация блокировок или запрета более чем одному процессу работать с файлом во время вы­полнения системного вызова является излишней, так как в подавляющем большинстве случаев выполнение системных вызовов и так не прерыва­ется, то есть ядро работает в условиях невытесняющей многозадачности. Однако в данном случае это не совсем так. Операции чтения и записи за­нимают продолжительное время и лишь инициируются центральным процессором, а осуществляются по независимым каналам, поэтому уста­новка блокировок на время системного вызова является необходимой га­ рантией атомарности операций чтения и записи. На практике оказывает­ся достаточным заблокировать один из буферов кэша диска, в заголовке которого ведется список процессов, ожидающих освобождения данного буфера. Таким образом, в соответствии с семантикой Unix изменения, сделанные одним пользователем, немедленно становятся «видны» друго­му пользователю, который держит данный файл открытым одновременно с первым.

 

При возникновении классического тупика между процессами.

Для предотвращения этого классического примера взаимной блоки­ровки в файловой системе принято, чтобы ядро освобождало индекс исход­ного файла после увеличения значения счетчика связей. Тогда, поскольку первый из ресурсов (индекс) свободен при обращении к следующему ре­сурсу, взаимной блокировки не происходит.

 

 



Дата добавления: 2017-06-13; просмотров: 1371;


Поиск по сайту:

Воспользовавшись поиском можно найти нужную информацию на сайте.

Поделитесь с друзьями:

Считаете данную информацию полезной, тогда расскажите друзьям в соц. сетях.
Poznayka.org - Познайка.Орг - 2016-2024 год. Материал предоставляется для ознакомительных и учебных целей.
Генерация страницы за: 0.008 сек.