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

         

. Пример использования функции



Рисунок 7.17. Пример использования функции wait и игнорирования сигнала "гибель потомка"

#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); }


В ранних версиях системы UNIX функции exit и wait не использовали и не рассматривали сигнал типа "гибель потомка". Вместо посылки сигнала функция exit возобновляла выполнение родительского процесса. Если родительский процесс при выполнении функции wait приостановился, он возобновляется, находит потомка, прекратившего существование, и возвращает управление. В противном случае возобновления не происходит; процесс-родитель обнаружит "погибшего" потомка при следующем обращении к функции wait. Точно так же и процесс начальной загрузки (init) может приостановиться, используя функцию wait, и завершающиеся по exit процессы будут возобновлять его, если он имеет усыновленных потомков, прекращающих существование.

В такой реализации функций exit и wait имеется одна нерешенная проблема, связанная с тем, что процессы, прекратившие существование, нельзя убирать из системы до тех пор, пока их родитель не исполнит функцию wait. Если процесс создал множество потомков, но так и не исполнил функцию wait, может произойти переполнение таблицы процессов из-за наличия потомков, прекративших существование с помощью функции exit. В качестве примера рассмотрим текст программы планировщика процессов, приведенный на Рисунке 7.18. Процесс производит считывание данных из файла стандартного ввода до тех пор, пока не будет обнаружен конец файла, создавая при каждом исполнении функции read нового потомка. Однако, процесс-родитель не дожидается завершения каждого потомка, поскольку он стремится запускать процессы на выполнение как можно быстрее, тем более, что может пройти довольно много времени, прежде чем процесс-потомок завершит свое выполнение. Если, обратившись к функции signal, процесс распорядился игнорировать сигналы типа "гибель потомка", ядро будет очищать записи, соответствующие прекратившим существование процессам, автоматически. Иначе в конечном итоге из-за таких процессов может произойти переполнение таблицы.



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