Операционная система UNIX
Операционная система UNIX читать книгу онлайн
Книга посвящена семейству операционных систем UNIX и содержит информацию о принципах организации, идеологии и архитектуре, объединяющих различные версии этой операционной системы.
В книге рассматриваются: архитектура ядра UNIX (подсистемы ввода/вывода, управления памятью и процессами, а также файловая подсистема), программный интерфейс UNIX (системные вызовы и основные библиотечные функции), пользовательская среда (командный интерпретатор shell, основные команды и утилиты) и сетевая поддержка в UNIX (протоколов семейства TCP/IP, архитектура сетевой подсистемы, программные интерфейсы сокетов и TLI).
Для широкого круга пользователей.
Внимание! Книга может содержать контент только для совершеннолетних. Для несовершеннолетних чтение данного контента СТРОГО ЗАПРЕЩЕНО! Если в книге присутствует наличие пропаганды ЛГБТ и другого, запрещенного контента - просьба написать на почту [email protected] для удаления материала
Доступ к драйверам STREAMS осуществляется с помощью коммутатора символьных устройств — таблицы
cdevsw[]
d_str
NULL
streamtab
streamtab
cdevsw[]
Создание потока
Поток создается при первом открытии с помощью системного вызова специального файла устройства, ассоциированного с драйвером STREAMS. Как правило, процесс создает поток в два этапа: сначала создается элементарный поток, состоящий из нужного драйвера и головного модуля (являющегося обязательным приложением), а затем производится встраивание дополнительных модулей для получения требуемой функциональности.
Процесс открывает поток с помощью системного вызова open(2), передавая ему в качестве аргумента имя специального файла устройства. При этом ядро производит трансляцию имени и обнаруживает, что адресуемый файл принадлежит файловой системе specfs, через которую в дальнейшем производятся все операции работы с файлом. В памяти размещается vnode этого файла и вызывается функция открытия файла для файловой системы specfs —
spec_open()
spec_open()
cdevsw[]
d_str
stropen()
Рис. 5.22. Структура потока после открытия
Головной модуль представлен структурой
stdata
q_ptr
queue
stdata
q_qinfo
queue
qinit
Очереди чтения и записи драйвера связываются с соответствующими очередями головного модуля. Информация, хранящаяся в структуре
streamtab
q_qinfo
В завершение вызывается функция
<i>xx</i>open()
stropen()
<i>xx</i>open()
После открытия потока процесс может произвести встраивание необходимых модулей. Для этого используется системный вызов ioctl(2). Команда
I_PUSH
I_POP
fd = open("/dev/stream", O_RDWR);
ioctl(fd, I_PUSH, "module1");
ioctl(fd, I_PUSH, "module2");
...
ioctl(fd, I_POP, (char*)0);
ioctl(fd, I_POP, (char*)0);
close(fd);
В этом примере процесс открыл поток /dev/stream, а затем последовательно встроил модули module1 и module2. Заметим, что команда
I_PUSH
Поскольку модули описываются такими же структурами данных, что и драйверы, схемы их встраивания похожи. Как и в случае драйверов, для заполнения полей
q_qinfo
streamtab
fmodsw[]
streamtab
<i>xx</i>open()
Управление потоком
Управление потоком осуществляется прикладным процессом с помощью команд системного вызова ioctl(2):
#include <sys/types.h>
#include <stropts.h>
#include <sys/conf.h>
int ioctl(int fildes, int command, ... /* arg */);
Хотя часть команд обрабатывается исключительно головным модулем потока, другие предназначены промежуточным модулям или драйверу. Для этого головной модуль преобразует команды ioctl(2) в сообщения и направляет их вниз по потоку. При этом возникают две потенциальные проблемы: синхронизация процесса с системным вызовом (поскольку передача сообщения и реакция модуля имеют асинхронный характер) и передача данных между процессом и модулем.
Синхронизацию осуществляет головной модуль. Когда процесс выполняет системный вызов ioctl(2), который может быть обработан самим головным модулем, последний выполняет все операции в контексте процесса, и никаких проблем синхронизации и копирования данных не возникает. Именно так происходит обработка ioctl(2) для обычных драйверов устройств. Если же головной модуль не может обработать команду, он блокирует выполнение процесса и формирует сообщение
M_IOCTL
M_IOCACK
M_IOCNAK