Учебники

Мониторинг дочерних процессов

Как мы уже видели, всякий раз, когда мы создаем дочерний процесс из программы с использованием fork, происходит следующее:

  • Текущий процесс теперь становится родительским процессом
  • Новый процесс становится дочерним процессом

Что произойдет, если родительский процесс завершит свою задачу раньше, чем дочерний процесс, а затем выйдет или завершится? Теперь, кто будет родителем дочернего процесса? Родителем дочернего процесса является процесс init, который является первым процессом, инициирующим все задачи.

Чтобы отслеживать состояние выполнения дочернего процесса, проверять, запущен или остановлен дочерний процесс, или проверять состояние выполнения и т. Д., Используются системные вызовы wait () и их варианты.

Давайте рассмотрим пример программы, в которой родительский процесс не ожидает дочерний процесс, в результате чего процесс init становится новым родителем для дочернего процесса.

Имя файла: parentprocess_nowait.c

#include<stdio.h>

int main() {
   int pid;
   pid = fork();
   
   // Child process
   if (pid == 0) {
      system("ps -ef");
      sleep(10);
      system("ps -ef");
   } else {
      sleep(3);
   }
   return 0;
}

Шаги компиляции и выполнения

UID         PID   PPID  C STIME TTY          TIME CMD
root          1      0  0 Jan20 ?        00:00:00 /bin/sh /usr/bin/mysqld_safe
mysql       101      1  0 Jan20 ?        00:04:41 /usr/libexec/mysqld --basedir=/usr --datadir=/var/lib/mysql --plugin-dir=/usr/lib64/mysql/plugin --user=mysql --log-error=/var/log/mariadb/mariadb.log --pid-file=/run/mariadb/mariadb.pid --socket=/var/lib/mysql/mysql.sock
3108506    5445      0  0 Jan22 ?        00:01:19 [/sbin/klogd -c ] <defunct>
4688328    5446      0  0 Jan22 ?        00:01:19 [/sbin/klogd -c ] <defunct>
4688328   21894      0  0 Jan22 ?        00:01:19 [/sbin/klogd -c ] <defunct>
3108506   21895      0  0 Jan22 ?        00:01:19 [/sbin/klogd -c ] <defunct>
4688328   27309      0  0 Jan22 ?        00:00:00 [/sbin/klogd -c ] <defunct>
3108506   27311      0  0 Jan22 ?        00:00:00 [/sbin/klogd -c ] <defunct>
8295652   32407      0  0 Jan20 ?        00:00:39 /sbin/klogd -c 1 -x -x
4688328   49830      0  0 Jan20 ?        00:00:18 /sbin/klogd -c 1 -x -x
3108506   50854      0  0 Jan20 ?        00:00:18 /sbin/klogd -c 1 -x -x
4688328   64936      0  0 Jan22 ?        00:00:59 [/sbin/klogd -c ] <defunct>
3108506   64937      0  0 Jan22 ?        00:00:59 [/sbin/klogd -c ] <defunct>
4688328   67563      0  0 Jan22 ?        00:00:59 [/sbin/klogd -c ] <defunct>
5942779   68128      0  0 Jan22 ?        00:00:07 /sbin/klogd -c 1 -x -x
3108506   68238      0  0 Jan22 ?        00:00:59 [/sbin/klogd -c ] <defunct>
4688328   68999      0  0 Jan22 ?        00:00:14 [/sbin/klogd -c ] <defunct>
3108506   69212      0  0 Jan22 ?        00:00:14 [/sbin/klogd -c ] <defunct>
4688328   74090      0  0 Jan22 ?        00:00:00 [/sbin/klogd -c ] <defunct>
3108506   74091      0  0 Jan22 ?        00:00:00 [/sbin/klogd -c ] <defunct>
4688328   74298      0  0 Jan22 ?        00:01:19 [/sbin/klogd -c ] <defunct>
3108506   74299      0  0 Jan22 ?        00:01:19 [/sbin/klogd -c ] <defunct>
6327201   74901      0  0 Jan20 ?        00:00:38 /sbin/klogd -c 1 -x -x
6327201   77274      0  0 Jan20 ?        00:00:27 /sbin/klogd -c 1 -x -x
7528790   78621      0  0 Jan20 ?        00:00:33 /sbin/klogd -c 1 -x -x
7528790   80536      0  0 Jan20 ?        00:01:09 [/sbin/klogd -c ] <defunct>
6327201   80542      0  0 Jan20 ?        00:01:09 [/sbin/klogd -c ] <defunct>
4688328   82050      0  0 Jan22 ?        00:01:59 [/sbin/klogd -c ] <defunct>
3108506   82051      0  0 Jan22 ?        00:01:59 [/sbin/klogd -c ] <defunct>
7528790   84116      0  0 Jan20 ?        00:00:27 /sbin/klogd -c 1 -x -x
7528790   84136      0 19 Jan20 ?        21:13:38 /sbin/klogd -c 1 -x -x
7528790   84140      0  0 Jan20 ?        00:00:28 /sbin/klogd -c 1 -x -x
3108506   84395      0  0 Jan22 ?        00:00:29 [/sbin/klogd -c ] <defunct>
4688328   84396      0  0 Jan22 ?        00:00:29 [/sbin/klogd -c ] <defunct>
5942779   84397      0  0 Jan22 ?        00:00:29 [/sbin/klogd -c ] <defunct>
3108506   84928      0  0 Jan22 ?        00:00:29 [/sbin/klogd -c ] <defunct>
4688328   84929      0  0 Jan22 ?        00:00:29 [/sbin/klogd -c ] <defunct>
5942779   84930      0  0 Jan22 ?        00:00:30 [/sbin/klogd -c ] <defunct>
7528790   84970      0  0 Jan20 ?        00:00:34 /sbin/klogd -c 1 -x -x
3108506   85787      0  0 Jan22 ?        00:00:14 [/sbin/klogd -c ] <defunct>
4688328   85789      0  0 Jan22 ?        00:00:14 [/sbin/klogd -c ] <defunct>
5942779   86368      0  0 Jan22 ?        00:00:14 [/sbin/klogd -c ] <defunct>
5942779   86402      0  0 Jan22 ?        00:00:14 [/sbin/klogd -c ] <defunct>
5942779   87027      0  0 Jan22 ?        00:00:14 [/sbin/klogd -c ] <defunct>
7528790   87629      0  0 Jan20 ?        00:00:39 /sbin/klogd -c 1 -x -x
7528790   87719      0  0 Jan20 ?        00:00:27 /sbin/klogd -c 1 -x -x
4688328   88138      0  0 Jan22 ?        00:00:14 [/sbin/klogd -c ] <defunct>
4688328   88140      0  0 Jan22 ?        00:00:14 [/sbin/klogd -c ] <defunct>
5942779   89353      0 99 Jan22 ?        2-07:35:14 /sbin/klogd -c 1 -x -x
5942779   91836      0  0 Jan22 ?        00:00:00 [/sbin/klogd -c ] <defunct>
4688328  125358      0  0 Jan22 ?        00:01:19 [/sbin/klogd -c ] <defunct>
3108506  125359      0  0 Jan22 ?        00:01:19 [/sbin/klogd -c ] <defunct>
4688328  127456      0  0 Jan22 ?        00:01:19 [/sbin/klogd -c ] <defunct>
3108506  127457      0  0 Jan22 ?        00:01:19 [/sbin/klogd -c ] <defunct>
8023807  163891      0  0 05:41 ?        00:00:00 main
8023807  164130      0  0 05:41 ?        00:00:00 sh -c cd /home/cg/root/8023807; timeout 10s main
8023807  164136 164130  0 05:41 ?        00:00:00 timeout 10s main
8023807  164137 164136  0 05:41 ?        00:00:00 main
8023807  164138 164137  0 05:41 ?        00:00:00 main
8023807  164139 164138  0 05:41 ?        00:00:00 ps -ef
UID         PID   PPID  C STIME TTY          TIME CMD
root          1      0  0 Jan20 ?        00:00:00 /bin/sh /usr/bin/mysqld_safe
mysql       101      1  0 Jan20 ?        00:04:41 /usr/libexec/mysqld --basedir=/usr --datadir=/var/lib/mysql --plugin-dir=/usr/lib64/mysql/plugin --user=mysql --log-error=/var/log/mariadb/mariadb.log --pid-file=/run/mariadb/mariadb.pid --socket=/var/lib/mysql/mysql.sock
3108506    5445      0  0 Jan22 ?        00:01:19 [/sbin/klogd -c ] <defunct>
4688328    5446      0  0 Jan22 ?        00:01:19 [/sbin/klogd -c ] <defunct>
4688328   21894      0  0 Jan22 ?        00:01:19 [/sbin/klogd -c ] <defunct>
3108506   21895      0  0 Jan22 ?        00:01:19 [/sbin/klogd -c ] <defunct>
4688328   27309      0  0 Jan22 ?        00:00:00 [/sbin/klogd -c ] <defunct>
3108506   27311      0  0 Jan22 ?        00:00:00 [/sbin/klogd -c ] <defunct>
8295652   32407      0  0 Jan20 ?        00:00:39 /sbin/klogd -c 1 -x -x
4688328   49830      0  0 Jan20 ?        00:00:18 /sbin/klogd -c 1 -x -x
3108506   50854      0  0 Jan20 ?        00:00:18 /sbin/klogd -c 1 -x -x
4688328   64936      0  0 Jan22 ?        00:00:59 [/sbin/klogd -c ] <defunct>
3108506   64937      0  0 Jan22 ?        00:00:59 [/sbin/klogd -c ] <defunct>
4688328   67563      0  0 Jan22 ?        00:00:59 [/sbin/klogd -c ] <defunct>
5942779   68128      0  0 Jan22 ?        00:00:07 /sbin/klogd -c 1 -x -x
3108506   68238      0  0 Jan22 ?        00:00:59 [/sbin/klogd -c ] <defunct>
4688328   68999      0  0 Jan22 ?        00:00:14 [/sbin/klogd -c ] <defunct>
3108506   69212      0  0 Jan22 ?        00:00:14 [/sbin/klogd -c ] <defunct>
4688328   74090      0  0 Jan22 ?        00:00:00 [/sbin/klogd -c ] <defunct>
3108506   74091      0  0 Jan22 ?        00:00:00 [/sbin/klogd -c ] <defunct>
4688328   74298      0  0 Jan22 ?        00:01:19 [/sbin/klogd -c ] <defunct>
3108506   74299      0  0 Jan22 ?        00:01:19 [/sbin/klogd -c ] <defunct>
6327201   74901      0  0 Jan20 ?        00:00:38 /sbin/klogd -c 1 -x -x
6327201   77274      0  0 Jan20 ?        00:00:27 /sbin/klogd -c 1 -x -x
7528790   78621      0  0 Jan20 ?        00:00:33 /sbin/klogd -c 1 -x -x
7528790   80536      0  0 Jan20 ?        00:01:09 [/sbin/klogd -c ] <defunct>
6327201   80542      0  0 Jan20 ?        00:01:09 [/sbin/klogd -c ] <defunct>
4688328   82050      0  0 Jan22 ?        00:01:59 [/sbin/klogd -c ] <defunct>
3108506   82051      0  0 Jan22 ?        00:01:59 [/sbin/klogd -c ] <defunct>
7528790   84116      0  0 Jan20 ?        00:00:27 /sbin/klogd -c 1 -x -x
7528790   84136      0 19 Jan20 ?        21:13:48 /sbin/klogd -c 1 -x -x
7528790   84140      0  0 Jan20 ?        00:00:28 /sbin/klogd -c 1 -x -x
3108506   84395      0  0 Jan22 ?        00:00:29 [/sbin/klogd -c ] <defunct>
4688328   84396      0  0 Jan22 ?        00:00:29 [/sbin/klogd -c ] <defunct>
5942779   84397      0  0 Jan22 ?        00:00:29 [/sbin/klogd -c ] <defunct>
3108506   84928      0  0 Jan22 ?        00:00:29 [/sbin/klogd -c ] <defunct>
4688328   84929      0  0 Jan22 ?        00:00:29 [/sbin/klogd -c ] <defunct>
5942779   84930      0  0 Jan22 ?        00:00:30 [/sbin/klogd -c ] <defunct>
7528790   84970      0  0 Jan20 ?        00:00:34 /sbin/klogd -c 1 -x -x
3108506   85787      0  0 Jan22 ?        00:00:14 [/sbin/klogd -c ] <defunct>
4688328   85789      0  0 Jan22 ?        00:00:14 [/sbin/klogd -c ] <defunct>
5942779   86368      0  0 Jan22 ?        00:00:14 [/sbin/klogd -c ] <defunct>
5942779   86402      0  0 Jan22 ?        00:00:14 [/sbin/klogd -c ] <defunct>
5942779   87027      0  0 Jan22 ?        00:00:14 [/sbin/klogd -c ] <defunct>
7528790   87629      0  0 Jan20 ?        00:00:39 /sbin/klogd -c 1 -x -x
7528790   87719      0  0 Jan20 ?        00:00:27 /sbin/klogd -c 1 -x -x
4688328   88138      0  0 Jan22 ?        00:00:14 [/sbin/klogd -c ] <defunct>
4688328   88140      0  0 Jan22 ?        00:00:14 [/sbin/klogd -c ] <defunct>
5942779   89353      0 99 Jan22 ?        2-07:35:24 /sbin/klogd -c 1 -x -x
5942779   91836      0  0 Jan22 ?        00:00:00 [/sbin/klogd -c ] <defunct>
4688328  125358      0  0 Jan22 ?        00:01:19 [/sbin/klogd -c ] <defunct>
3108506  125359      0  0 Jan22 ?        00:01:19 [/sbin/klogd -c ] <defunct>
4688328  127456      0  0 Jan22 ?        00:01:19 [/sbin/klogd -c ] <defunct>
3108506  127457      0  0 Jan22 ?        00:01:19 [/sbin/klogd -c ] <defunct>
8023807  164138      0  0 05:41 ?        00:00:00 main
8023807  164897 164138  0 05:41 ?        00:00:00 ps -ef

