DAY12 (Старые версии Машбука или нечто подобное)

2019-05-08СтудИзба

Описание файла

Файл "DAY12" внутри архива находится в следующих папках: Старые версии Машбука или нечто подобное, Лекции (Машечкин 1998). Документ из архива "Старые версии Машбука или нечто подобное", который расположен в категории "". Всё это находится в предмете "операционные системы" из 3 семестр, которые можно найти в файловом архиве МГУ им. Ломоносова. Не смотря на прямую связь этого архива с МГУ им. Ломоносова, его также можно найти и в других разделах. .

Онлайн просмотр документа "DAY12"

Текст из документа "DAY12"

4

Лекция №12

Лекция 12

Продолжим рассмотрение темы «Взаимодействие процессов». На прошлой лекции мы начали говорить о сигналах. Мы выяснили, что сигналы есть средства взаимодействия между процессами, выделили три причины, по которым может произойти возникновение сигнала: это событие, произошедшее внутри процесса, событие, связанное с приходом некоторой информации от устройства и передача сигнала от одного процесса к другому. Мы обсудили тот факт, что установка игнорирования и default-обработки сигнала действует на протяжении всей программы до того места, пока мы сами не переопределим эту установку, в отличие от того случая, когда мы устанавливаем пользовательскую установку сигнала. В этом случае после передачи сигнала реакция на ее возникновение автоматически устанавливается как SIG_DEF (Небольшое замечание: в нашем машинном зале установка пользовательской реакции на сигнал также является долговременной). Мы выяснили, что не все сигналы можно обрабатывать или игнорировать (например, сигнал 9 SIG_KILL).

Рассмотрим в качестве примера работы сигналов программу-шутку «Будильник»:

main()

{

char s[80];

signal(SIG_ALR, alrm);

alarm(5); // Заводим будильник

printf(«Введите имя\n»);

for (;;)

{

printf («Имя:»);

if (gets(s) != NULL) break;

}

printf («Ok!\n»);

}

alrm ()

{

printf («\nЖду имя\n»);

alarm(5); //Заводим будильник

signal (SIG_ALR,alrm);

}

В начале программы мы устанавливаем реакцию на сигнал SIG_ALRM - функцию alrm, далее средствами ОС «заводим» будильник, запрашиваем имя и ожидаем ввода строки. Если ввод задерживается, то будет вызвана функция alrm, которая напомнит, что программа «ожидает» ввод имени, опять заведет будильник и поставит себя на обработку сигнала SIG_ALRM опять. Так будет продолжаться до тех пор, пока не будет введена строка.

Еще раз отметим, что одноразово устанавливается только «свой» обработчик. Default-обработчик и игнорирование устанавливаются для многоразового использования, то есть их не надо каждый раз подтверждать после обработки сигнала.

Рассмотрим две функции, которые необходимы для организации взаимодействия между процессами:

  1. int kill(int pid,sig);

Функция kill осуществляет передачу сигнала от процесса к процессу. Она работает следующим образом: осуществляется попытка передачи сигнала, значение которого равно sig, процессу с номером pid . Соответственно, сигнал может быть передан в рамках процессов, принадлежащих одной группе (Заметим, что это требование нарушается, когда сигнал посылается ядром системы!). Функция возвращает -1, если сигнал по какой-либо причине передать не удалось, конкретную причину можно найти в errno. С помощью функции kill мы получаем возможность проверять существует ли процесс с заданным идентификатором. Если sig положить равным 0, то это тестовый сигнал, который определяет можно ли передать процессу сигнал; если можно, то kill возвратит число, отличное от -1. Если в качестве параметра pid мы задаем 0, то сигнал передается всем процессам, входящим в группу.

  1. int wait(int *wait_ret);

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

а) если процесс-сын приостановлен, тогда старшие 8 бит wait_ret есть код сигнала, который получил процесс-сын, а младшие биты имеют значение 0177 (процесс сын может быть приостановлен в случае трассировки или получения сигнала);

б) если сыновний процесс завершился по функции exit, тогда младшие 8 бит равны 0, а старшие 8 бит равны коду, который был передан функции exit в качестве параметра;
в) если процесс сын завершился по причине возникновения у него необрабатываемого сигнала, то старшие 8 бит равны 0, а младшие являются номером сигнала, который завершил процесс.

