как создать два процесса из одного родителя - PullRequest
2 голосов
/ 01 июля 2011

Я знаю, что мне нужно будет использовать fork (), но это просто создает один дочерний процесс.Я просто снова вызываю fork из дочернего процесса?Кроме того, мне нужно, чтобы они общались через сигнал или канал, что проще в реализации и что мне нужно знать для этого (функции и т. Д.)

Ответы [ 7 ]

11 голосов
/ 01 июля 2011

Чтобы создать второй процесс, снова вызовите fork() - либо в родительском, либо в дочернем (но не в обоих!).Выбор зависит от того, хотите ли вы, чтобы этот процесс был дочерним по отношению к исходному родительскому процессу или дочерним по отношению к первому дочернему процессу (обычно это дочерний процесс по отношению к исходному родительскому процессу).труба намного проще и надежнее, чем использование сигналов.pipe(), close(), read(), write() и select() - ключевые функции здесь.


Например, чтобы родительский объект создал два дочерних процесса, вы должны сделатькак:

pid_t child_a, child_b;

child_a = fork();

if (child_a == 0) {
    /* Child A code */
} else {
    child_b = fork();

    if (child_b == 0) {
        /* Child B code */
    } else {
        /* Parent Code */
    }
}
3 голосов
/ 13 ноября 2017
#include <stdio.h>
#include <unistd.h>

void main(){
  int pi_d ;
  int pid ;
  pi_d = fork();
  if(pi_d == 0){
    printf("Child Process B:\npid :%d\nppid:%d\n",getpid(),getppid());
  }
  if(pi_d > 0){
    pid = fork();
    if(pid > 0){
      printf("\nParent Process:\npid:%d\nppid :%d\n",getpid(),getppid());
    }
    else if(pid == 0){
      printf("Child Process A:\npid :%d\nppid:%d\n",getpid(),getppid());
    }
  }
}

вывод:

Parent Process:
pid:3648
ppid :2379
Child Process B:
pid :3649
ppid:3648
Child Process A:
pid :3650
ppid:3648
1 голос
/ 04 февраля 2014

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

for(nSon=0; nSon < nSonsAsked; nSon++) {
  Log_Print("Setup son #%.2u ", nSon+1);

  if((pid = fork()) == 0) {
    /* Do child stuff init, like connect the pipes, close shared handles */

    return iTMInChild(...);     /* A specific function of the child work */
  /* The life of the child should not go beyond that point, i.e. the loop is over 
     or else the child will spawn even more processes. */ 
  }
  else if(pid > 0) {
    /* Father process stuff. Here I initialise an array with the pid of the forked */
    /* processes, this way I can index with the number of processes.*/
    pid[nSon] = pid;
  }
  else
    return Err_Print(ERR_FORK_FAILED, "fork failed. errno=%d \"%s\"\n", errno, strerror(errno));
}

Log_Print () и Err_Print () являются внутренними функциями, но вполне очевидны, поэтому я позволяю им быть такими, как есть.

Есть один аспект с переменными, который необходимо объяснить. nSon и nSonAsked должны быть объявлены как глобальные переменные, а не как переменные стека. Таким образом, их ценность сохраняется в разветвленном процессе. Это означает, что переменная nSon будет иметь разные значения в каждом из дочерних элементов. Это позволяет ему иметь более простую схему нумерации, чем номер ownpid().

Чтобы все было правильно, есть много деталей, чтобы понять это правильно. Вам нужно будет установить обработчики сигналов в родительском процессе для обнаружения смерти ребенка, так же как и наоборот (возможно только в Linux, другие Unix (по крайней мере, Solaris) не поддерживают родительские сигналы смерти). Вы должны знать, что дескрипторы открытых файлов в родительском процессе также будут открыты у дочернего элемента после fork, и это будет тот же . Это открывает много проблем параллелизма, если вы не знаете об этом (решение использует dup() и close() в нужных местах).

