- •Введение
- •Глава 1. Фундаментальные концепции unix Систем
- •Программы, процессы и потоки
- •Сигналы
- •Идентификаторы процессов, группы процессов и сеансы
- •Система прав
- •Другие атрибуты процесса
- •Межпроцессное взаимодействие
- •Использование системных вызовов
- •Краткие описания функций и обработка ошибок
- •Контрольные вопросы
- •Литература
- •Глава 2. Базовые операции ввода-вывода
- •Файловые операции ввода - вывода
- •Стандартные дескрипторы
- •Системные вызовы open и creat
- •Системный вызов umask
- •Системный вызов unlink
- •Текущая позиция в файле
- •Системный вызов write
- •2.8. Системный вызов read
- •2.9. Системный вызов close
- •2.10. Системный вызов lseek
- •2.11. Системные вызовы pread и pwrite
- •2.12. Системные вызовы truncate и ftruncate
- •Контрольные вопросы
- •Литература
- •Глава 3. Дополнительные операции файлового ввода_вывода
- •Низкоуровневый доступ к файловой системе
- •Жесткие и символические ссылки
- •Системный вызов getcwd
- •Отображение метаданных файла
- •Системные вызовы getpwuid, getgrgid и getlogin
- •Каталоги
- •Системные вызовы chdir и fchdir
- •Системные вызовы mkdir и rmdir
- •Контрольные вопросы
- •Литература
- •Глава 4. Процессы и потоки
- •4.1. Среда окружения
- •Системный вызов exec
- •Системный вызов fork
- •Завершение процесса и системные вызовы exit
- •Системные вызовы wait, waitpid и waitid
- •Получение и изменение идентификаторов пользователя и группы
- •Получение и изменение приоритета
- •Контрольные вопросы
- •Литература
- •Глава 5. Механизмы межпроцессного взаимодействия
- •5.1. Каналы
- •5.2. Системные вызовы dup и dup2
- •5.3. Двунаправленное взаимодействие с использованием однонаправленных каналов
- •Контрольные вопросы
- •Литература
- •Глава 6.Механизмы взаимодействия процессов
- •Именованные каналы (fifo)
- •Системные вызовы для работы с очередями сообщений posix
- •Семафоры
- •Системные вызовы для работы с общей памятью posix
- •Контрольные вопросы
- •Литература
- •Глава 7.Сетевое взаимодействие и сокеты
- •Основные системные вызовы для работы с сокетами, образующими логические соединения
- •Обслуживание нескольких клиентов
- •Адресация сокетов
- •In_port_t sin_port; /* номер порта (uint16_t) */
- •In_addr_t s_addr; /* адрес iPv4 (uint32_t) */
- •Домен адресов af_inet6
- •In_port_t sin6_port; /* номер порта (uint16_t) */
- •Доменная система именования
- •Параметры сокетов
- •Контрольные вопросы
- •Литература
- •Глава 8.Сигналы и таймеры
- •Введение в сигналы
- •Жизненный цикл сигналов
- •Типы сигналов
- •Системный вызов sigaction
- •Контрольные вопросы
- •Литература
- •Заключение
- •Список литературы
- •Глава 2. Базовые операции ввода-вывода 14
- •Глава 3. Дополнительные операции файлового ввода_вывода 25
- •Глава 6. Механизмы взаимодействия процессов 58
Системные вызовы wait, waitpid и waitid
Системные вызовы wait, waitpid и waited ожидают, пока дочерний процесс не изменит свое состояние (приостановка, возобновление или завершение) и возвращают его вызывающей программе:
waitpid - ожидает изменения состояния дочернего процесса
#include <sys/wait.h>
pid_t waitpid (
pid_t pid, /* идентификатор процесса или группы процессов */
int *statusp, /* указатель на статус или NUUL */
int options /* флаги */
);
/* В случае успеха возвращает идентификатор процесса или 0, -1 в случае ошибки (код ошибки - в переменной errno) */
Аргумент pid принимает следующие значения: > 0 (ожидать изменение состояния дочернего процесса с указанным идентификатором); -1 (ожидать изменение состояния любого дочернего процесса); 0 (ожидать изменение состояния любого дочернего процесса, принадлежащего к той же группе процессов, что и вызывающий); < -1 (ожидать изменение состояния любого дочернего процесса, принадлежащего к группе процессов с идентификатором pid).
На выходе из waitpid вызывающий процесс получает идентификатор процесса-потомка в виде возвращаемого значения, чей идентификатор совпал с аргументом pid. Ноль возвращается только в том случае, когда был установлен флаг WNOHANG. Допускается ожидать изменения состояния только прямых потомков, порожденных системным вызовом fork. Ожидание процессов-внуков не допускается, даже если их родители (прямые потомки вызывающего процесса) к моменту вызова уже завершили свою работу. Осиротевшие процессы передаются под опекунство специального системного процесса. Как правило, процессы-предки заинтересованы в получении информации о состоянии своих потомков – в противном случае процессы-потомки по завершении превращаются в зомби и пребывают в таком виде, пока не завершит работу родительский процесс. Тогда системный процесс, ставший приемным родителем, сможет обратиться к вызову wait и удалить зомбированный процесс.
Системный вызов waitpid может вернуть состояние изменившего его дочернего процесса только один раз (такой дочерний процесс называется ожидаемый). Если в одной точке программы было получено состояние потомка и вдруг обнаружилось, что это не тот потомок, которого ожидали, то нет никакого способа вернуть результат обратно в систему, чтобы другой waitpid мог получить его.
Если к моменту вызова waitpid имеется ожидаемый дочерний процесс, соответствующий заданному аргументу pid, управление в вызывающую программу возвращается немедленно. Если потомок найден, но еще не изменил свое состояние, системный вызов waitpid блокируется до появления подходящего ожидаемого потомка. Если потомок не был найден, вызывающей программе возвращается значение -1 и код ошибки ECHILD. Это может произойти потому, что аргумент pid задан неправильно или процесс-потомок перестал быть ожидаемым, то есть его состояние уже было получено.
Если в качестве аргумента statusp передан непустой указатель, то по заданному адресу записывается код состояния потомка. Он представляет собой комбинацию аргумента системного вызова _exit или exit и числа, описывающего причину завершения или приостановки.
Последний аргумент options может содержать один или более флагов, объединенных операцией ИЛИ: WCONTINUED (сообщать о возобновлении работы потомка); WNOHANG (не ожидать потомка, если он еще не изменил свое состояние, возвращать 0 вместо идентификатора процесса); WUNTRACED (сообщать о приостановке в работе потомка). Приведем несколько примеров, использующих системный вызов waitpid:
waitpid(pid, &status, 0) /* ожидать завершения потомка pid и получить код завершения*/
pid = waitpid(-1, NULL, 0) /* ожидать завершения любого из потомков, без получения кода завершения*/
Второй представитель группы системных вызовов wait представляет собой упрощенный вариант waitpid и эквивалентен вызову последнего с аргументом pid, равным -1, и с аргументом options равным нулю:
wait - ожидает завершения дочернего процесса
#include <sys/wait.h>
pid_t wait (
int *statusp, /* указатель на статус или NUUL */
);
/* Возвращает идентификатор процесса или -1 в случае ошибки (код ошибки - в переменной errno) */
Системный вызов wait довольно редко используется в больших приложениях, поскольку ожидает завершения любого потомка. Когда функция создает дочерний процесс и пытается его подождать, она может случайно дождаться завершения совершенно другого потомка, внося беспорядок в ход исполнения всего приложения в целом. Для таких случаев waitpid подходит гораздо лучше, так как он позволяет ожидать конкретный процесс или, по крайней мере, члена группы процессов.