Примечание. Обратите внимание, что PID родительского процесса был 94, а PID дочернего процесса — 95. После выхода из родительского процесса PPID дочернего процесса изменился с 94 на 1 (процесс инициализации).

Ниже приведены варианты системных вызовов для контроля дочернего процесса (ов).

  • Подождите()
  • waitpid ()
  • waitid ()

Системный вызов wait () будет ожидать завершения одного из дочерних элементов и возврата своего состояния завершения в буфер, как объяснено ниже.

#include <sys/types.h>
#include <sys/wait.h>

pid_t wait(int *status);

Этот вызов возвращает идентификатор процесса завершенного дочернего процесса в случае успеха и -1 в случае ошибки. Системный вызов wait () приостанавливает выполнение текущего процесса и ожидает бесконечно, пока один из его дочерних элементов не завершится. Статус завершения от ребенка доступен в статусе.

Давайте изменим предыдущую программу, чтобы родительский процесс теперь ждал дочерний процесс.

/ * Имя файла: parentprocess_waits.c * /

#include<stdio.h>

int main() {
   int pid;
   int status;
   pid = fork();
   
   // Child process
   if (pid == 0) {
      system("ps -ef");
      sleep(10);
      system("ps -ef");
      return 3; //exit status is 3 from child process
   } else {
      sleep(3);
      wait(&status);
      printf("In parent process: exit status from child is decimal %d, hexa %0x\n", status, status);
   }
   return 0;
}

