Главная страница Взаимодействие нетривиальных процессов новлен флаг D NDNBLDCK, вызов read или write, конфликтующий с установленной блокировкой, вернет ошибку EAGAIN. Если флаг D NDNBLDCK не установлен, выполнение процесса в такой ситуации будет отложено до тех пор, пока ресурс не освободится. ПРИМЕЧАНИЕ- Стандарты Posix.l и Unix 98 определяют только рекомендательную блокировку. Во многих реализациях, производных от System V, имеется возможность установки как рекомендательной, так и обязательной блокировки. Обязательная блокировка записей впервые появилась в System V Release 3. Для установки обязательной блокировки какого-либо файла требуется выполнение двух условий: ш бит group -execute должен быть снят; ш бит set-group- ID должен быть установлен. Обратите внимание, что установка бита set-user- ID без установки user-execute смысла не имеет; аналогично и с битами set-group-ID и group-execute. Таким образом, добавление возможности обязательной блокировки никак не повлияло на работу используемого программного обеспечения. Не потребовалось и добавлять новые системные вызовы. В системах, поддерживающих обязательную блокировку записей, команда 1 s просматривает файлы на наличие указанной специальной комбинации битов и выводит буквы 1 или L, указывающие на то, что для данного файла включена обязательная блокировка. Аналогично команда chmod принимает аргумент 1, позволяющий включить для указанного файла обязательную блокировку. Пример На первый взгляд, использование обязательной блокировки должно решить проблему с несотрудничающими процессами, поскольку все операции чтения и записи будут приостановлены до снятия блокировки. К сожалению, проблемы с одновременными обращениями к ресурсу являются гораздо более сложными, чем кажется, что мы можем легко продемонстрировать. Чтобы использовать в нашем примере обязательную блокировку, изменим биты разрешений файла seqno. Кроме того, мы будем использовать новую версию функции main, которая принимает количество проходов цикла for в качестве аргумента командной строки (вместо использования константы 20) и не вызывает pri ntf при каждом проходе цикла: Solaris % cat > seqno инициализируем файл единицей *D конец файла Solaris % Is -1 seqno -rw-r--r-- 1 rstevens otherl 2 Oct 7 11:24 seqno Solaris % cfmrod +1 seqno включение обязательной блокировки Solaris * Is -1 seqno -rq-r-lr-- 1 rstevens otherl 2 Oct 7 11:24 seqno Теперь запустим две программы в качестве фоновых процессов: loopfcntl использует блокировку записей fcntl, а loopnone не использует блокировку вовсе. Укажем в командной строке аргумента 10 ООО - количество последовательных увеличений порядкового номера. Solaris % loopfcntl 10000 & loopnone 10000 & Solaris % wait Solaris % cat seqno 14378 запуск фоновых процессов ожидание их завершения вывод последовательного номера ошибка, должно быть 20 001 Каждый раз при выполнении этих программ результат будет между 14 ООО и 16 ООО. Если бы блокировка работала так как надо, он всегда был бы равен 20 001. Чтобы понять, где же возникает ошибка, нарисуем временную диаграмму выполнения процессов, изображенную на рис. 9.1. lockfcntl 1. open О 2. блокировка файла 3. read () X 1 4. увеличение порядкового номера 5. write О X 2 6. снятие блокировки 7. блокировка файла 8. read О X 2 переключение процессов X X переключение процессов 13. увеличение порядкового номера 14. write О X 3 15. снятие блокировки переключение процессов X locknone X переключение процессов 25. блокировка файла 26. read () X 5 27. увеличенив порядкового номера 28. write О X 6 29. снятие блокировки 30. блокировка файла 31. read ()Х6 32. увеличение порядкового номера 33. write О X 7 34. снятие блокировки переключение процессов X 10. open О 11. read О blocks 17. read О X 3 18.увеличение порядкового номера 19, write О X 4 20, read () X 4 21.увеличение порядкового номера 22. write О X 5 23. read () X 5 36,увеличение порядкового номера 37, write О X 6 Рис. 9.1. Временная диаграмма работы программ loopfcntl и loopnone Предположим, что loopfcntl запускается первой и выполняет первые восемь действий, изображенных на рисунке. Затем ядро передает управление другому процессу в тот момент, когда установлена блокировка на файл с порядковым номером. Запускается процесс loopnone, но он блокируется в первом вызове read, потому что на файл, который он пытается читать, установлена обязательная блокировка. Затем ядро передает управление первому процессу, который выполняет шаги 13-15. Пока все работает именно так, как мы предполагали, - ядро защищает файл от чтения несотрудничающим процессом, когда этот файл заблокирован. Дальше ядро передает управление программе loopnone, которая выполняет шаги 17-23. Вызовы read и write разрешены, поскольку файл был разблокирован на шаге 15. Проблема возникает в тот момент, когда программа считывает значение 5 на шаге 23, а ядро в этот момент передает управление другому процессу. Он устанавливает блокировку и также считывает значение 5. Затем он дважды увеличивает это значение (получается 7), и управление передается 1 оорпопе на шаге 36. Однако эта программа записывает в файл значение 6. Так и возникает ошибка. На этом примере мы видим, что обязательная блокировка предотвращает доступ к заблокированному файлу (шаг И), но это не решает проблему. Проблема заключается в том, что левый процесс (на рисунке) может обновить содержимое файла (шаги 25-34) в тот момент, когда процесс справа также находится в состоянии обновления данных (шаги 23, 36 и 37). Если файл обновляется несколькими процессами, все они должны сотрудничать, используя некоторую форму блокировки. Один неподчиняющийся процесс может все разрушить. 9.6. Приоритет чтения и записи в нашей реализации блокировок чтения-записи в разделе 8.4 приоритет предоставлялся ожидающим записи процессам. Теперь мы изучим детали возможного решения задачи читателей и писателей с помощью блокировки записей fcntl. Хочется узнать, как обрабатываются накапливающиеся запросы на блокировку, когда ресурс уже заблокирован. Стандарт Posix этого никак не оговаривает. Пример: блокировка на чтение при наличии в очереди блокировки на запись Первый вопрос, на который мы попытаемся найти ответ, звучит так: если ресурс заблокирован на чтение и какой-то процесс послал запрос на установление блокировки на запись, будет ли при этом разрешена установка еще одной блокировки на чтение? Некоторые решения задачи читателей и писателей не разрешают установки еще одной блокировки на чтение в случае, если есть ожидающий своей очереди пишущий процесс, поскольку если бы разрешалось непрерывное подключение считывающих процессов, запрос на запись, возможно, никогда бы не был удовлетворен. Чтобы проверить, как эта ситуация разрешится при использовании блокировки записей fcntl, напишем тестовую программу, устанавливающую блокировку на чтение для всего файла и затем порождающую два процесса с помощью fork.
|
© 2000 - 2024 ULTRASONEX-AMFODENT.RU.
Копирование материалов разрешено исключительно при условии цититирования. |