разрабатывают и исполняют много разных процессов и получают результаты от каждого - PullRequest
3 голосов
/ 12 мая 2011

Мне удалось создать и запустить другую программу из моего приложения.В настоящее время я работаю над тем, как ждать, пока процесс, вызванный из exec, вернет результат через канал или стандартный вывод.Однако могу ли я иметь группу процессов, использующих один форк, или мне приходится многократно форкать и снова вызывать одну и ту же программу?Могу ли я получить PID для каждого отдельного процесса?Я хочу, чтобы мое приложение вызывало одну и ту же программу, которую я в данный момент вызываю много раз, но с другими параметрами: я хочу, чтобы группа из 8 процессов одной и той же программы выполнялась и возвращала результаты по каналам.Может кто-нибудь, пожалуйста, укажите мне правильное направление, пожалуйста?Я просмотрел справочные страницы linux.die, но они довольно спартанские и загадочные в своем описании.Есть ли электронная книга или PDF, которые я могу найти для получения подробной информации?Спасибо!

pid_t pID = fork();
 if (pID == 0){
  int proc = execl(BOLDAGENT,BOLDAGENT,"-u","2","-c","walkevo.xml",NULL);
  std::cout << strerror(errno) << std::endl;
}

Например, как я могу контролировать PID, какой дочерний элемент (согласно файлу параметра xml) получил какой результат (по каналу или стандартному выводу), и, таким образом, действовать соответствующим образом?Нужно ли инкапсулировать дочерние процессы в объект и работать оттуда, или я могу сгруппировать их вообще?

Ответы [ 3 ]

6 голосов
/ 12 мая 2011

Один Fork системный вызов создает только один новый процесс (один PID).Вы должны организовать некоторые структуры данных (например, массив pids, массив концов родительских каналов и т. Д.), Выполнить 8 форков из основной программы (каждый дочерний элемент выполнит exec), а затем дождаться дочерних элементов.

Послекаждый fork () будет возвращать вам PID ребенка.Вы можете сохранить этот pid и связанную с ним информацию следующим образом:

#define MAX_CHILD=8
pid_t pids[MAX_CHILD];
int pipe_fd[MAX_CHILD];
for(int child=0;child<MAX_CHILD;child++) {
 int pipe[2];
 /* create a pipe; save one of pipe fd to the pipe_fd[child] */
 int ret;
 ret = fork();
 if(ret) { /* parent */ 
  /* close alien half of pipe */
  pids[child] = ret; /* save the pid */
 } else { /* child */
  /* close alien half of pipe */
  /* We are child #child, exec needed program */
  exec(...);
  /* here can be no more code in the child, as `exec` will not return if there is no error! */
 }
} 

/* there you can do a `select` to wait data from several pipes; select will give you number of fd with data waiting, you can find a pid from two arrays */
5 голосов
/ 12 мая 2011

Сначала это утомительно, но вы, кажется, это понимаете, когда вызываете fork ():

  • вызывающий процесс («родитель») по существу дублируется операционная система и дубликат процесса становится "ребенком" с уникальным идентификатором PID

  • возвращаемое значение из fork () вызов либо: целое число 0, 1 означает, что Программа получения возврата 0 является «Ребенок»; или это ненулевой целочисленный PID этого раздвоенного ребенка; и

  • новый дочерний процесс введен в очередь планирования для выполнения. Родитель остается в расписании очередь и продолжает выполняться как до этого.

Именно этот (0 .xor. non-0) возврат из fork () сообщает программе, какую роль он играет в данный момент - возвращается 0, программа является дочерним процессом; все остальное возвращается, программа является родительским процессом.

Если программе, исполняющей родительскую роль, требуется много детей, он должен выполнить fork () для каждого из них отдельно; нет такой вещи, как несколько детей, совместно использующих вилку ().

Промежуточные результаты, безусловно, могут быть отправлены через канал.

Что касается вызова каждого дочернего элемента с различными параметрами, на самом деле ничего особенного делать не нужно: вы можете быть уверены, что когда ребенок получит контроль, он будет иметь (копии) точно таких же переменных, что и родительский элемент. Таким образом, передача параметров ребенку зависит от установки родителем значений переменных, с которыми он хочет, чтобы ребенок работал; и затем вызывая fork ().


1 Точнее: fork () возвращает значение типа pid_t, которое в наши дни идентично целому числу в довольно многих системах.

1 голос
/ 12 мая 2011

Прошло много времени с тех пор, как я работал на C / C ++, но несколько моментов:

  • Википедия страница fork-exec предоставляет отправную точкучтобы узнать о разветвлении и изгнании.Google здесь тоже ваш друг.

  • Как сказано в ответе osgx, fork () может дать вам только один подпроцесс, поэтому вам придется вызывать его 8 раз, чтобы получить 8 процессов, а затемкаждая из них должна будет выполнить другую программу.

  • fork () возвращает PID дочернего процесса в основной процесс и 0 в подпроцесс, так что вы должны иметь возможность что-то делатькак:

int pid = fork();
if (pid == 0) {
  /* exec new program here */
} else {
  /* continue with parent process stuff */
}
...