Шаги компиляции и выполнения

UID         PID   PPID  C STIME TTY          TIME CMD
root          1      0  0 Jan20 ?        00:00:00 /bin/sh /usr/bin/mysqld_safe
mysql       101      1  0 Jan20 ?        00:04:42 /usr/libexec/mysqld --basedir=/usr --datadir=/var/lib/mysql --plugin-dir=/usr/lib64/mysql/plugin --user=mysql --log-error=/var/log/mariadb/mariadb.log --pid-file=/run/mariadb/mariadb.pid --socket=/var/lib/mysql/mysql.sock
3108506    5445      0  0 Jan22 ?        00:01:19 [/sbin/klogd -c ] <defunct>
4688328    5446      0  0 Jan22 ?        00:01:19 [/sbin/klogd -c ] <defunct>
4688328   21894      0  0 Jan22 ?        00:01:19 [/sbin/klogd -c ] <defunct>
3108506   21895      0  0 Jan22 ?        00:01:19 [/sbin/klogd -c ] <defunct>
4688328   27309      0  0 Jan22 ?        00:00:00 [/sbin/klogd -c ] <defunct>
3108506   27311      0  0 Jan22 ?        00:00:00 [/sbin/klogd -c ] <defunct>
8295652   32407      0  0 Jan20 ?        00:00:39 /sbin/klogd -c 1 -x -x
4688328   49830      0  0 Jan20 ?        00:00:18 /sbin/klogd -c 1 -x -x
3108506   50854      0  0 Jan20 ?        00:00:18 /sbin/klogd -c 1 -x -x
4688328   64936      0  0 Jan22 ?        00:00:59 [/sbin/klogd -c ] <defunct>
3108506   64937      0  0 Jan22 ?        00:00:59 [/sbin/klogd -c ] <defunct>
4688328   67563      0  0 Jan22 ?        00:00:59 [/sbin/klogd -c ] <defunct>
5942779   68128      0  0 Jan22 ?        00:00:07 /sbin/klogd -c 1 -x -x
3108506   68238      0  0 Jan22 ?        00:00:59 [/sbin/klogd -c ] <defunct>
4688328   68999      0  0 Jan22 ?        00:00:14 [/sbin/klogd -c ] <defunct>
3108506   69212      0  0 Jan22 ?        00:00:14 [/sbin/klogd -c ] <defunct>
4688328   74090      0  0 Jan22 ?        00:00:00 [/sbin/klogd -c ] <defunct>
3108506   74091      0  0 Jan22 ?        00:00:00 [/sbin/klogd -c ] <defunct>
4688328   74298      0  0 Jan22 ?        00:01:19 [/sbin/klogd -c ] <defunct>
3108506   74299      0  0 Jan22 ?        00:01:19 [/sbin/klogd -c ] <defunct>
6327201   74901      0  0 Jan20 ?        00:00:38 /sbin/klogd -c 1 -x -x
6327201   77274      0  0 Jan20 ?        00:00:27 /sbin/klogd -c 1 -x -x
7528790   78621      0  0 Jan20 ?        00:00:33 /sbin/klogd -c 1 -x -x
7528790   80536      0  0 Jan20 ?        00:01:09 [/sbin/klogd -c ] <defunct>
6327201   80542      0  0 Jan20 ?        00:01:09 [/sbin/klogd -c ] <defunct>
4688328   82050      0  0 Jan22 ?        00:01:59 [/sbin/klogd -c ] <defunct>
3108506   82051      0  0 Jan22 ?        00:01:59 [/sbin/klogd -c ] <defunct>
7528790   84116      0  0 Jan20 ?        00:00:27 /sbin/klogd -c 1 -x -x
7528790   84136      0 19 Jan20 ?        21:19:39 /sbin/klogd -c 1 -x -x
7528790   84140      0  0 Jan20 ?        00:00:28 /sbin/klogd -c 1 -x -x
3108506   84395      0  0 Jan22 ?        00:00:29 [/sbin/klogd -c ] <defunct>
4688328   84396      0  0 Jan22 ?        00:00:29 [/sbin/klogd -c ] <defunct>
5942779   84397      0  0 Jan22 ?        00:00:29 [/sbin/klogd -c ] <defunct>
3108506   84928      0  0 Jan22 ?        00:00:29 [/sbin/klogd -c ] <defunct>
4688328   84929      0  0 Jan22 ?        00:00:29 [/sbin/klogd -c ] <defunct>
5942779   84930      0  0 Jan22 ?        00:00:30 [/sbin/klogd -c ] <defunct>
7528790   84970      0  0 Jan20 ?        00:00:34 /sbin/klogd -c 1 -x -x
3108506   85787      0  0 Jan22 ?        00:00:14 [/sbin/klogd -c ] <defunct>
4688328   85789      0  0 Jan22 ?        00:00:14 [/sbin/klogd -c ] <defunct>
5942779   86368      0  0 Jan22 ?        00:00:14 [/sbin/klogd -c ] <defunct>
5942779   86402      0  0 Jan22 ?        00:00:14 [/sbin/klogd -c ] <defunct>
5942779   87027      0  0 Jan22 ?        00:00:14 [/sbin/klogd -c ] <defunct>
7528790   87629      0  0 Jan20 ?        00:00:39 /sbin/klogd -c 1 -x -x
7528790   87719      0  0 Jan20 ?        00:00:27 /sbin/klogd -c 1 -x -x
4688328   88138      0  0 Jan22 ?        00:00:14 [/sbin/klogd -c ] <defunct>
4688328   88140      0  0 Jan22 ?        00:00:14 [/sbin/klogd -c ] <defunct>
5942779   89353      0 99 Jan22 ?        2-07:41:15 /sbin/klogd -c 1 -x -x
5942779   91836      0  0 Jan22 ?        00:00:00 [/sbin/klogd -c ] <defunct>
4688328  125358      0  0 Jan22 ?        00:01:19 [/sbin/klogd -c ] <defunct>
3108506  125359      0  0 Jan22 ?        00:01:19 [/sbin/klogd -c ] <defunct>
4688328  127456      0  0 Jan22 ?        00:01:19 [/sbin/klogd -c ] <defunct>
3108506  127457      0  0 Jan22 ?        00:01:19 [/sbin/klogd -c ] <defunct>
8023807  191762      0  0 05:47 ?        00:00:00 sh -c cd /home/cg/root/8023807; timeout 10s main
8023807  191768 191762  0 05:47 ?        00:00:00 timeout 10s main
8023807  191769 191768  0 05:47 ?        00:00:00 main
8023807  191770 191769  0 05:47 ?        00:00:00 main
8023807  192193      0  0 05:47 ?        00:00:00 sh -c cd /home/cg/root/8023807; timeout 10s main
8023807  192199 192193  0 05:47 ?        00:00:00 timeout 10s main
8023807  192200 192199  0 05:47 ?        00:00:00 main
8023807  192201 192200  0 05:47 ?        00:00:00 main
8023807  192202 192201  0 05:47 ?        00:00:00 ps -ef