0 голосов
/ 13 февраля 2019
#include <sys/wait.h>
#include <stdio.h>
#include <unistd.h>
int main()
{
pid_t AliceID, BobID;
double n=0;
int i1 =0;
/* fork a child process */
AliceID = fork();

if (AliceID < 0) { /* error occurred */
fprintf(stderr, "Fork Failed");
return 1;
}
else if (AliceID == 0) { /* child Alice code */
    for(int i=1; i<11; i++)
          {n = n+i;
           i1++; }
        double avg1 = n/i1;
       printf("From Alice: the average of 1,2, …, 10 is the-average-she-calculated");
       printf("  sum = %.2f and avg = %.2f \n",n, avg1); 
     }
   else  { 
          BobID = fork();
         if (BobID == 0) { /* Child Bob code */
          printf("From Bob: I am born to print this and then die.\n");

        } else {  /* Parent Code */
                  /* parent will wait for the child to complete */
            wait(NULL);
            printf("From parent: AliceID is %d \n",  AliceID);
            printf("From parent: Bob is %d \n",  BobID);
            printf("Parent ID %d \n", getpid());

         }
}
return 0;
}
0 голосов
/ 20 апреля 2017

Небольшой вклад, если вы хотите создать 2 детей от одного и того же родителя, вы можете использовать этот код ниже. В котором один отец создает 2 дочерних процесса (ленивый и активный).

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>

int main (){
  pid_t lazy_child;

  lazy_child = fork();

  if(lazy_child == 0){ // This is the lazy child process.
    printf("LAZY CHILD:%d\n", getpid());
  }
  else if(lazy_child > 0){ // This is the father process.
    pid_t active_child = fork();

    if(active_child == 0){ // This is the active child process.
      printf("ACTIVE CHILD:%d\n", getpid());
    }
    else if(active_child > 0){ // This is the father process.
      printf("FATHER:%d\n", getpid());
    }
    else{ // Fork doesnt work.
      printf("fork error\n");
      exit(1);
    }
  }
  else{ // Fork doesnt work.
    printf("fork error\n");
    exit(1);
  }
  return 0;
}

Если вы запустите этот код, вы должны получить похожий вывод:

$ ./a.out 
FATHER:14501
ACTIVE CHILD:14503
LAZY CHILD:14502
0 голосов
/ 10 мая 2016

В этом примере

они просто спят в течение нескольких случайных секунд. Он также имеет все pid , поэтому мы можем отправить SIGNAL для связи ...

Большинство #include прокомментированы, потому что они были бесполезны Я скомпилировал.
#include <stdlib.h> // exit() ...
#include <stdio.h> // printf() ...

// Compile with -lrt -> cc file_name.c -lrt

//#include <fcntl.h>
//#include <sys/stat.h>
//#include <sys/types.h>
//#include <sys/wait.h> // may need this for wait()
//#include <time.h>

//#include <unistd.h> // and this one for fork()

// In the start function you can do whatever you want.
void start (const int azon) {
    // For children processes
    srand( time(NULL) );
    unsigned t = rand()%5; // printf("%d\n", t);
    sleep(t);
    printf("%d. process reached the end.\n", azon);
    exit(0);
}

int main() {
    const int N = 5;
    pid_t pids[N];

    int i;

    // The 'for' loop make 'N' process with 'fork()'.
    // The children processes will call the start function.
    // Since after fork() you will get 2 process. One Parent, and One Child
    // The returning value from fork() is saved in "pids" which is an
    // integer AND it is (<0) IF something went wrong.
    //             it is (>0) IF 'we are' in the Parent process,
    // because this number is the Child process' ID (pid).
    // and Last    it is (==0) IF 'we are' in the Child process.
    for (i = 0; i < N; i++) {
        pids[i] = fork();
        sleep(1);
        if (pids[i] == 0) start(i+1); // ... OR you can make a switch(..)
    }
    // This 'for' loop in the wait(NULL) statement ONLY move on when a
    // process ended, so it waits until 'N' proc ends.
    for (i = 0; i < N; i++)
        wait(NULL);

    printf("Partent process reached the end\n");

    return 0;
}
0 голосов
/ 04 февраля 2014
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
int main()
{
    system ("clear");
    int i ;
    pid_t childa,childb,childa1,childa2,childb1,childb2;
    printf("\n \t \t I am the parent process with ID %d \n",getpid());
    childa=fork();
    if (childa == 0 )
    {
        printf("\nI am a child A with PID %d and my parent ID is %d\n",getpid(),getppid());
    }
    else
    {
        childb = fork();
        if (childb == 0)
        {
            printf("\nI am Child B with ID %d and my parent ID is %d\n",getpid(),getppid());
        }
        else
        {
            sleep(1);
        }
    }
}
...