Все о моделировании в Компас-3D LT
   Главная Статьи Файлы Форум Ссылки Категории новостей
Август 21 2019 08:47:18   
Навигация
Главная
Статьи
Файлы
FAQ
Форум
Ссылки
Категории новостей
Обратная связь
Фото галерея
Поиск
Разное
Карта Сайта
Популярные статьи
Что необходимо ... 65535
Учимся удалять!... 23655
4.12.1 Професси... 22365
Примеры, синони... 21282
FAST (методика ... 19237
Просмотр готовы... 18955
Декартовы коорд... 17349
Просмотр готовы... 15793
Работа с инстру... 11931
Что такое САПР 11339
Сейчас на сайте
Гостей: 1
На сайте нет зарегистрированных пользователей

Пользователей: 9,955
новичок: Logyattella
Друзья сайта
Ramblers Top100
Рейтинг@Mail.ru

Реклама
Выполняем курсовые и лабораторные по разным языкам программирования
Подробнее - курсовые и лабораторные на заказ по Delphi
Turbo Pascal, Assembler, C, C++, C#, Visual Basic, Java, GPSS, Prolog
7.4 ОЖИДАНИЕ ЗАВЕРШЕНИЯ ВЫПОЛНЕНИЯ ПРОЦЕССА
Процесс может синхронизировать продолжение своего выполнения с моментом завершения потомка, если воспользуется системной функцией wait. Синтаксис вызова функции:
pid = wait(stat_addr);
где pid — значение кода идентификации (PID) прекратившего свое существование потомка, stat_addr — адрес переменной целого типа, в которую будет помещено возвращаемое функцией exit значение, в пространстве задачи.
main() {
int child;
if ((child = fork()) == 0) {
printf("PID потомка %d\n", getpid());
pause(); /* приостанов выполнения до получения сигнала */
}
/* родитель */
printf("PID потомка %d\n", child);
exit(child);
}
Рисунок 7.15. Пример использования функции exit
Алгоритм функции wait приведен на Рисунке 7.16. Ядро ведет поиск потомков процесса, прекративших существование, и в случае их отсутствия возвращает ошибку. Если потомок, прекративший существование, обнаружен, ядро передает его код идентификации и значение, возвращаемое через параметр функции exit, процессу, вызвавшему функцию wait. Таким образом, через параметр функции exit (status) завершающийся процесс может передавать различные значения, в закодированном виде содержащие информацию о причине завершения процесса, однако на практике этот параметр используется по назначению довольно редко. Ядро передает в соответствующие поля, принадлежащие пространству родительского процесса, накопленные значения продолжительности исполнения процесса-потомка в режиме ядра и в режиме задачи и, наконец, освобождает в таблице процессов место, которое в ней занимал прежде прекративший существование процесс. Это место будет предоставлено новому процессу.
Если процесс, выполняющий функцию wait, имеет потомков, продолжающих существование, он приостанавливается до получения ожидаемого сигнала. Ядро не возобновляет по своей инициативе процесс, приостановившийся с помощью функции wait: такой процесс может возобновиться только в случае получения сигнала. На все сигналы, кроме сигнала «гибель потомка», процесс реагирует ранее рассмотренным образом. Реакция процесса на сигнал «гибель потомка» проявляется по-разному в зависимости от обстоятельств:
• По умолчанию (то есть если специально не оговорены никакие другие действия) процесс выходит из состояния останова, в которое он вошел с помощью функции wait, и запускает алгоритм issig для опознания типа поступившего сигнала. Алгоритм issig (Рисунок 7.7) рассматривает особый случай поступления сигнала типа «гибель потомка» и возвращает «ложь». Поэтому ядро не выполняет longjump из функции sleep, а возвращает управление функции wait. Оно перезапускает функцию wait, находит потомков, прекративших существование (по крайней мере, одного), освобождает место в таблице процессов, занимаемое этими потомками, и выходит из функции wait, возвращая управление процессу, вызвавшему ее.
• Если процессы принимает сигналы данного типа, ядро делает все необходимые установки для запуска пользовательской функции обработки сигнала, как и в случае поступления сигнала любого другого типа.
• Если процесс игнорирует сигналы данного типа, ядро перезапускает функцию wait, освобождает в таблице процессов место, занимаемое потомками, прекратившими существование, и исследует оставшихся потомков.
алгоритм wait
входная информация: адрес переменной для хранения значения status, возвращаемого завершающимся процессом
выходная информация: идентификатор потомка и код возврата функции exit
{
if (процесс, вызвавший функцию wait, не имеет потомков) return (ошибку);
for (;;) { /* цикл с внутренним циклом */
if (процесс, вызвавший функцию wait, имеет потомков, прекративших существование) {
выбрать произвольного потомка;
передать его родителю информацию об использовании потомком ресурсов центрального процессора;
освободить в таблице процессов место, занимаемое потомком;
return (идентификатор потомка, код возврата функции exit, вызванной потомком);
}
if (у процесса нет потомков) return ошибку;
приостановиться с приоритетом, допускающим прерывания (до завершения потомка);
}
}
Рисунок 7.16. Алгоритм функции wait
Например, если пользователь запускает программу, приведенную на Рисунке 7.17, с параметром и без параметра, он получит разные результаты. Сначала рассмотрим случай, когда пользователь запускает программу без параметра (единственный параметр — имя программы, то есть argc равно 1). Родительский процесс порождает 15 потомков, которые в конечном итоге завершают свое выполнение с кодом возврата i, номером процесса в порядке очередности создания. Ядро, исполняя функцию wait для родителя, находит потомка, прекратившего существование, и передает родителю его идентификатор и код возврата функции exit. При этом заранее не известно, какой из потомков будет обнаружен. Из текста программы, реализующей системную функцию exit, написанной на языке Си и включенной в библиотеку стандартных подпрограмм, видно, что программа запоминает код возврата функции exit в битах 8-15 поля ret_code и возвращает функции wait идентификатор процесса-потомка. Таким образом, в ret_code хранится значение, равное 256*i, где i — номер потомка, а в ret_val заносится значение идентификатора потомка.
Если пользователь запускает программу с параметром (то есть argc › 1), родительский процесс с помощью функции signal делает распоряжение игнорировать сигналы типа «гибель потомка». Предположим, что родительский процесс, выполняя функцию wait, приостановился еще до того, как его потомок произвел обращение к функции exit: когда процесс-потомок переходит к выполнению функции exit, он посылает своему родителю сигнал «гибель потомка»; родительский процесс возобновляется, поскольку он был приостановлен с приоритетом, допускающим прерывания. Когда так или иначе родительский процесс продолжит свое выполнение, он обнаружит, что сигнал сообщал о «гибели» потомка; однако, поскольку он игнорирует сигналы этого типа и не обрабатывает их, ядро удаляет из таблицы процессов запись, соответствующую прекратившему существование потомку, и продолжает выполнение функции wait так, словно сигнала и не было. Ядро выполняет эти действия всякий раз, когда родительский процесс получает сигнал типа «гибель потомка», до тех пор, пока цикл выполнения функции wait не будет завершен и пока не будет установлено, что у процесса больше потомков нет. Тогда функция wait возвращает значение, равное -1. Разница между двумя способами запуска программы состоит в том, что в первом случае процесс-родитель ждет завершения любого из потомков, в то время как во втором случае он ждет, пока завершатся все его потомки.
#include ‹signal.h›
main(argc, argv)
int argc;
char *argv[];
{
int i, ret_val, ret_code;
if (argc ›= 1) signal(SIGCLD, SIG_IGN); /* игнорировать гибель потомков */
for (i = 0; i ‹ 15; i++) if (fork() == 0) {
/* процесс-потомок */
printf("процесс-потомок %x\n", getpid());
exit(i);
}
ret_val = wait(&ret_code);
printf("wait ret_val %x ret_code %x\n", ret_val, ret_code);
}
Рисунок 7.17. Пример использования функции wait и игнорирования сигнала «гибель потомка»
В ранних версиях системы UNIX функции exit и wait не использовали и не рассматривали сигнал типа «гибель потомка». Вместо посылки сигнала функция exit возобновляла выполнение родительского процесса. Если родительский процесс при выполнении функции wait приостановился, он возобновляется, находит потомка, прекратившего существование, и возвращает управление. В противном случае возобновления не происходит; процесс-родитель обнаружит «погибшего» потомка при следующем обращении к функции wait. Точно так же и процесс начальной загрузки (init) может приостановиться, используя функцию wait, и завершающиеся по exit процессы будут возобновлять его, если он имеет усыновленных потомков, прекращающих существование.
В такой реализации функций exit и wait имеется одна нерешенная проблема, связанная с тем, что процессы, прекратившие существование, нельзя убирать из системы до тех пор, пока их родитель не исполнит функцию wait. Если процесс создал множество потомков, но так и не исполнил функцию wait, может произойти переполнение таблицы процессов из-за наличия потомков, прекративших существование с помощью функции exit. В качестве примера рассмотрим текст программы планировщика процессов, приведенный на Рисунке 7.18. Процесс производит считывание данных из файла стандартного ввода до тех пор, пока не будет обнаружен конец файла, создавая при каждом исполнении функции read нового потомка. Однако, процесс-родитель не дожидается завершения каждого потомка, поскольку он стремится запускать процессы на выполнение как можно быстрее, тем более, что может пройти довольно много времени, прежде чем процесс-потомок завершит свое выполнение. Если, обратившись к функции signal, процесс распорядился игнорировать сигналы типа «гибель потомка», ядро будет очищать записи, соответствующие прекратившим существование процессам, автоматически. Иначе в конечном итоге из-за таких процессов может произойти переполнение таблицы.
#include ‹signal.h›
main(argc, argv) {
char buf[256];
if (argc != 1) signal(SIGCLD, SIG_IGN); /* игнорировать гибель потомков */
while (read(0, buf, 256))
if (fork() == 0) {
/* здесь процесс-потомок обычно выполняет какие-то операции над буфером (buf) */
exit(0);
}
}
Рисунок 7.18. Пример указания причины появления сигнала «гибель потомков»
Комментарии
Нет комментариев.
Добавить комментарий
Пожалуйста залогиньтесь для добавления комментария.
Рейтинги
Рейтинг доступен только для пользователей.

Пожалуйста, залогиньтесь или зарегистрируйтесь для голосования.

Нет данных для оценки.
Гость
Имя

Пароль



Вы не зарегистрированны?
Нажмите здесь для регистрации.

Забыли пароль?
Запросите новый здесь.
Случайные статьи
2.4.3 Блоковые коды
Просмотр готовых м...
Обобщенные модели
Сервисное программ...
3.2.2. Сетевое обо...
Вывод на семантич...
Глава 2. Беспровод...
7.4.2. Организа...
Метод доступа в се...
Глава вторая. СИЛ...
Программное обеспе...
2.3.2.1 Сигналы те...
Декартовы координа...
4.12.3.1 Поколения...
2.7 Сети PDH и SO...
5.16.1 Целостность...
Процессное управле...
Отзывы о книге Сет...
4.12.3.4 Структурн...
10.1.1 Конфигураци...
Глава 19. GSM/GPS-...
Подтип сущности
3.4 ЧТЕНИЕ И ЗАПИС...
ЦЕЛИ КАЖДОЙ ГРУ...
Настройки телефона...
Выводы
1.1. Зрелые и незр...
Встроенная карта
12.1 ПРОБЛЕМЫ, СВ...
Одноранговые сети
Известные объекты
Глава 1. MacCentre...
Компьютерные файлы
2.4.2 Логическое к...
Виды связи и режим...
1.4 ФУНКЦИИ ОПЕРАЦ...
Необходимые предпо...
ГЛАВА 6. СТРУКТУРА...
NMEA Monitor
1. Продукции типа...
Мини-чат
Вам необходимо залогиниться.

Нет присланных сообщений.
Copyright © 2009