Примечание. Несмотря на то, что child возвращает состояние выхода 3, почему родительский процесс видит это как 768. Состояние сохраняется в байте более высокого порядка, поэтому оно хранится в шестнадцатеричном формате как 0X0300, что равно 768 в десятичном виде. Нормальное завершение выглядит следующим образом

Байт высшего порядка (биты с 8 по 15) Байт младшего разряда (биты от 0 до 7)
Статус выхода (от 0 до 255) 0

Системный вызов wait () имеет ограничение, заключающееся в том, что он может ждать только до выхода следующего дочернего элемента. Если нам нужно дождаться определенного дочернего элемента, это невозможно с помощью wait (), однако это возможно с помощью системного вызова waitpid ().

Системный вызов waitpid () будет ожидать завершения определенных дочерних процессов и возвращать свой статус завершения в буфере, как объяснено ниже.

#include <sys/types.h>
#include <sys/wait.h>

pid_t waitpid(pid_t pid, int *status, int options);

Вышеуказанный вызов возвращает идентификатор процесса прерванного дочернего элемента в случае успеха и -1 при ошибке. Системный вызов waitpid () приостанавливает выполнение текущего процесса и ожидает неопределенно долго, пока указанные дочерние элементы (согласно значению pid) не завершатся. Статус завершения от ребенка доступен в статусе.

