Взаимодействие между процессами

Операционная система UNIX в полной мере отвечает требованиям технологии клиент-сервер. Эта универсальная модель служит основой построения любых сколь угодно сложных систем, в том числе и сетевых. Разработчики СУБД, коммуника­ционных систем, систем электронной почты, банковских систем и т. д. во всем мире широко используют технологию клиент-сервер. Для построения программных систем, работающих по принципам модели «клиент-сервер», в UNIX существуют следующие механизмы: - сигналы; - семафоры; - программные каналы; - очереди сообщений; - сегменты разделяемой памяти; - вызовы удаленных процедур.

Многие из этих механизмов нам уже знакомы, поэтому рассмотрим их вкратце. Для более глубокого изучения этих вопросов можно рекомендовать известную работу [43].

Сигналы

Если рассматривать выполнение процесса на виртуальном компьютере, который предоставляется каждому пользователю, то в такой системе должна существовать система прерываний, отвечающая стандартным требованиям:

- обработка исключительных ситуаций;

- средства обработки внешних и внутренних прерываний;

- средства управления системой прерываний (маскирование и демаскирование).

Всем этим требованиям в UNIX отвечает механизм сигналов, который позволяет не только воспринимать и обрабатывать сигналы, но и порождать их и посылать на другие машины (процессы). Сигналы могут быть синхронными, когда инициатор сигнала — сам процесс, и асинхронными, когда инициатор сигнала — интерактив­ный пользователь, сидящий за терминалом. Источником асинхронных сигналов может быть также ядро, когда оно контролирует определенные состояния аппара­туры, рассматриваемые как ошибочные.

Сигналы можно рассматривать как простейшую форму взаимодействия между про­цессами. Они используются для передачи от одного процесса другому или от ядра ОС какому-либо процессу уведомления о возникновении определенного события.

Семафоры

Механизм семафоров, реализованный в UNIX-системах, является обобщением классического механизма семафоров, предложенного известным голландским спе-

Взаимодействие между процессами - student2.ru 330________________ Глава 10. Краткий обзор современных операционных систем

циалистом профессором Дейкстрой. Семафор в операционной системе семейства UNIX состоит из следующих элементов:

- значения семафора;

- идентификатора процесса, который хронологически последним работал с се­мафором;

- числа процессов, ожидающих увеличения значения семафора;
- числа процессов, ожидающих нулевого значения семафора.

Для работы с семафорами имеются следующие три системных вызова: - semget — создание и получение доступа к набору семафоров; - semop — манипулирование значениями семафоров (именно этот системный вызов позволяет с помощью семафоров организовать синхронизацию процес­сов);

- semctl — выполнение разнообразных управляющих операций над набором се­
мафоров.

Системный вызов semget имеет следующий синтаксис:

id = semget(key. count, flag);

Здесь параметры key и flag определяют ключ объекта и дополнительные флаги. Параметр count задает число семафоров в наборе семафоров, обладающих одним и тем же ключом. После этого индивидуальный семафор идентифицируется деск­риптором набора семафоров и номером семафора в этом наборе. Если к моменту выполнения системного вызова semget набор семафоров с указанным ключом уже существует, то обращающийся процесс получит соответствующий дескриптор, но так и не узнает о реальном числе семафоров в группе (хотя позже это все-таки можно узнать с помощью системного вызова semctl). Основным системным вызовом для манипулирования семафором является semop:

oldval = semopdd. oplist, count):

Здесь id — это ранее полученный дескриптор группы семафоров, oplist — массив описателей операций над семафорами группы, a count — размер этого массива. Значение, возвращаемое системным вызовом, является значением последнего об­работанного семафора. Каждый элемент массива oplist имеет следующую структуру:

- номер семафора в указанном наборе семафоров; - операция; - флаги.

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

- Если значение поля операции положительно, то значение семафора увеличи­
вается на единицу, а все процессы, ожидающие увеличения значения семафо­
ра, активизируются (пробуждаются — в терминологии UNIX).




Взаимодействие между процессами - student2.ru Семейство операционных систем UNIX____________________________________ 331

О Если значение поля операции равно нулю и значение семафора также равно нулю, выбирается следующий элемент массива oplist. Если же значение поля операции равно нулю, а значение семафора отлично от нуля, то ядро увеличи­вает на единицу число процессов, ожидающих нулевого значения семафора, причем обратившийся процесс переводится в состояние ожидания (засыпает — в терминологии UNIX).

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

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

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

Системный вызов semctl имеет следующий формат:

semctKid. number, cmd, arg):

