UNIX предоставляет различные механизмы для синхронизации и связи между процессами В этом разделе мы рассмотрим важнейшие из них:
- каналы;
- сообщения;
- разделяемую память;
- семафоры;
- сигналы.
Каналы, сообщения и разделяемая память обеспечивают обмен данными между процессами, в то время как семафоры и сигналы используются для инициации некоторых действий другого процесса.
Каналы
Каналы (pipes) являются одним из наиболее значительных вкладов UNIX в развитие операционных систем. Разработанные на основе концепции сопрограмм [RITC84], каналы представляют собой циклические буфера, которые позволяют двум процессам связываться друг с другом в соответствии с моделью производитель/потребитель. Следовательно, канал — не что иное, как очередь, работающая по принципу "первым вошел — первым вышел", запись в которую осуществляется одним процессом, а чтение — другим.
При создании канала он получает буфер определенного размера. При записи в канал при наличии свободного места соответствующий запрос удовлетворяется немедленно; в противном случае процесс блокируется. Аналогично блокируется процесс, пытающийся прочесть из канала большее количество информации, чем имеющееся в нем; в противном случае запрос на чтение выполняется немедленно. Операционная система обеспечивает взаимоисключения — одновременно доступ к каналу имеет только один процесс.
Существует два типа каналов: именованные и неименованные. Совместно использовать неименованные каналы могут только связанные друг с другом процессы; не связанные друг с другом процессы могут совместно использовать только именованные каналы.
Сообщения
Сообщение представляет собой блок текста определенного типа. UNIX для работы с системой передачи сообщений предоставляет процессам системные вызовы msgsnd и msgrcv. С каждым процессом связана очередь сообщений, функционирующая подобно почтовому ящику.
Указанный отправителем тип сообщения может быть использован получателем как критерий отбора сообщений. Он может получать сообщения либо в соответствии с принципом "первым вошел — первым вышел", либо в соответствии с их типом. При попытке отправить сообщение в заполненную очередь выполнение процесса приостанавливается, так же как и при попытке прочесть сообщение из пустой очереди. Если же процесс пытается прочесть сообщение определенного типа, но такого сообщения в очереди нет, процесс не приостанавливается.
Разделяемая память
Наиболее быстрым видом связи между процессами, обеспечиваемым операционной системой UNIX, является разделяемая память. Это общий блок виртуальной памяти, совместно используемый многими процессами. Процессы читают информацию и записывают ее в разделяемую память с помощью тех же инструкций чтения и записи, что и при работе с другими частями своего виртуального пространства памяти. Права доступа (чтение и запись или только чтение) к разделяемой памяти предоставляются каждому из процессов в отдельности. Взаимоисключения не являются частью механизма разделяемой памяти и должны обеспечиваться процессами, использующими разделяемую память.
Семафоры
Система вызовов семафоров в UNIX System V представляет собой обобщение примитивов wait и signal, определенных в главе 5, "Параллельные вычисления: взаимоисключения и многозадачность". Все требуемые при работе с семафорами операции выполняются ядром автоматически; ни один процесс не может получить доступ к семафору, пока с ним выполняется операция, вызванная другим процессом.
Семафор состоит из следующих элементов.
Текущее значение семафора.
Идентификатор последнего процесса, работавшего с семафором.
Количество процессов, ожидающих, пока значение семафора не превысит
текущее.
Количество процессов, ожидающих, пока значение семафора не станет равным нулю.
С семафором связаны очереди приостановленных процессов.
При создании семафоры принадлежат множествам. Множество может содержать как один так и несколько создаваемых семафоров. Системный вызов semctl позволяет установить значения всех семафоров множества одновременно. Кроме того, имеется системный вызов semop, в качестве аргумента которому передается список операций с семафорами (по одной для каждого семафора из множества). При этом вызове ядро выполняет указанные операции одновременно. Каждая из операций определяется значением sem_op.
Если sem_op положительно, ядро увеличивает значение семафора и активизирует все процессы, ожидающие увеличения значения семафора.
Если sem_op равно 0, ядро проверяет значение семафора. Если оно нулевое,
то ядро переходит к выполнению операций со следующим семафором; в
противном случае количество процессов, ожидающих обнуления семафора,
увеличивается, и процесс приостанавливается до тех пор, пока значение семафора не станет равным нулю.
Если sem_op отрицательно, а его абсолютное значение не превышает значение семафора, ядро добавляет sem_op (отрицательное число!) к значению
семафора. Если полученный результат равен нулю, ядро активизирует все
процессы, ожидавшие обнуления значения семафора.
Если sem_op отрицательно, а его абсолютное значение больше значения семафора, ядро приостанавливает процесс до тех пор, пока значение семафора
не увеличится.
Такое обобщение семафоров обеспечивает значительную гибкость при выполнении синхронизации и координации процессов.
Сигналы
Сигнал представляет собой программный механизм, информирующий процесс о наступлении асинхронного события. Сигнал подобен аппаратному прерыванию, но не использует систему приоритетов, т.е. все сигналы обрабатываются одинаково. Процесс получает сигналы по одному, без специального упорядочения.
Процессы могут посылать сигналы друг другу; в обмене сигналами может принимать участие и ядро. Доставка сигнала выполняется путем обновления поля в таблице процесса, которому послан данный сигнал. Поскольку каждый сигнал соответствует отдельному биту, сигналы одного типа не могут накапливаться в виде очереди. Сигнал обрабатывается сразу же после активизации процесса или возврата его из системного вызова. Процесс может ответить на сигнал выполнением некоторых действий по умолчанию (например, завершением работы), выполнить функцию обработки сигнала или проигнорировать его.
В табл. 6.1 перечислены сигналы UNIX SVR4.
Таблица 6.1. Сигналы UNIX
Значение |
Имя |
Описание |
1 |
SIGHUP |
Завесить; посылается процессу, когда ядро полагает, что пользователь этого процесса выполняет бесполезную работу |
2 |
SIGINT |
Прерывание |
3 |
SIGQUIT |
Выход; посылается пользователем, для того чтобы вызвать остановку процесса и сброс дампа памяти |
4 |
SIGILL |
Некорректная инструкция |
5 |
SIGTRAP |
Запуск кода трассировки процесса |
6 |
SIGIOT |
Инструкция ЮТ |
7 |
SIGEMT |
Инструкция ЕМТ |
8 |
SIGFPT |
Исключение при работе с числами с плавающей точкой |
9 |
SIGKILL |
Прекращение работы процесса |
10 |
SIGBUS |
Ошибка шины |
11 |
SIGSEGV |
Нарушение сегментации; процесс пытается обратиться к ячейке памяти вне своего виртуального адресного пространства |
12 |
SIGSYS |
Неверный аргумент системного вызова |
13 |
SIGPIPE |
Запись в канал, к которому не присоединены процессы, считывающие из него информацию |
14 |
SIGALARM |
Сигнал от часов; используется, когда процесс должен полу-
чить сигнал после определенного периода времени |
15 |
SIGTERM |
Завершение работы программы |
16 |
SIGUSR1 |
Пользовательский сигнал 1 |
17 |
SIGUSR2 |
Пользовательский сигнал 2 |
18 |
SIGCLD |
Завершение дочернего процесса |
19 |
SIGPW |
Сбой питания |