Значение pid может быть одним из следующих:

  • <-1 — Дождаться любого дочернего процесса, чей идентификатор группы процессов равен абсолютному значению pid.

  • -1 — Ожидание любого дочернего процесса, что соответствует системному вызову wait ().

  • 0 — Ожидание любого дочернего процесса, чей идентификатор группы процессов равен идентификатору вызывающего процесса.

  • > 0 — Дождаться любого дочернего процесса, чей идентификатор процесса равен значению pid.

<-1 — Дождаться любого дочернего процесса, чей идентификатор группы процессов равен абсолютному значению pid.

-1 — Ожидание любого дочернего процесса, что соответствует системному вызову wait ().

0 — Ожидание любого дочернего процесса, чей идентификатор группы процессов равен идентификатору вызывающего процесса.

> 0 — Дождаться любого дочернего процесса, чей идентификатор процесса равен значению pid.

По умолчанию системный вызов waitpid () ожидает только завершенных потомков, но это поведение по умолчанию можно изменить с помощью аргумента options.

Теперь давайте рассмотрим программу в качестве примера, ожидая определенного процесса с его идентификатором процесса.

/ * Имя файла: waitpid_test.c * /

#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/wait.h>

int main() {
   int pid;
   int pids[3];
   int status;
   int numprocesses = 0;
   int total_processes = 3;
   while (numprocesses < total_processes) {
      pid = fork();
      
      // Child process
      if (pid == 0) {
         printf("In child process: process id is %d\n", getpid());
         sleep(5);
         return 4;
      } else {
         pids[numprocesses] = pid;
         numprocesses++;
         printf("In parent process: created process number: %d\n", pid);
      }
   }
   
   // Waiting for 3rd child process
   waitpid(pids[total_processes - 1], &status, 0);
   if (WIFEXITED(status) != 0) {
      printf("process %d exited normally\n", pids[total_processes - 1]);
      printf("exit status from child is %d\n", WEXITSTATUS(status));
   } else {
      printf("process %d not exited normally\n", pids[total_processes - 1]);
   }
   return 0;
}