Здесь id — это дескриптор группы семафоров, number — номер семафора в группе, cmd — код операции, arg — указатель на структуру, содержимое которой интерпре­тируется по-разному в зависимости от операции. В частности, с помощью вызова semctl можно уничтожить индивидуальный семафор в указанной группе. Однако детали этого системного вызова настолько громоздки, что лучше рекомендовать в случае необходимости обращаться к технической документации используемого варианта операционной системы.

Программные каналы

Мы уже познакомились с программными каналами в главе 7. Рассмотрим этот механизм еще раз, так сказать, в его исходном, изначальном толковании.

Программные каналы (pipes) в системе UNIX являются очень важным средством взаимодействия и синхронизации процессов. Теоретически программный канал

Взаимодействие между процессами - student2.ru 332________________ Глава 10. Краткий обзор современных операционных систем

позволяет взаимодействовать любому числу процессов, обеспечивая дисциплину FIFO (First In First Out — первый пришедший первым и выбывает). Другими сло­вами, процесс, читающий из программного канала, прочитает те данные, которые были записаны в программный канал раньше других. В традиционной реализации программных каналов для хранения данных использовались файлы. В современ­ных версиях операционных систем семейства UNIX для реализации программных каналов применяются другие средства взаимодействия между процессами (в час­тности, очереди сообщений).

В UNIX различаются два вида программных каналов — именованные и неимено­ванные. Именованный программный канал может служить для общения и синх­ронизации произвольных процессов, знающих имя данного программного канала и имеющих соответствующие права доступа. Неименованным программным кана­лом могут пользоваться только породивший его процесс и его потомки (необяза­тельно прямые).

Для создания именованного программного канала (или получения к нему досту­па) используется обычный файловый системный вызов open. Для создания же не­именованного программного канала существует специальный системный вызов pipe (исторически более ранний). Однако после получения соответствующих дескрип­торов оба вида программных каналов используются единообразно с помощью стан­дартных файловых системных вызовов read, write и close.

Системный вызов pipe имеет следующий синтаксис:

pipe(fdptr);

Здесь fdptr — это указатель на массив из двух целых чисел, в который после созда­ния неименованного программного канала будут помещены дескрипторы, пред­назначенные для чтения из программного канала (с помощью системного вызова read) и записи в программный канал (с помощью системного вызова write). Деск­рипторы неименованного программного канала — это обычные дескрипторы фай­лов, то есть такому программному каналу соответствуют два элемента таблицы открытых файлов процесса. Поэтому при последующих системных вызовах read и write процесс совершенно не обязан отличать случай использования программных каналов от случая использования обычных файлов (собственно, на этом и основа­на идея перенаправления ввода-вывода и организации конвейеров).

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

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

Взаимодействие между процессами - student2.ru Семейство операционных систем UNIX___________________________________ 333

Окончание работы процесса с программным каналом (независимо от того, имено­ванный он или не именованный) производится с помощью системного вызова close.

Очереди сообщений

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

- msgget — образование новой очереди сообщений или получение дескриптора существующей очереди;

- msgsnd — отправка сообщения (точнее, его постановка в указанную очередь со­общений);

- msgrcv — прием сообщения (точнее, выборка сообщения из очереди сообщений);

- msgctl — выполнение ряда управляющих действий.

Ядро хранит сообщения в виде связного списка (очереди), а дескриптор очереди сообщений является индексом в массиве заголовков очередей сообщений.

Системный вызов msgget имеет следующий синтаксис:

msgqid = msgget(key. flag):

Здесь параметры key и flag имеют то же значение, что и в вызове semget при запросе семафора.

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

Для отправки сообщения используется системный вызов msgsnd:

msgsnd(msgqid. msg. count, flag):

Здесь msg — указатель на структуру, содержащую определяемый пользователем целочисленный тип сообщения и символьный массив (собственно сообщение); count — размер сообщения в байтах; flag — значение, которое определяет действия ядра при выходе за пределы допустимых размеров внутренней буферной памяти.

Для приема сообщения используется системный вызов msgrcv:

count = msgrcv(id. msg. maxcount, type, flag);

Здесь msg — указатель на структуру данных в адресном пространстве пользовате­ля, предназначенную для размещения принятого сообщения; maxcount — размер области данных (массива байтов) в структуре msg; type — тип сообщения, которое требуется принять; flag — значение, которое указывает ядру, что следует предпри­нять, если в указанной очереди сообщений отсутствует сообщение с указанным типом. Возвращаемое значение системного вызова задает реальное число байтов, переданных пользователю.

Следующий системный вызов служит для опроса состояния описателя очереди сообщений, изменения его состояния (например, изменения прав доступа к очере­ди) и для уничтожения указанной очереди сообщений:

msgctl(id. and. mstatbuf):

Взаимодействие между процессами - student2.ru 334________________ Глава 10. Краткий обзор современных операционных систем

Разделяемая память

Для работы с разделяемой памятью используются четыре системных вызова:

- shmget — создает новый сегмент разделяемой памяти или находит существую­
щий сегмент с тем же ключом;

- shmat — подключает сегмент с указанным дескриптором к виртуальной памяти обращающегося процесса;

- shmdt — отключает от виртуальной памяти ранее подключенный к ней сегмент с указанным виртуальным адресом начала;

- shmctl — служит для управления разнообразными параметрами, связанными с
существующим сегментом.

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

shmid = shmget(key. size, flag);

Параметр size определяет желаемый размер сегмента в байтах. Далее работа про­исходит по общим правилам. Если в таблице разделяемой памяти находится эле­мент, содержащий заданный ключ, и права доступа не противоречат текущим ха­рактеристикам обращающегося процесса, то значением системного вызова является дескриптор существующего сегмента (и обратившийся процесс так и не узнает реального размера сегмента, хотя впоследствии его можно узнать с помощью сис­темного вызова shmctl). В противном случае создается новый сегмент, размер ко­торого не меньше, чем установленный в системе минимальный размер сегмента разделяемой памяти, и не больше, чем установленный максимальный размер. Со­здание сегмента не означает немедленного выделения для него основной памяти. Это действие откладывается до первого системного вызова подключения сегмента к виртуальной памяти некоторого процесса. Аналогично, при выполнении после­днего системного вызова отключения сегмента от виртуальной памяти соответ­ствующая основная память освобождается.

Подключение сегмента к виртуальной памяти выполняется путем обращения к системному вызову shmat:

virtaddr = shmatdd. addr, flags):

Здесь id — ранее полученный дескриптор сегмента; addr— требуемый процессу виртуальный адрес, который должен соответствовать началу сегмента в виртуаль­ной памяти. Значением системного вызова является реальный виртуальный адрес начала сегмента (его значение не обязательно совпадает со значением параметра addr). Если значением addr является нуль, ядро выбирает подходящий виртуаль­ный адрес начала сегмента.

Для отключения сегмента от виртуальной памяти используется системный вызов shmdt:

shmdt(addr):

Взаимодействие между процессами - student2.ru Семейство операционных систем UNIX___________________________________ 335

Здесь addr — виртуальный адрес начала сегмента в виртуальной памяти, ранее по­лученный с помощью системного вызова shmat. При этом система гарантирует (опи­раясь на данные таблицы сегментов процесса), что указанный виртуальный адрес действительно является адресом начала разделяемого сегмента в виртуальной па­мяти данного процесса.

Для управления памятью служит системный вызов shmctl:

shmctKid. cmd, shsstatbuf);

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

Вызовы удаленных процедур

Во многих случаях взаимодействие процессов соответствует отношениям клиент-сервер. Один из процессов (клиент) запрашивает у другого процесса (сервера) некоторую услугу (сервис) и не продолжает свое выполнение до тех пор, пока эта услуга не будет выполнена (то есть пока процесс-клиент не получит соответству­ющие результаты). Видно, что семантически такой режим взаимодействия экви­валентен вызову процедуры. Отсюда и соответствующее название — вызов уда­ленной процедуры (Remote Procedure Call, RPC). Другими словами, процесс обращается к процедуре, которая не принадлежит данному процессу. Она может находиться даже на другом компьютере. Операционная система UNIX по своей «идеологии» идеально подходит для того, чтобц быть сетевой операционной сис­темой, на основе которой можно создавать распределенные системы и организо­вывать распределенные вычисления. Свойства переносимости позволяют созда­вать «операционно-однородные» сети, включающие разнородные компьютеры. Однако остается проблема разного представления данных в компьютерах разной архитектуры. Поэтому одной из основных идей RPC является автоматическое обес­печение преобразования форматов данных при взаимодействии процессов, выпол­няющихся на разнородных компьютерах.

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

Взаимодействие между процессами - student2.ru 336________________ Глава 10, Краткий обзор современных операционных систем

Вызов удаленных процедур включает следующие шаги [39].

1. Процесс-клиент осуществляет вызов локальной процедуры, которую называ­
ют заглушкой (stub). Задача этого модуля-заглушки — принять аргументы, пре­
образовать их в стандартную форму и сформировать сетевой запрос. Упаковка
аргументов и создание сетевого запроса называется сборкой (marshalling).

