Архитектура Unix

       

. Алгоритм функции wait



Рисунок 7.16. Алгоритм функции wait

алгоритм wait входная информация: адрес переменной для хранения значения status, возвращаемого завершающимся процессом выходная информация: идентификатор потомка и код возврата функции exit { если (процесс, вызвавший функцию wait, не имеет потом- ков) возвратить (ошибку); для (;;) /* цикл с внутренним циклом */ { если (процесс, вызвавший функцию wait, имеет потом- ков, прекративших существование) { выбрать произвольного потомка; передать его родителю информацию об использова- нии потомком ресурсов центрального процессора; освободить в таблице процессов место, занимае- мое потомком; возвратить (идентификатор потомка, код возврата функции exit, вызванной потомком); } если (у процесса нет потомков) возвратить ошибку; приостановиться с приоритетом, допускающим прерыва- ния (до завершения потомка); } }


Например, если пользователь запускает программу, приведенную на Рисунке 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. Разница между двумя способами запуска программы состоит в том, что в первом случае процесс-родитель ждет завершения любого из потомков, в то время как во втором случае он ждет, пока завершатся все его потомки.



Содержание раздела