После компиляции и выполнения, следующий вывод.

In child process: process id is 32528
In parent process: created process number: 32528
In child process: process id is 32529
In parent process: created process number: 32528
In parent process: created process number: 32529
In child process: process id is 32530
In parent process: created process number: 32528
In parent process: created process number: 32529
In parent process: created process number: 32530
process 32530 exited normally
exit status from child is 4

Теперь давайте проверим системный вызов waitid (). Этот системный вызов ожидает, когда дочерний процесс изменит состояние.

#include <sys/wait.h>

int waitpid(idtype_t idtype, id_t id, siginfo_t *infop, int options);

Приведенный выше системный вызов ожидает, когда дочерний процесс изменит состояние, и этот вызов приостанавливает текущий / вызывающий процесс, пока какой-либо из его дочерних процессов не изменит свое состояние. Аргумент «infop» предназначен для записи текущего состояния ребенка. Этот вызов немедленно возвращается, если процесс уже изменил свое состояние.

Значение idtype может быть одним из следующих:

  • P_PID — Дождаться любого дочернего процесса, чей идентификатор процесса равен идентификатору идентификатора.

  • P_PGID — Ожидание любого дочернего процесса, чей идентификатор группы процессов равен идентификатору идентификатора.

  • P_ALL — ждать любого дочернего процесса, а id игнорируется.

  • Аргумент options должен указать, какое состояние изменяется, и это можно сформировать с помощью побитовой операции ИЛИ с указанными ниже флагами:

  • WCONTINUED — возвращает статус любого ребенка, который был остановлен и был продолжен.

  • WEXITEDожидает завершения процесса.

  • WNOHANG — Возвращается немедленно.

  • WSTOPPEDОжидает процесс любого ребенка, который остановился, после получения сигнала и возвращает статус.

