Рефераты. Администрирование локальных сетей p> $ A | B записанной на языке СиШелл.
Файл, выделяемый под pipe, имеет ограниченный размер (и поэтому обычно целиком оседает в буферах в памяти машины). Как только он заполнен целиком
- процесс, пишущий в трубу вызовом write, приостанавливается до появления свободного места в трубе. Это может привести к возникновению тупиковой ситуации, если писать программу неаккуратно. Пусть процесс A является сыном процесса B, и пусть процесс B издает вызов wait, не закрыв канал conn[0].
Процесс же A очень много пишет в трубу conn[1]. Мы получаем ситуацию, когда оба процесса спят:
A потому что труба переполнена, а процесс B ничего из нее не читает, так как ждет окончания A;
B потому что процесс-сын A не окончился, а он не может окончиться пока не допишет свое сообщение.
Решением служит запрет процессу B делать вызов wait до тех пор, пока он не прочитает ВСЮ информацию из трубы (не получит EOF). Только сделав после этого close(conn[0]); процесс B имеет право сделать wait.
Если процесс B закроет свою сторону трубы close(conn[0]) прежде, чем процесс A закончит запись в нее, то при вызове write в процессе A, система пришлет процессу A сигнал SIGPIPE - "запись в канал, из которого никто не читает".

Нелокальный переход.

Теперь поговорим про нелокальный переход. Стандартная функция setjmp позволяет установить в программе "контрольную точку"*, а функция longjmp осуществляет прыжок в эту точку, выполняя за один раз выход сразу из нескольких вызванных функций (если надо)*. Эти функции не являются системными вызовами, но поскольку они реализуются машинно-зависимым образом, а используются чаще всего как реакция на некоторый сигнал, речь о них идет в этом разделе. Вот как, например, выглядит рестарт программы по прерыванию с клавиатуры:

#include

#include jmp_buf jmp; /* контрольная точка */

/* прыгнуть в контрольную точку */ void onintr(nsig){ longjmp(jmp, nsig); }

main(){ int n; n = setjmp(jmp); /* установить контрольную точку */ if( n ) printf( "Рестарт после сигнала %dn", n); signal (SIGINT, onintr); /* реакция на сигнал */ printf("Началиn");

...

} setjmp возвращает 0 при запоминании контрольной точки. При прыжке в контрольную точку при помощи longjmp, мы оказываемся снова в функции setjmp, и эта функция возвращает нам значение второго аргумента longjmp, в этом примере - nsig.
Прыжок в контрольную точку очень удобно использовать в алгоритмах перебора с возвратом (backtracking): либо - если ответ найден - прыжок на печать ответа, либо если ветвь перебора зашла в тупик - прыжок в точку ветвления и выбор другой альтернативы. При этом можно делать прыжки и в рекурсивных вызовах одной и той же функции: с более высокого уровня рекурсии в вызов более низкого уровня (в этом случае jmp_buf лучше делать автоматической переменной - своей для каждого уровня вызова функции).

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

shmget создает новый сегмент разделяемой памяти или находит существующий сегмент с тем же ключом shmat подключает сегмент с указанным дескриптором к виртуальной памяти обращающегося процесса shmdt отключает от виртуальной памяти ранее подключенный к ней сегмент с указанным виртуальным адресом начала shmctl служит для управления параметрами, связанными с существующим сегментом После подключения сегмента разделяемой памяти к виртуальной памяти процесса, он может обращаться к соответствующим элементам памяти с использованием обычных машинных команд чтения и записи shmid = shmget(key, size, flag); size определяет желаемый размер сегмента в байтах если в таблице разделяемой памяти находится элемент, содержащий заданный ключ, и права доступа не противоречат текущим характеристикам процесса, то значением системного вызова является дескриптор существующего сегмента реальный размер сегмента можно узнать с помощью системного вызова shmctl иначе создается новый сегмент с размером не меньше установленного в системе минимального размера сегмента разделяемой памяти и не больше установленного максимального размера создание сегмента не означает немедленного выделения под него основной памяти откладывается до выполнения первого системного вызова подключения сегмента к виртуальной памяти некоторого процесса при выполнении последнего системного вызова отключения сегмента от виртуальной памяти соответствующая основная память освобождается virtaddr = shmat(id, addr, flags); id - это ранее полученный дескриптор сегмента addr - желаемый процессом виртуальный адрес, который должен соответствовать началу сегмента в виртуальной памяти virtaddr - реальный виртуальный адрес начала сегмента не обязательно совпадает со значением прямого параметра addr если addr == 0, ядро выбирает наиболее удобный виртуальный адрес начала сегмента shmdt(addr); addr - виртуальный адрес начала сегмента в виртуальной памяти, ранее полученный от системного вызова shmat shmctl(id, cmd, shsstatbuf); cmd идентифицирует требуемое конкретное действие важна функция уничтожения сегмента разделяемой памяти

Семафоры

Обобщение классического механизма семафоров общего вида Диекстры
Целесообразность обобщения сомнительна
Обычно использовался облегченный вариант двоичных семафоров
Известен алгоритм реализации семафоров общего вида на основе двоичных
Семафор в ОС UNIX: значение семафора идентификатор процесса, который хронологически последним работал с семафором число процессов, ожидающих увеличения значения семафора число процессов, ожидающих нулевого значения семафора
Три системных вызова: semget для создания и получения доступа к набору семафоров semop для манипулирования значениями семафоров semctl для выполнения управляющих операций над набором семафоров id = semget(key, count, flag); key, flag и id - обычный смысл count - число семафоров в наборе семафоров, обладающих одним и тем же ключом индивидуальный семафор идентифицируется дескриптором набора семафоров и номером семафора в наборе если набор семафоров с указанным ключом уже существует, то число семафоров в группе можно узнать с помощью системного вызова semctl oldval = semop(id, oplist, count); id - дескриптор группы семафоров oplist - массив описателей операций над семафорами группы count - размер этого массива возвращается значение последнего обработанного семафора
Элемент массива oplist: номер семафора в указанном наборе семафоров операция флаги
Если проверка прав доступа проходит нормально указанные в массиве oplist номера семафоров не выходят за пределы общего размера набора семафоров для каждого элемента массива oplist значение семафора изменяется в соответствии со значением поля "операция"
Значение поля операции положительно значение семафора увеличивается на единицу все процессы, ожидающие увеличения значения семафора, активизируются
(пробуждаются)
Значение поля операции равно нулю если значение семафора равно нулю, выбирается следующий элемент массива oplist иначе число процессов, ожидающих нулевого значения семафора, увеличивается на единицу обратившийся процесс переводится в состояние ожидания (усыпляется)
Значение поля операции отрицательно
(1) его абсолютное значение меньше или равно значению семафора это отрицательное значение прибавляется к значению семафора если значение семафора стало нулевым, то ядро активизирует все процессы, ожидающие нулевого значения этого семафора
(2) значение семафора меньше абсолютной величины поля операции число процессов, ожидающих увеличения значения семафора увеличивается на единицу текущий процесс откладывается
Стремление добиться возможности избегать тупиковых ситуаций
Системный вызов semop выполняется как атомарная операция
Флаг IPC_NOWAIT заставляет ядро ОС UNIX не блокировать текущий процесс лишь сообщать в ответных параметрах о возникновении ситуации, приведшей бы к блокированию процесса semctl(id, number, cmd, arg); id - это дескриптор группы семафоров number - номер семафора в группе cmd - код операции arg - указатель на структуру, содержимое которой интерпретируется в зависимости от операции
Можно уничтожить индивидуальный семафор в указанной группе

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

Четыре системных вызова: msgget для образования новой очереди сообщений или получения дескриптора существующей очереди msgsnd для посылки сообщения (его постановки в очередь сообщений) msgrcv для приема сообщения (выборки сообщения из очереди) msgctl для выполнения управляющих действий msgqid = msgget(key, flag);
Сообщения хранятся в виде связного списка
Декскриптор очереди сообщений - индекс в массиве заголовков очередей сообщений
В заголовке очереди хранятся: указатели на первое и последнее сообщение в данной очереди число сообщений общий размер в байтах сообщений, находящихся в очереди идентификаторы процессов, которые последними послали или приняли сообщение через данную очередь временные метки последних выполненных операций msgsnd, msgrsv и msgctl

msgsnd(msgqid, msg, count, flag); msg - это указатель на структуру, содержащую целочисленный тип сообщения и символьный массив

. count - задает размер сообщения в байтах flag определяет действия ядра при выходе за пределы допустимых размеров внутренней буферной памяти
Условия успешной постановки сообщения в очередь: процесс должен иметь право на запись в очередь длина сообщения не должна превосходить верхний предел общая длина сообщений не должна превосходить установленного предела тип сообщения должен быть положительным целым числом
Процесс продолжает свое выполнение
Ядро активизирует (пробуждает) все процессы, ожидающие поступления сообщений из очереди
Превышается верхний предел суммарной длины сообщений обратившийся процесс откладывается до разгрузки очереди но есть флаг IPC_NOWAIT (как для семафоров) count = msgrcv(id, msg, maxcount, type, flag); msg - указатель на структуру данных в адресном пространстве пользователя для размещения принятого сообщения maxcount - размер области данных (массива байтов) в структуре msg type специфицирует тип сообщения, которое желательно принять flag указывает ядру, что следует предпринять, если в указанной очереди сообщений отсутствует сообщение с указанным типом count - реальное число байтов, переданных пользователю
Значением параметра type является нуль выбирается первое сообщение копируется в заданную пользовательскую структуру данных процессы, отложенные по причине переполнения очереди сообщений, активизируются если значение параметра maxcount оказывается меньше реального размера сообщения, ядро не удаляет сообщение из очереди и возвращает код ошибки если задан флаг MSG_NOERROR, то выборка сообщения производится, и в буфер пользователя переписываются первые maxcount байтов сообщения
Значение type есть положительное целое число выбирается первое сообщение с таким же типом
Значение type есть отрицательное целое число выбирается первое сообщение, значение типа которого меньше или равно абсолютному значению type
В очереди отсутствуют сообщения, соответствующие спецификации type процесс откладывается до появления в очереди требуемого сообщения но есть флаг IPC_NOWAIT msgctl(id, cmd, mstatbuf); опрос состояния описателя очереди сообщений изменение его состояния уничтожение очереди сообщений

Страницы: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25



2012 © Все права защищены
При использовании материалов активная ссылка на источник обязательна.