алгоритм close /* для устройств */ входная информация: дескриптор файла выходная информация: отсутствует { выполнить алгоритм стандартного закрытия (глава 5ххх); если (значение счетчика ссылок в таблице файлов не 0) перейти на finish; если (существует еще один открытый файл, старший и млад- ший номера которого совпадают с номерами закрываемого устройства) перейти на finish; /* не последнее закрытие */ если (устройство символьного типа) { использовать старший номер в качестве указателя в таблице ключей устройства посимвольного ввода-выво- да; вызвать процедуру закрытия, определяемую типом драй- вера и передать ей в качестве параметра младший но- мер устройства; } если (устройство блочного типа) { если (устройство монтировано) перейти на finish; переписать блоки устройства из буферного кеша на уст- ройство; использовать старший номер в качестве указателя в таблице ключей устройства ввода-вывода блоками; вызвать процедуру закрытия, определяемую типом драй- вера и передать ей в качестве параметра младший но- мер устройства; сделать недействительными блоки устройства, оставшие- ся в буферном кеше; } finish: освободить индекс; } |
10.1.2.2 Closе
Процесс разрывает связь с открытым устройством, закрывая его. Однако, ядро запускает определяемую типом устройства процедуру close только в последнем вызове функции close для этого устройства, и то только если не осталось процессов, которым устройство необходимо открытым, поскольку процедура закрытия устройства завершается разрывом аппаратного соединения; отсюда ясно, что ядру следует подождать, пока не останется ни одного процесса, обращающегося к устройству. Поскольку ядро запускает процедуру открытия устройства при каждом вызове системной функции open, а процедуру закрытия только один раз, драйверу устройства неведомо, сколько процессов используют устройство в данный момент. Драйверы могут легко выйти из строя, если при их написании не соблюдалась осторожность: когда при выполнении процедуры close они приостанавливают свою работу и какой-нибудь процесс открывает устройство до того, как завершится процедура закрытия, устройство может стать недоступным для работы, если в результате комбинации вызовов open и close сложилась нераспознаваемая ситуация.
Алгоритм закрытия устройства похож на алгоритм закрытия файла обычного типа (Рисунок 10.4). Однако, до того, как ядро освобождает индекс, в нем выполняются действия, специфичные для файлов устройств.
часть устройства с тем, чтобы ядро могло бы позднее открыть устройство вновь.
10.1.2.3 Read и Writе
Алгоритмы чтения и записи ядром на устройстве похожи на аналогичные алгоритмы для файлов обычного типа. Если процесс производит чтение или запись на устройстве посимвольного ввода-вывода, ядро запускает процедуры read или write, определяемые типом драйвера. Несмотря на часто встречающиеся ситуации, когда ядро осуществляет передачу данных непосредственно между адресным пространством задачи и устройством, драйверы устройств могут буферизовать информацию внутри себя. Например, терминальные драйверы для буферизации данных используют символьные списки (раздел 10.3.1). В таких случаях драйвер устройства выделяет "буфер", копирует данные из пространства задачи при выполнении процедуры write и выводит их из "буфера" на устройство. Процедура записи, управляемая драйвером, регулирует объем выводимой информации (т.н. управление потоком данных): если процессы генерируют информацию быстрее, чем устройство выводит ее, процедура записи приостанавливает выполнение процессов до тех пор, пока устройство не будет готово принять следующую порцию данных. При чтении драйвер устройства помещает данные, полученные от устройства, в буфер и копирует их из буфера в пользовательские адреса, указанные в вызове системной функции.