Заметим, что функция wait имеет несколько режимов работы. Вообще говоря, в стандартном режиме работы функция wait ожидает возникновения события в одном из сыновних процессов, но можно установить такой режим работы wait, что эта функция не будет ожидать возникновения события (вернет «-1» , в errno - причина), либо такой режим, что wait возвратит информацию о последнем происшедшем в процессе-сыне событии.

Рассмотрим еще один пример, программу «Будильник», но будильник уже многопроцессный:

alr()

{

printf(“\n Быстрее!!! \n”);

signal (SIG_ALRM, alr);

}

main ()

{

char s[80]; int pid;

signal(SIG_ALRM, alr);

if (pid=fork()) for (;;)

{

sleep(5); //приостанавливаем процесс на 5 сек.

kill(pid, SIG_ALRM); //отправляем сигнал SIG_ALRM сыну

}

for (;;)

{

printf(“имя?”);

if gets(s)!=NULL) break;

}

printf(“OK!\n”);

kill(getpid(), SIG_KILL); // убиваем зациклившегося отца

}

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

Механизм сигналов является достаточно мощным, но явно не достаточным для эффективной работы процессов средством мультипроцессирования UNIXа. Одним из недостатков этого средства является тот факт, что набор сигналов ограничен, да и к тому же как уже было сказано выше, не всеми сигналами из этого набора может пользоваться программист при создании своих приложений. В UNIXе имеется еще одно достаточно мощное средство взаимодействия процессов - это каналы.

Механизм каналов или PIPEов.

На концептуальном уровне канал - это некая сущность, с которой ассоциированы два файловых дескриптора. Через один можно читать информацию из сущности, через другой -

записывать информацию в сущность. Очередности записи/чтения определятся по правилу fifo (первым пришел - первым ушел).

Для каждого открытого канала выделяется определенный кусок ОЗУ фиксированного размера. (Можно настроить UNIX так, что будет выделятся общий кусок памяти для всех PIPEов). В некоторых системах место под PIPEы можно отводить на ВЗУ.

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

Возможны ситуации, когда процесс хочет записать что-либо в канал, но места в канале уже нет, либо когда процесс хочет считать информацию из пустого канала. Что при этом происходит? Ответ прост. Система реагирует на эти ситуации опционально, т.е. можно настроить систему так, что в обоих случаях процесс будет приостановлен до тех пор, пока место в канале не освободится, соответственно, пока в канале не появится информация; можно настроить систему и так, что реакцией на эти ситуации будет не ожидание, а возврат некоторого кода ответа.

Для порождения канала в системе используется функция pipe:

int pipe (pipes);

int pipes[2];

Нулевой элемент массива после обращения к функции pipe получит ФД для чтения, первый элемент - на запись. Если нет свободных ФД, то эта функция возвратит -1. Количество ФД, открытых в одном процессе, лимитировано. Существует важное правило: для считывающего дескриптора при чтении не будет получен признак конца файла, пока не будет закрыт, хотя бы один ФД записи!

Проиллюстрируем наше изучение каналов небольшим примером:

char *s = «Это пример »;

char b[80];

int pipes[2];

pipe(pipes);

write(pipes[1],s, strlen(s)+1);

read(pipes[0],b, strlen(s)+1);

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

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

int dup(fd); int dup2(fd, to_fd);

int fd; int fd, to_fd;

Аргументом функции dup является файловый дескриптор открытого в данном процессе файла. Работа функции dup заключается в том, что осуществляется дублирование ФД в некоторый свободный ФД (вообще говоря в первый свободный ФД), т.е. можно как бы продублировать открытый файл. Эта функция возвращает -1 в том случае, если обращение не проработало, и значение большее или равное нулю, если работа функции успешно завершена.

Функция dup2 дублирует файловый дескриптор fd в некоторый файловый дескриптор с номером to_fd. При этом если при обращении к этой функции ФД, в который мы хотим продублировать, был занят, то происходит закрытие файла, работающего с этим ФД, и переопределение этого ФД.

Теперь перейдем непосредственно к рассмотрению обещанного примера:

main()

{

int fd[2];

pipe(fd); // в отцовском процессе открываем канал

if (fork()) // у процесса-сына будут те же ФД, что и у отца

{// в отце:

dup2(fd[1],1); // заменяем стандартный вывод выводом в канал

close(fd[1]); // закрываем дескрипторы канала

close(fd[0]); // теперь весь вывод будет происходить в канал

execl(«/bin/ls»,«ls»,(char*)0); // заменяем тело отца на ls

}

// в сыне:

dup2(fd[0],0); // все делаем аналогично

close(fd[0]);

close(fd[1]);

execl(«/bin/wc»,«wc»,(char*)0);

}

