У меня есть 3 исполняемых файла, которые также запрограммированы на C, и теперь я хочу создать процесс-обертку, который будет вызывать другие. Более конкретно, я хочу вызвать 1 копию первого и третьего процесса и 10 копий для второго процесса. Кроме того, я хочу дождаться, пока первый процесс завершится выполнением. Идея состоит в том, что эти процессы, однажды вызванные, отправляют сообщения между собой и обмениваются данными с использованием библиотеки ZMQ, и после обмена всеми сообщениями они завершаются. Я начал с чего-то вроде этого, пытаясь запустить только мой первый процесс:

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

int main(void) {
  pid_t parent = getpid();
  pid_t pid = fork();

  if (pid == -1) {
    fprintf(stderr, "Error: failed to fork.\n");
    exit(1);
  } else if (pid > 0) {
    int status;
    waitpid(pid, &status, 0);
  } else {
    char *args[] = { "0", "10" };
    char *env[] = { NULL };
    execve("./first", args, env);
    _exit(EXIT_FAILURE);
  }

  return 0;
}

Но это либо не вызывает первый процесс, либо не ждет его. Причина в том, что если кто-то вызывает только первый процесс, он вообще не должен завершаться, он должен войти в бесконечный цикл, поскольку он пытается подключиться ко второму процессу, который в этом случае не вызывается. Тем не менее, мой код выше завершает выполнение немедленно. Как правильно вызвать 12 процессов в общей сложности, из которых они состоят из 3 различных типов процессов, и дождаться завершения одного из них?

c
0
terett 28 Апр 2020 в 22:30

2 ответа

Лучший ответ
char *args[] = { "0", "10" };

Это неверно. Ядро волшебным образом не знает, где это заканчивается, поэтому оно читает слишком далеко и делает сбой execve. Это заставляет ребенка делать _exit(EXIT_FAILURE);, и если он мертв, родительский wait возвращается, так что он тоже возвращается. Чтобы исправить это, измените это на это:

char *args[] = { "0", "10", NULL };

Кроме того, вы, вероятно, не хотели, чтобы argv[0] был "0", поэтому на самом деле измените его следующим образом:

char *args[] = { "./first", "0", "10", NULL };
2
Joseph Sible-Reinstate Monica 28 Апр 2020 в 22:15

Относительно вашего второго вопроса:

Сохраните каждый сгенерированный процесс pid в массиве

pid_t  childPids[10];

Тогда индекс в этом массиве является дочерним процессом, которого вы хотите ждать.

Чтобы ждать конкретного ребенка:

int x = <which child you want to wait for>
int status;
waitpid( childPids[x], &status, 0 );
0
user3629249 29 Апр 2020 в 19:42