2. Сетевой запрос пересылается на удаленную систему, где соответствующий мо­
дуль ожидает такой запрос и при его получении извлекает параметры вызова
процедуры, то есть выполняет разборку (unmarshalling), а затем передает их
серверу удаленной процедуры. После выполнения осуществляется обратная
передача.

Операционная система Linux

Linux — это современная UNIX-подобная операционная система для персональ­ных компьютеров и рабочих станций, удовлетворяющая стандарту POSIX.

Как известно, Linux — это свободно распространяемая версия UNIX-систем, кото­рая первоначально разрабатывалась Линусом Торвальдсом ([email protected]) в университете Хельсинки (Финляндия). Он предложил разрабатывать ее совместно и выдвинул условие, согласно которому исходные коды являются от­крытыми, любой может их использовать и изменять, но при этом обязан оставить открытым и свой код, внесенный в тот или иной модуль системы. Все компоненты системы, включая исходные тексты, распространяются с лицензией на свободное копирование и установку для неограниченного числа пользователей.

Таким образом, система Linux была создана с помощью многих программистов и эн­тузиастов UNIX-систем, общающихся между собой через Интернет. К данному проекту добровольно подключились те, кто имеет достаточно навыков и способ­ностей развивать систему. Большинство программ Linux разработаны в рамках проекта GNU из Free Software Foundation (Кембридж, штат Массачусетс). Но в него внесли свою лепту и многие программисты со всего мира.

Изначально система Linux создавалась как «самодельная» UNIX-подобная реали­зация для машин типа IBM PC с процессором i80386. Однако вскоре Linux стала настолько популярна и ее поддержало такое большое число компаний, что в насто­ящее время имеются реализации этой операционной системы практически для всех типов процессоров и компьютеров на их основе. На базе Linux создаются и встро­енные системы, и суперкомпьютеры. Система поддерживает кластеризацию и боль­шинство современных интерфейсов и технологий.

Большинство свойств Linux присущи другим реализациям UNIX, кроме того, име­ются некоторые уникальные свойства. Этот раздел представляет собой лишь крат­кий обзор этих свойств.

