|
Программирование >> Структура ядра и системные вызовы
программа пользователя, находящаяся в состоянии выполнения), контекст выполнения процесса переключается ядром из режима пользователя в режим ядра. Режим пользователя - обычный режим выполнения любого пользовательского процесса. Он обеспечивает процессу доступ только к его собственным данным. Режим ядра - защищенный режим выполнения, который позволяет процессу пользователя получать ограниченный доступ к данным ядра. Когда выполнение API завершается, пользовательский процесс переключается обратно в режим пользователя. Это переключение контекста для каждого вызова API гарантирует, что доступ процессов к данным ядра контролируется, и уменьшает вероятность того, что вышедшее из-под контроля пользовательское приложение сможет повредить всю систему. В общем, вызов API требует больше времени, чем вызов пользовательской функции, из-за необходимости переключения контекста. Таким образом, для приложений, требующих высокого быстродействия, пользователи должны вызывать системные API только в том случае, если это абсолютно необходимо. 5.1. Интерфейсы прикладного программирования POSIX Большинство API, определенных в стандартах POSIX. 1 и POSIX.lb, соответствуют API ОС UNIX. Тем не менее комитеты POSIX все же разрабатывают собственные API, когда ощущается нехватка API UNIX. Например, комитет POSIX. lb создает новый набор API для межпроцессного взаимодействия на основе сообщений, разделяемой памяти и семафоров. Аналогичные механизмы для межпроцессного взаимодействия есть и в ОС UNIX System V, но последние не используют путевые имена для определения этих средств межпроцессного взаимодействия, и процессы не могут использовать их для осуществления связи по локальной сети. Поэтому комитет POSIX. lb создал другую версию сообщений, разделяемой памяти и семафоров, в которой упомянутые недостатки устранены. И все же API POSIX используются и ведут себя аналогично API UNIX. Однако пользователи должны определять POSIX SOURCE (для API POSIX. 1) и (или) POSIX C SOURCE (для API POSIX. 1 и POSIX. lb) в своих программах, чтобы обеспечить объявление API POSIX в файлах заголовков, указанных в этих программах. 5.2. Среда разработки UNIX и POSIX в файле заголовков <unistd.h> объявляются некоторые широко используемые API POSIX. 1 и UNIX. Имеется также набор относящихся к API заголовков, размещенных в каталоге <sys> (в UNIX-системе это каталог /usr/include/sys). Заголовки типа <sys/...> объявляют специальные типы данных для объектов данных, которыми манипулируют и API, и пользовательские процессы. Кроме того, заголовок <stdio.h> объявляет функцию perror, которая может быть вызвана процессом пользователя всякий раз, когда выполнение API завершается неудачей. Функция perror обеспечивает вывод на экран определенного системой диагностического сообщения для любого отказа, вызванного API. Большая часть объектного кода API POSIX. 1, POSIX. lb и UNIX находится в библиотеках libc.a и libc.so. Таким образом, не нужно определять никаких специальных ключей компилятора, чтобы указать, в каком архиве или совместно используемой библиотеке хранится объектный код API. В некоторых системах, однако, объектный код определенных сетевых коммуникационных API находится в специальных библиотеках (например, в ОС Solaris 2.x фирмы Sun Microsystems API гнезд (sockets) хранятся в библиотеках libsocket.a и lib socket.so). Поэтому пользователи должны обращаться к руководству системного программиста за информацией о специальных заголовках и библиотеках, необходимых для API, которые они используют. 5.3. Общие характеристики интерфейсов прикладного программирования Хотя API POSIX и UNIX выполняют от лица пользователей разнообразные системные функции, большинство из них возвращает целое число, значение которого свидетельствует о корректности завершения выполнения. В частности, если API возвращает -1, это значит, что попытка выполнить API потерпела неудачу и глобальной переменной егто (которая объявлена в заголовке <errno.h>) присваивается код ошибки. Пользовательский процесс может вызывать функцию perror, чтобы направить диагностическое сообщение об отказе на стандартный вывод, или функцию strerror, задав ей в качестве аргумента значение еггпо. Функция strerror возвращает строку диагностического сообщения, и пользовательский процесс может вывести это сообщение так, как он считает нужным (например, поместить его в файл регистрации ошибок). Коды ошибок, которые могут быть присвоены еггпо любым API, определены в файле заголовков <errno.h>. Когда пользователь просматривает man-страницу API, на ней, как правило, перечисляются возможные коды ошибок, которые присваиваются еггпо данным API, и причины их возникновения. Так как эта информация всегда доступна пользователям, а коды ошибок в различных системах могут быть разными, в этой книге не будут подробно описываться значения еггпо для отдельных API. Ниже приведен список наиболее распространенных кодов ошибок и их значения. Код ошибки Значение EACCESS Процесс не имеет права на выполнение операции с помощью EPERM API был прерван, потому что вызывающий процесс не имеет права привилегированного пользователя ENOENT Интерфейсу прикладного профаммирования было указано не- действительное имя файла Код ошибки Значение BADF API был вызван с недействительным дескриптором файла EINTR Выполнение API было прервано каким-то сигналом (сигналы и вызываемые ими прерывания рассматриваются в главе 9) EAGAIN API был прерван, потому что какой-то необходимый системный ресурс был временно недоступен. Этот API следует вызвать позже ENOMEM API был прерван потому, что ему не была вьщелена динамиче- ская память ЕЮ В процессе выполнения API произошла ошибка ввода-вывода EPIPE API попытался записать данные в канал, для которого не суще- ствует читающего процесса EFAULT Интерфейсу прикладного программирования был передан не- действительный адрес в одном из аргументов ENOEXEC API не смог выполнить программу с помощью одного из сис- темных вызовов семейства exec 1 g. ECHILD Процесс не имеет ни одного порожденного процесса, заверше- ния которого он мог бы ждать Если API выполнен успешно, он возвращает нулевое значение или указатель на некоторую запись данных, где хранится необходимая пользователю информация. 5.4. Заключение в этой главе дан краткий обзор интерфейсов прикладного программирования UNIX и POSIX, описана методика их использования, приведены общие характеристики. Эти API достаточно мощны и дают возможность пользователям разрабатывать развитые системные программы, манипулирующие системными объектами (например, файлами и процессами) более разнообразными способами, нежели это позволяют делать стандартные библиотечные функции С и классы С++. Кроме того, пользователи могут применять эти API для создания собственной библиотеки или классов С++ и собственных версий shell-команд, чтобы расширить ассортимент команд. Следует отметить, однако, что в большинстве API выполняется переключение контекста пользовательских процессов между режимом пользователя и режимом ядра, поэтому применение этих API приводит к увеличению затрат времени. В остальных главах книги API UNIX и POSIX исследуются более подробно. Предназначены они для манипулирования файлами и процессами, обеспечения межпроцессного взаимодействия и удаленного вызова процедур. Приводятся примеры использования API для создания пользовательских версий библиотечных функций С и shell-команд, а также для построения классов С++ с целью создания обобщенных типов данных для системных объектов (например, процессов) и системных функций (например, функций, обеспечивающих межпроцессное взаимодействие). ГЛАВА Файловая система ОС UNIX Файлы - основа любой операционной системы, поскольку именно с ними производится наибольшее число действий. Когда вы выполняете команду в системе UNIX, ее ядро выбирает соответствующий исполняемый файл из файловой системы, загружает текст инструкций в память и создает процесс для выполнения команды от вашего имени. Кроме того, в ходе выполнения процесс может читать данные из файлов и записывать их в файлы. Создание операционной системы всегда начинается с разработки эффективной системы управления файлами. Файлы в UNIX- и POSIX-системах могут быть самых разных типов. Здесь используются текстовые файлы, двоичные файлы, файлы каталогов и файлы устройств. Кроме того, в UNIX- и POSIX-системах имеется набор общих системных интерфейсов, предназначенных для осуществления доступа к файлам, благодаря чему прикладные программы могут работать с ними по единой методике. Это, в свою очередь, упрощает задачу разработки прикладных программ для данных систем. В этой главе будут рассмотрены файлы различных типов, используемые в UNIX- и POSIX-системах, и будет показано, как они создаются и применяются. Кроме того, существует набор общих атрибутов, которые операционная система хранит для каждого файла, имеющегося в системе. Данная глава содержит подробное описание этих атрибутов и варианты их использования. Наконец, описываются структуры данных ядра UNIX System V и всех процессов, которые используются при манипулировании файлами и для формирования интерфейса системных вызовов. Системные вызовы UNIX и POSIX.l, применяемые для управления файлами, описаны в следующей главе. 6.1. Типы файлов в UNIX- и POSIX-системах существуют файлы следующих типов: обычный файл; каталог; FIFO-файл; байт-ориентированный файл устройства; блок-ориентированный файл устройства. Обычный файл может быть текстовым или двоичным. В UNIX- и POSIX-системах эти типы файлов не различаются и оба могут быть исполняемыми при условии, что для них установлено разрешение на выполнение и они могут читаться или записываться пользователями, имеющими соответствующие права доступа. Обычные файлы могут создаваться, просматриваться и модифицироваться с помошью различных средств (например, текстовых редакторов и компиляторов) и удаляться определенными системными командами (например, командой гт в ОС UNIX). Каталог подобен папке, которая содержит много файлов, а также подкаталоги. Каталог предоставляет пользователям средства для организации их файлов в некую иерархическую структуру, основанную на взаимосвязи файлов и направлений их использования. Например, UNIX-каталог /Ып содержит все системные исполняемые профаммы, такие как cat, т, sort и т.д. Каталог может быть создан в UNIX с помощью команды mkdir. Следующая UNIX-команда создаст каталог /usr/foo/xyz, если он не существует: mkdir /usr/foo/xyz Каталог в ОС UNIX считается пустым, если он не содержит никаких других файлов, кроме ссылок на текущий и родительский каталоги, и может быть удален посредством команды rmdir Следующая UNIX-команда удаляет каталог /usr/foo/xyz, если он существует и если он пустой: rmdir /usr/foo/xyz Содержимое каталога в UNIX может быть отображено на экране с помошью команды Is. Блок-ориентированный файл устройства служит для представления физического устройства, которое передает данные блоками. Примерами блок-ориентированных усфойств являются дисководы жестких дисков и дисководы гибких дисков. Байт-ориентированный файл устройства служит для представления физического устройства, которое передает данные побайтово. Примерами байт-ориентированных устройств могут служить построчно-пе-чатающие принтеры, модемы, консоли. Физическое устройство могут представлять и блок-ориентированные, и байт-ориентированные файлы, что обеспечивает доступ к ним различными методами. Например, байт-ориентированный файл жесткого диска используется для передачи данных между процессом и диском без обработки (не поблочно). Прикладная профамма может выполнять операции чтения и записи с файлом устройства так же, как с обычным файлом, а операционная система будет автоматически вызывать соответствующий драйвер устройства для выполнения фактической передачи данных между физическим устройством и приложением. Обратите внимание на то, что на физическое устройство могут ссылаться и байт-ориентированный, и блок-ориентированный файлы. Прикладная профамма таким образом выбирает необходимый метод обмена данными с этим устройством (посимвольный, через байт-ориентированный файл устройства, или поблочный, через блок-ориентированный файл). Файл устройства создается в ОС UNIX с помощью команды mknod. Ниже указанная команда создает байт-ориентированный файл устройства с именем /dev/cdskO, старшим и младшим номерами устройства являются 115 и 5 соответственно. Аргумент с определяет, что файл, который будет создан, является байт-ориентированным файлом устройства: mknod /dev/cdsk с 115 5 Старший номер устройства - это индекс в таблице ядра, которая содержит адреса всех драйверов устройств, известных системе. Всякий раз, когда процесс читает данные из файла устройства или записывает в него, ядро, используя старший номер файла, выбирает и вызывает драйвер устройства для осуществления фактического обмена данными с физическим устройством. Младший номер устройства - это целое значение, которое передается как аргумент в драйвер устройства при его вызове. Младший номер устройства сообщает драйверу устройства, с каким конкретно физическим устройством он взаимодействует (драйвер может обслуживать физические устройства нескольких типов) и какая схема буферизации ввода-вывода должна использоваться при обмене. Драйверы устройств инсталлируются либо поставщиками физических устройств, либо поставщиками операционных систем. При инсталляции драйвера устройства ядро операционной системы должно быть реконфигу-рировано. Эта схема позволяет расширять операционную систему при необходимости ввода устройств новых типов, которые становятся нужны пользователю. Блок-ориентированный файл устройства также создается в ОС UNIX командой mknod, однако вторым аргументом команды mknod должен быть не с, а Ь. Аргумент b показывает, что создаваемый файл является блок-ориентированным файлом устройства. С помошью приведенной ниже команды создается блок-ориентированный файл устройства /dev/bdsk со старшим и младшим номерами устройства - 287 и 101 соответственно: mknod /dev/bdsk Ь 287 101 В ОС UNIX команда mknod должна выполняться привилегированным пользователем. Кроме того, в UNIX все файлы усфойств, как правило, помещаются в каталог /dev или в его подкаталог.
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |