Вот реализация того, что, я думаю, вам нужно - с обильной печатью, которая показывает мне, что код делает то, что я ожидаю.Я использую некоторый мой код сообщения об ошибках, который очень помогает, имея опции для печати времени и идентификатора процесса в каждом сообщении.Этот код доступен в моем репозитории SOQ (Вопросы о переполнении стека) на GitHub в виде файлов stderr.c
и stderr.h
в подкаталоге src / libsoq .
#include "stderr.h"
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <time.h>
#include <unistd.h>
static void wait_for_kids(void);
static void random_nanosleep(void);
static void process_tree(int row_num, int num_kids)
{
int i;
int ppid = getpid();
err_remark("Launching row %d (%d kids)\n", row_num, num_kids);
for (i = 0; i < num_kids; i++)
{
int pid = fork();
if (pid < 0)
err_syserr("Failed to fork: ");
if (pid == 0)
{
err_remark("Child %d at work (parent %d)\n", i + 1, (int)getppid());
}
else
{
err_remark("Child %d launched (PID %d)\n", i + 1, pid);
break;
}
}
wait_for_kids();
if (getpid() != ppid)
{
random_nanosleep();
int status = 10 * row_num + i + 1;
err_report(ERR_EXIT | ERR_PID | ERR_MILLI | ERR_NOARG0, status,
"Process complete (status %d = 0x%.2X)\n", status, status);
}
err_remark("Launching of row %d complete\n", row_num);
}
int main(int argc, char **argv)
{
err_setarg0(argv[0]);
err_setlogopts(ERR_PID | ERR_MILLI | ERR_NOARG0);
if (argc != 1)
err_usage("");
int proc_tree[] = { 3, 2, 4, 2 };
enum { NUM_ROWS = sizeof(proc_tree) / sizeof(proc_tree[0]) };
err_remark("At work!\n");
for (int i = 0; i < NUM_ROWS; i++)
process_tree(i + 1, proc_tree[i]);
err_remark("All done!\n");
return 0;
}
static void wait_for_kids(void)
{
int corpse;
int status;
while ((corpse = wait(&status)) > 0)
err_remark("Child %d exited with status 0x%.4X\n", corpse, status);
err_remark("No progeny left - woe is me!\n");
}
static void random_nanosleep(void)
{
srand(getpid()); /* Not very good, but adequate */
struct timespec nap = { .tv_sec = 0, .tv_nsec = (rand() % 5000 + 5000) * 10000 };
nanosleep(&nap, 0);
}
Основной операционный код в main()
и process_tree()
;две другие функции, объявленные вверху, являются служебными функциями, которые выполняют полезную работу, но не являются основной частью ответа.
Код в process_tree()
имеет дело с одной строкой массива и ему сообщаютномер строки (для целей отчетности) и количество детей.Он сообщает основную информацию о том, что он будет делать, а затем запускает цикл for
, очень похожий на ваш.Процесс вилки;если происходит сбой, он сообщает о проблеме (включая системное сообщение об ошибке) и завершает работу.Если это ребенок, он говорит, что он на работе и кто его родитель, и переходит к следующей итерации цикла.Если это родитель, он отмечает, какой дочерний элемент запущен, и выходит из цикла.В конце цикла процесс (будь то исходный или один из дочерних процессов) ожидает смерти своих потомков, а затем, если это не исходный процесс, берет случайный сон и завершает работу с неНулевой статус (и печатное сообщение).Если это родительский (оригинальный) процесс, он говорит, что он завершен с текущей строкой и возвращает.
Код в main()
в основном прост.Он выполняет минимальную обработку аргументов и настраивает систему отчетов об ошибках так, чтобы сообщения не включали имя программы (ERR_NOARG0
), но включали время с миллисекундами (ERR_MILLI
) и PID (ERR_PID
), и сообщали, что она работает,Затем для каждой строки дерева вызывается process_tree()
.затем он сообщает «все выполнено» и завершается.
Функция wait_for_kids()
просто ожидает смерти дочерних процессов и сообщает о состоянии каждого дочернего элемента, который действительно умирает, затем объявляет свое бездетное состояние и возвращает.
Код random_nanosleep()
инициализирует генератор случайных чисел отдельно для каждого процесса, чтобы он спал в течение различного времени, которое настроено на период от 50 до 100 миллисекунд.(Без этого весь процесс занимает около 20 миллисекунд.)
Пример выполнения:
2018-06-09 14:23:15.717 - pid=29868: At work!
2018-06-09 14:23:15.718 - pid=29868: Launching row 1 (3 kids)
2018-06-09 14:23:15.718 - pid=29868: Child 1 launched (PID 29869)
2018-06-09 14:23:15.718 - pid=29869: Child 1 at work (parent 29868)
2018-06-09 14:23:15.719 - pid=29869: Child 2 launched (PID 29870)
2018-06-09 14:23:15.719 - pid=29870: Child 2 at work (parent 29869)
2018-06-09 14:23:15.720 - pid=29870: Child 3 launched (PID 29871)
2018-06-09 14:23:15.720 - pid=29871: Child 3 at work (parent 29870)
2018-06-09 14:23:15.720 - pid=29871: No progeny left - woe is me!
2018-06-09 14:23:15.790 - pid=29871: Process complete (status 14 = 0x0E)
2018-06-09 14:23:15.790 - pid=29870: Child 29871 exited with status 0x0E00
2018-06-09 14:23:15.791 - pid=29870: No progeny left - woe is me!
2018-06-09 14:23:15.843 - pid=29870: Process complete (status 13 = 0x0D)
2018-06-09 14:23:15.844 - pid=29869: Child 29870 exited with status 0x0D00
2018-06-09 14:23:15.844 - pid=29869: No progeny left - woe is me!
2018-06-09 14:23:15.927 - pid=29869: Process complete (status 12 = 0x0C)
2018-06-09 14:23:15.928 - pid=29868: Child 29869 exited with status 0x0C00
2018-06-09 14:23:15.928 - pid=29868: No progeny left - woe is me!
2018-06-09 14:23:15.928 - pid=29868: Launching of row 1 complete
2018-06-09 14:23:15.928 - pid=29868: Launching row 2 (2 kids)
2018-06-09 14:23:15.929 - pid=29868: Child 1 launched (PID 29872)
2018-06-09 14:23:15.929 - pid=29872: Child 1 at work (parent 29868)
2018-06-09 14:23:15.930 - pid=29872: Child 2 launched (PID 29873)
2018-06-09 14:23:15.930 - pid=29873: Child 2 at work (parent 29872)
2018-06-09 14:23:15.931 - pid=29873: No progeny left - woe is me!
2018-06-09 14:23:15.987 - pid=29873: Process complete (status 23 = 0x17)
2018-06-09 14:23:15.988 - pid=29872: Child 29873 exited with status 0x1700
2018-06-09 14:23:15.988 - pid=29872: No progeny left - woe is me!
2018-06-09 14:23:16.076 - pid=29872: Process complete (status 22 = 0x16)
2018-06-09 14:23:16.076 - pid=29868: Child 29872 exited with status 0x1600
2018-06-09 14:23:16.076 - pid=29868: No progeny left - woe is me!
2018-06-09 14:23:16.076 - pid=29868: Launching of row 2 complete
2018-06-09 14:23:16.076 - pid=29868: Launching row 3 (4 kids)
2018-06-09 14:23:16.077 - pid=29868: Child 1 launched (PID 29874)
2018-06-09 14:23:16.077 - pid=29874: Child 1 at work (parent 29868)
2018-06-09 14:23:16.078 - pid=29874: Child 2 launched (PID 29875)
2018-06-09 14:23:16.078 - pid=29875: Child 2 at work (parent 29874)
2018-06-09 14:23:16.079 - pid=29875: Child 3 launched (PID 29876)
2018-06-09 14:23:16.079 - pid=29876: Child 3 at work (parent 29875)
2018-06-09 14:23:16.080 - pid=29876: Child 4 launched (PID 29877)
2018-06-09 14:23:16.080 - pid=29877: Child 4 at work (parent 29876)
2018-06-09 14:23:16.080 - pid=29877: No progeny left - woe is me!
2018-06-09 14:23:16.159 - pid=29877: Process complete (status 35 = 0x23)
2018-06-09 14:23:16.159 - pid=29876: Child 29877 exited with status 0x2300
2018-06-09 14:23:16.160 - pid=29876: No progeny left - woe is me!
2018-06-09 14:23:16.221 - pid=29876: Process complete (status 34 = 0x22)
2018-06-09 14:23:16.221 - pid=29875: Child 29876 exited with status 0x2200
2018-06-09 14:23:16.222 - pid=29875: No progeny left - woe is me!
2018-06-09 14:23:16.314 - pid=29875: Process complete (status 33 = 0x21)
2018-06-09 14:23:16.315 - pid=29874: Child 29875 exited with status 0x2100
2018-06-09 14:23:16.315 - pid=29874: No progeny left - woe is me!
2018-06-09 14:23:16.389 - pid=29874: Process complete (status 32 = 0x20)
2018-06-09 14:23:16.390 - pid=29868: Child 29874 exited with status 0x2000
2018-06-09 14:23:16.390 - pid=29868: No progeny left - woe is me!
2018-06-09 14:23:16.390 - pid=29868: Launching of row 3 complete
2018-06-09 14:23:16.390 - pid=29868: Launching row 4 (2 kids)
2018-06-09 14:23:16.391 - pid=29868: Child 1 launched (PID 29878)
2018-06-09 14:23:16.391 - pid=29878: Child 1 at work (parent 29868)
2018-06-09 14:23:16.392 - pid=29878: Child 2 launched (PID 29879)
2018-06-09 14:23:16.392 - pid=29879: Child 2 at work (parent 29878)
2018-06-09 14:23:16.393 - pid=29879: No progeny left - woe is me!
2018-06-09 14:23:16.457 - pid=29879: Process complete (status 43 = 0x2B)
2018-06-09 14:23:16.457 - pid=29878: Child 29879 exited with status 0x2B00
2018-06-09 14:23:16.457 - pid=29878: No progeny left - woe is me!
2018-06-09 14:23:16.554 - pid=29878: Process complete (status 42 = 0x2A)
2018-06-09 14:23:16.556 - pid=29868: Child 29878 exited with status 0x2A00
2018-06-09 14:23:16.556 - pid=29868: No progeny left - woe is me!
2018-06-09 14:23:16.556 - pid=29868: Launching of row 4 complete
2018-06-09 14:23:16.556 - pid=29868: All done!