Этот пример связывает конвейером две команды: ls и wc. Команда ls выводит содержимое каталога, а команда wc подсчитывает количество строк. Результатом выполнения нашей программы будет подсчет строк, выведенных командой ls.

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

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

В заключении сегодняшней лекции хочу сделать одно важное замечание. Все примеры, которые разбираются на лекции, Вам рекомендуется проверить и разобраться с ними в машинном зале ...

Свежие статьи
Популярно сейчас
Почему делать на заказ в разы дороже, чем купить готовую учебную работу на СтудИзбе? Наши учебные работы продаются каждый год, тогда как большинство заказов выполняются с нуля. Найдите подходящий учебный материал на СтудИзбе!
Ответы на популярные вопросы
Да! Наши авторы собирают и выкладывают те работы, которые сдаются в Вашем учебном заведении ежегодно и уже проверены преподавателями.
Да! У нас любой человек может выложить любую учебную работу и зарабатывать на её продажах! Но каждый учебный материал публикуется только после тщательной проверки администрацией.
Вернём деньги! А если быть более точными, то автору даётся немного времени на исправление, а если не исправит или выйдет время, то вернём деньги в полном объёме!
Да! На равне с готовыми студенческими работами у нас продаются услуги. Цены на услуги видны сразу, то есть Вам нужно только указать параметры и сразу можно оплачивать.
Отзывы студентов
Ставлю 10/10
Все нравится, очень удобный сайт, помогает в учебе. Кроме этого, можно заработать самому, выставляя готовые учебные материалы на продажу здесь. Рейтинги и отзывы на преподавателей очень помогают сориентироваться в начале нового семестра. Спасибо за такую функцию. Ставлю максимальную оценку.
Лучшая платформа для успешной сдачи сессии
Познакомился со СтудИзбой благодаря своему другу, очень нравится интерфейс, количество доступных файлов, цена, в общем, все прекрасно. Даже сам продаю какие-то свои работы.
Студизба ван лав ❤
Очень офигенный сайт для студентов. Много полезных учебных материалов. Пользуюсь студизбой с октября 2021 года. Серьёзных нареканий нет. Хотелось бы, что бы ввели подписочную модель и сделали материалы дешевле 300 рублей в рамках подписки бесплатными.
Отличный сайт
Лично меня всё устраивает - и покупка, и продажа; и цены, и возможность предпросмотра куска файла, и обилие бесплатных файлов (в подборках по авторам, читай, ВУЗам и факультетам). Есть определённые баги, но всё решаемо, да и администраторы реагируют в течение суток.
Маленький отзыв о большом помощнике!
Студизба спасает в те моменты, когда сроки горят, а работ накопилось достаточно. Довольно удобный сайт с простой навигацией и огромным количеством материалов.
Студ. Изба как крупнейший сборник работ для студентов
Тут дофига бывает всего полезного. Печально, что бывают предметы по которым даже одного бесплатного решения нет, но это скорее вопрос к студентам. В остальном всё здорово.
Спасательный островок
Если уже не успеваешь разобраться или застрял на каком-то задание поможет тебе быстро и недорого решить твою проблему.
Всё и так отлично
Всё очень удобно. Особенно круто, что есть система бонусов и можно выводить остатки денег. Очень много качественных бесплатных файлов.
Отзыв о системе "Студизба"
Отличная платформа для распространения работ, востребованных студентами. Хорошо налаженная и качественная работа сайта, огромная база заданий и аудитория.
Отличный помощник
Отличный сайт с кучей полезных файлов, позволяющий найти много методичек / учебников / отзывов о вузах и преподователях.
Отлично помогает студентам в любой момент для решения трудных и незамедлительных задач
Хотелось бы больше конкретной информации о преподавателях. А так в принципе хороший сайт, всегда им пользуюсь и ни разу не было желания прекратить. Хороший сайт для помощи студентам, удобный и приятный интерфейс. Из недостатков можно выделить только отсутствия небольшого количества файлов.
Спасибо за шикарный сайт
Великолепный сайт на котором студент за не большие деньги может найти помощь с дз, проектами курсовыми, лабораторными, а также узнать отзывы на преподавателей и бесплатно скачать пособия.
Популярные преподаватели
Добавляйте материалы
и зарабатывайте!
Продажи идут автоматически
5224
Авторов
на СтудИзбе
428
Средний доход
с одного платного файла
Обучение Подробнее