P_PID — Дождаться любого дочернего процесса, чей идентификатор процесса равен идентификатору идентификатора.

P_PGID — Ожидание любого дочернего процесса, чей идентификатор группы процессов равен идентификатору идентификатора.

P_ALL — ждать любого дочернего процесса, а id игнорируется.

Аргумент options должен указать, какое состояние изменяется, и это можно сформировать с помощью побитовой операции ИЛИ с указанными ниже флагами:

WCONTINUED — возвращает статус любого ребенка, который был остановлен и был продолжен.

WEXITEDожидает завершения процесса.

WNOHANG — Возвращается немедленно.

WSTOPPEDОжидает процесс любого ребенка, который остановился, после получения сигнала и возвращает статус.

Этот вызов возвращает 0, если он возвращается из-за изменения состояния одного из его дочерних элементов, и используется WNOHANG. Возвращает -1 в случае ошибки и устанавливает соответствующий номер ошибки.

/ * Имя файла: waitid_test.c * /

#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/wait.h>

int main() {
   int pid;
   int pids[3];
   int status;
   int numprocesses = 0;
   int total_processes = 3;
   siginfo_t siginfo;
   while (numprocesses < total_processes) {
      pid = fork();
      
      // Child process
      if (pid == 0) {
         printf("In child process: process id is %d\n", getpid());
         sleep(5);
         return 2;
      } else {
         pids[numprocesses] = pid;
         numprocesses++;
         printf("In parent process: created process number: %d\n", pid);
      }
   }
   
   // Waiting for 3rd child process
   status = waitid(P_PID, pids[total_processes - 1], &siginfo, WEXITED);
   if (status == -1) {
      perror("waitid error");
      return 1;
   }
   printf("Info received from waitid is: ");
   printf("PID of child: %d, real user id of child: %d\n", siginfo.si_pid, siginfo.si_uid);
   return 0;
}

После выполнения и компиляции вышеуказанной программы, следующий результат.