Linux — это полноценная многозадачная многопользовательская операционная система (точно так же, как и все другие версии UNIX). Это означает, что одновре­менно много пользователей могут работать на одной машине, параллельно выпол­няя множество программ. Поскольку при работе за персональным компьютером практически никто не подключает к нему дополнительные терминалы (хотя это в

Взаимодействие между процессами - student2.ru Взаимодействие между процессами - student2.ru Семейство операционных систем UNIX___________________________________ 337

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

Mandrake Linux release 9.0 (dolphin) for i586 Kernel 2.4.16-16mdk on an i686 /ttyl Vienna login:

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

При желании открыть второй или последующий сеанс работы на соответствую­щем терминале, пользователь должен нажать комбинацию клавиш Alt+Fi, где i обозначает номер функциональной клавиши и одновременно номер соответству­ющего виртуального терминала. Всего Linux поддерживает до семи терминалов, причем седьмой терминал связан с графическим режимом работы и использова­нием одного из оконных менеджеров. Однако если пользователь работает в графи­ческом режиме, то для перехода в один из алфавитно-цифровых терминалов сле­дует воспользоваться комбинацией клавиш Ctrl+Alt+Fi. В каждом сеансе пользователь может запускать свои задачи.

Система Linux достаточно хорошо совместима с рядом стандартов для UNIX (на­сколько можно говорить о стандартизации UNIX) на уровне исходных текстов, включая IEEE POSIX.l, System V и BSD. Она и создавалась с расчетом на такую совместимость. Большинство свободно распространяемых через Интернет про­грамм для UNIX может быть откомпилировано для Linux практически без особых изменений1. Кроме того, все исходные тексты для Linux, включая ядро, драйверы устройств, библиотеки, пользовательские программы и инструментальные сред­ства распространяются свободно. Другие специфические внутренние черты Linux включают контроль работ по стандарту POSIX (используемый оболочками, таки­ми как csh и bash), псевдотерминалы (pty), поддержку национальных и стандарт­ных раскладок клавиатур динамически загружаемыми драйверами клавиатур.

Linux поддерживает различные типы файловых систем для хранения данных. Не­которые файловые системы, такие как EXT2FS, были созданы специально для Linux. Поддерживаются также другие типы файловых систем, например Minix-1 и Xenix. Кроме того, реализована система управления файлами на основе FAT, по­зволяющая непосредственно обращаться к файлам, находящимся в разделах с этой файловой системой. Поддерживается также файловая система ISO 9660 CD-ROM для работы с дисками CD-ROM. Имеются системы управления файлами и на то­мах с HPFS и NTFS, правда, они работают только на чтение файлов. Созданы ва­рианты системы управления файлами и для доступа к FAT32; эта файловая систе­ма в операционной системе Linux называется VFAT.

Взаимодействие между процессами - student2.ru ' Справедливости ради следует заметить, что в последнее время в Linux наметились тенденции все большего отхода от принятых в семействе UNIX стандартов и увеличения количества различий в разных дистрибутивах Linux. Эти различия распространяются и на структуру каталогов файловой системы, что приводит к определенным проблемам при переносе прикладных программ из одной системы Linux В другую.

Взаимодействие между процессами - student2.ru Взаимодействие между процессами - student2.ru 338________________ Глава 10. Краткий обзор современных операционных систем

Linux, как и все UNIX-системы, поддерживает полный набор протоколов стека TCP/IP для сетевой работы. Программное обеспечение для работы в Интернет/ интранет включает драйверы устройств для многих популярных сетевых адапте­ров технологии Ethernet, протоколы SLIP (Serial Line Internet Protocol), PLIP (Parallel Line Internet Protocol), PPP (Point-to-Point Protocol), NFS (Network File System) и пр. Поддерживается весь спектр клиентов и услуг TCP/IP, таких как FTP, telnet, NNTP и SMTP.

Ядро Linux сразу было создано с учетом возможностей защищенного режима 32-разрядных процессоров 80386 и 80486 фирмы Intel. В частности, в Linux использу­ется парадигма описания памяти в защищенном режиме и другие новые свойства процессоров с архитектурой ia32. Для защиты пользовательских программ друг от друга и операционной системы от них Linux работает исключительно в защищен­ном режиме1, реализованном в процессорах фирмы Intel. В защищенном режиме только программный код, исполняющийся в нулевом кольце защиты, имеет не­посредственный доступ к аппаратным ресурсам компьютера — памяти и устрой­ствам ввода-вывода. Пользовательские и системные обрабатывающие программы работают в третьем кольце защиты. Они обращаются к аппаратным ресурсам ком­пьютера исключительно через системные подпрограммы, функционирующие в нулевом кольце защиты. Таким образом, пользовательским программам предо­ставляются только те услуги, которые реализованы разработчиками операцион­ной системы. При этом системные подпрограммы обеспечивают выполнение только тех функций, которые безопасны с точки зрения операционной системы.

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

В отличие от старых версий UNIX, в которых задачи выгружались во внешнюю память на магнитных дисках целиком, ядро Linux использует аппаратную поддерж­ку процессорами страничного механизма организации виртуальной памяти. Поэто­му в Linux замещаются отдельные страницы. То есть с диска в память загружаются те виртуальные страницы образа, которые сейчас реально требуются, а неиспользу­емые страницы выгружаются на диск в файл подкачки. Возможно разделение стра­ниц кода, то есть использование одной страницы, физически уже один раз загру­женной в память, несколькими процессами. Другими словами, реентерабельность кода, присущая всем UNIX-системам, осталась. В настоящее время имеются ядра для этой системы, оптимизированные для работы с процессорами Intel и AMD

Взаимодействие между процессами - student2.ru 1 Напомним, что только в этом режиме процессоры с архитектурой ia32 используют 32-разрядную адресацию и имеют доступ ко всей оперативной памяти.

Взаимодействие между процессами - student2.ru Семейство операционных систем UNIX___________________________________ 339

последнего поколения, хотя основные архитектурные особенности защищенного режима работы изменились мало. Уже разработаны ядра для работы с 64-разряд­ными процессорами от Intel и AMD.

Ядро также поддерживает универсальный пул памяти для пользовательских про­грамм и дискового кэша. При этом для кэширования может использоваться вся свободная память, и наоборот, требуемый объем памяти, отводимой для кэширо­вания файлов, уменьшается при работе больших программ. Этот механизм, назы­ваемый агрессивным кэшированием, позволяет более эффективно расходовать имеющуюся память и увеличить производительность системы.

Исполняемые программы задействуют динамически связываемые библиотеки (Dynamic Link Library, DLL), то есть эти программы могут совместно использо­вать библиотеку, представленную одним физическим файлом на диске. Это по­зволяет занимать меньше места на диске исполняемым файлам, особенно тем, ко­торые многократно вызывают библиотечные функции. Есть также статические связываемые библиотеки для тех, кто желает пользоваться отладкой на уровне объектных кодов или иметь «полные» исполняемые программы, не нуждающиеся в разделяемых библиотеках. В Linux разделяемые библиотеки динамически свя­зываются во время выполнения, позволяя программисту заменять библиотечные модули своими собственными.

Наши рекомендации