Linux программирование в примерах
Linux программирование в примерах читать книгу онлайн
В книге рассмотрены вопросы, связанные с программированием под Linux: файловый ввод/вывод, метаданные файлов, основы управления памятью, процессы и сигналы, пользователи и группы, вопросы интернационализации и локализации, сортировка, поиск и многие другие. Много внимания уделено средствам отладки, доступным под GNU Linux. Все темы иллюстрируются примерами кода, взятого из V7 UNIX и GNU. Эта книга может быть полезна любому, кто интересуется программированием под Linux.
Внимание! Книга может содержать контент только для совершеннолетних. Для несовершеннолетних чтение данного контента СТРОГО ЗАПРЕЩЕНО! Если в книге присутствует наличие пропаганды ЛГБТ и другого, запрещенного контента - просьба написать на почту [email protected] для удаления материала
37 /* childhandler --- перехват SIGCHLD, сбор данных лишь об одном потомке */3839 void childhandler(int sig, siginfo_t *si, void *context)40 {41 int status, ret;42 int i;43 char buf[100];44 static const char entered[] = "Entered childhandlern";45 static const char exited[] = "Exited childhandlern";4647 write(1, entered, strlen(entered));48 retry:49 if ((ret = waitpid(si->si_pid, &status, WNOHANG)) == si->si_pid) {50 strcpy(buf, "treaped process ");51 strcat(buf, format_num(si->si_pid));52 strcat(buf, "n");53 write(1, buf, strlen(buf));54 manage(si); /* обработать то, что произошло */55 } else if (ret > 0) {56 strcpy(buf, "treaped unexpected pid ");57 strcat(buf, format_num(ret));58 strcat(buf, "n");59 write(1, buf, strlen(buf));60 goto retry; /* почему бы нет? */61 } else if (ret == 0) {62 strcpy(buf, "tpid ");63 strcat(buf, format_num(si->si_pid));64 strcat(buf, " changed statusn");65 write(1, buf, strlen(buf));66 manage(si); /* обработать то, что произошло */67 } else if (ret == -1 && errno == EINTR) {68 write(1, "tretryingn", 10);69 goto retry;70 } else {71 strcpy(buf, "twaitpid() failed: ");72 strcat(buf, strerror(errno));73 strcat(buf, "n");74 write(1, buf, strlen(buf));75 }7677 write(1, exited, strlen(exited));78 }Обработчик сигнала похож на показанные ранее. Обратите внимание на список аргументов (строка 39) и на то, что нет цикла.
Строки 49–54 обрабатывают завершение процесса, включая вызов
manage()Строки 55–60 обрабатывают случай неожиданного завершения потомка. Этого не должно происходить, поскольку обработчику сигнала передается специфическая для определенного порожденного процесса информация.
Строки 61–66 представляют для нас интерес: возвращаемое значение для изменений состояния равно 0.
manage()Строки 67–69 обрабатывают прерывания, а строки 70–75 распоряжаются ошибками
80 /* child --- что сделать в порожденном процессе */8182 void child(void)83 {84 raise(SIGCONT); /* должен быть проигнорирован */85 raise(SIGSTOP); /* заснуть, родитель снова разбудит */86 printf("t---> child restarted <---n");87 exit(42); /* нормальное завершение, дать возможность родителю получить значение */88 }Функция
child()SIGCONTCLD_CONTINUEDSIGSTOPCLD_STOPPED90 /* main --- установка относящихся к порожденному процессу сведений и сигналов, создание порожденного процесса */9192 int main(int argc, char **argv)93 {94 pid_t kid;95 struct sigaction sa;96 sigset_t childset, emptyset;9798 sigemptyset(&emptyset);99100 sa.sa_flags = SA_SIGINFO;101 sa.sa_sigaction = childhandler;102 sigfillset(&sa.sa_mask); /* при вызове обработчика все заблокировать */103 sigaction(SIGCHLD, &sa, NULL);104105 sigemptyset(&childset);106 sigaddset(&childset, SIGCHLD);107108 sigprocmask(SIG_SETMASK, &childset, NULL); /* блокировать его в коде main */109110 if ((kid = fork()) == 0)111 child();112113 /* здесь выполняется родитель */114 for (;;) {115 printf("waiting for signalsn");116 sigsuspend(&emptyset);
