Читать книгу 📗 "Linux программирование в примерах - Роббинс Арнольд"
Строки 99–100 создают набор сигналов, представляющих
SIGCHLDСтроки 104–109 создают пять порожденных процессов, каждый из которых засыпает на три секунды. По ходу дела они обновляют массив
kidsnkidsСтрока 111 дает затем потомкам шанс завершиться, заснув на еще больший промежуток времени. (Это не гарантирует, что порожденные процессы завершатся, но шансы довольно велики.)
Наконец, строки 113–114 выводят сообщение и приостанавливаются, заменив маску сигналов процесса, блокирующую
SIGCHLDSIGCHLD$ <b>ch10-reap1</b> /* Запуск программы */waiting for signalEntered childhandler reaped process 23937 reaped process 23938 reaped process 23939 reaped process 23940 reaped process 23941Exited childhandlerОбработчик сигнала собирает сведения о потомках за один проход.
Следующая программа,
ch10-reap2.cch10-reap1.cSIGCHLDSIGCHLD1 /* ch10-reap2.c — демонстрирует управление SIGCHLD, один сигнал на потомка */2 /* ...не изменившийся код пропущен... */1213 pid_t kids[MAX_KIDS];14 size_t nkids = 0;15 size_t kidsleft = 0; /* <<< Добавлено */16 /* ...не изменившийся код пропущен... */4142 /* childhandler --- перехват SIGCHLD, опрос всех доступных потомков */4344 void childhandler(int sig)45 {46 int status, ret;47 int i;48 char buf[100];49 static const char entered[] = "Entered childhandlern";50 static const char exited[] = "Exited childhandlern";5152 write(1, entered, strlen(entered));53 for (i = 0; i < nkids; i++) {54 if (kids[i] == NOT_USED)55 continue;5657 retry:58 if ((ret = waitpid(kids[i], &status, WNOHANG)) == kids[i]) {59 strcpy(buf, "treaped process ");60 strcat(buf, format_num(ret));61 strcat(buf, "n");62 write(1, buf, strlen(buf));63 kids[i] = NOT_USED;64 kidsleft--; /* <<< Добавлено */65 } else if (ret == 0) { /* ...не изменившийся код пропущен... */80 write(1, exited, strlen(exited));81 }Это идентично предыдущей версии за тем исключением, что у нас есть новая переменная,
kidsleft83 /* main --- установка относящейся к порожденным процессам сведений и сигналов, создание порожденных процессов */8485 int main(int argc, char **argv)86 { /* ...не изменившийся код пропущен... */100101 sigemptyset(&childset);102 sigaddset(&childset, SIGCHLD);103104 /* sigprocmask(SIG_SETMASK, &childset, NULL); /* блокирование в коде main */105106 for (nkids = 0; nkids < 5; nkids++) {107 if ((kids[nkids] = fork()) == 0) {108 sleep(3);109 _exit(0);110 }111 kidsleft++; /* <<< Added */112 }113114 /* sleep(5); /* дать потомкам шанс завершиться */115116 while (kidsleft > 0) { /* <<< Добавлено */117 printf("waiting for signalsn");118 sigsuspend(&emptyset);119 } /* <<< Добавлено */120121 return 0;122 }Здесь код также почти идентичен. Строки 104 и 114 закомментированы из предыдущей версии, а строки 111, 116 и 119 добавлены. Удивительно, при запуске поведение меняется в зависимости от версии ядра!
$ <b>uname -a</b> /* Отобразить версию системы */Linux example1 2.4.20-8 #1 Thu Mar 13 17:54:28 EST 2003 i686 i686 i386 GNU/Linux