C语言 如何从单个父级创建两个进程

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6542491/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 09:03:49  来源:igfitidea点击:

how to create two processes from a single Parent

cipcforkparent-child

提问by fifamaniac04

I know I'm going to need to use fork(), but this just creates a single child process. Do i simply call fork again from within the child process? Also, I need them to communicate through a signal or pipe, which is easier to implement and what do i need to know for doing that (functions, etc..)

我知道我将需要使用 fork(),但这只会创建一个子进程。我是否只是从子进程中再次调用 fork ?此外,我需要它们通过信号或管道进行通信,这更容易实现,我需要知道什么(函数等)

回答by caf

To create a second process, call fork()again - either within the parent or the child (but not both!). Which you choose depends on whether you want this process to be a child of the original parent or a child of the first child process (it is usual for it to be a child of the original parent).

要创建第二个进程,请fork()再次调用- 在父进程或子进程中(但不能同时调用!)。您选择哪个取决于您希望此进程是原始父进程的子进程还是第一个子进程的子进程(通常它是原始父进程的子进程)。

Communicating through a pipe is much simpler and more reliable than using signals. pipe(), close(), read(), write()and select()are the key functions here.

通过管道进行通信比使用信号更简单、更可靠。 pipe(), close(), read(),write()select()是这里的关键功能。



For example, to have the parent create two child processes, you would do something like:

例如,要让父进程创建两个子进程,您可以执行以下操作:

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 */
    }
}

回答by Manas Kinkar

#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());
    }
  }
}

output :

输出 :

Parent Process:
pid:3648
ppid :2379
Child Process B:
pid :3649
ppid:3648
Child Process A:
pid :3650
ppid:3648

回答by Patrick Schlüter

You can put the fork in a loop and generate as many child processes as you need. I did that on a project recently.

您可以将 fork 放入循环中,并根据需要生成任意数量的子进程。我最近在一个项目中做到了这一点。

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() and Err_Print() are internal functions but quite obvious so I let them like they are.

Log_Print() 和 Err_Print() 是内部函数,但很明显,所以我让它们像它们一样。

There is one aspect with the variables that has to be explained. nSonand nSonAskedshould be declared as globals not as stack variables. This way, their value persists in the forked process. This means that the nSonvariable will have a different value in each of the children. This allows it to have a simpler numbering scheme than the ownpid()number.

必须解释变量的一方面。nSon并且nSonAsked应该声明为全局变量而不是堆栈变量。这样,它们的价值在分叉过程中持续存在。这意味着该nSon变量在每个孩子中都有不同的值。这允许它具有比ownpid()数字更简单的编号方案。

To get it completely right, there are a lot of details to get right. You will have to set signal handlers in the father process to detect the death of a child, likewise the other way round (only possible on Linux, other Unix (at least Solaris) do not support parent death signals). You have to be aware that open file descriptors in the father process will be also open in the child after fork and it will be the sameone. This opens a lot of concurrency problems if you're not aware of it (the solution is using dup()and close()in the right places).

要完全正确,有很多细节需要正确处理。您必须在父进程中设置信号处理程序来检测子进程的死亡,反之亦然(仅在 Linux 上可能,其他 Unix(至少 Solaris)不支持父进程死亡信号)。你必须知道,在父进程中打开的文件描述符在 fork 之后也会在子进程中打开,并且是相同的。如果您不知道,这会引发很多并发问题(解决方案是在正确的地方使用dup()和使用close())。

回答by Sayan Medya

Another fancy code using &&operator:

另一个使用&&运算符的花哨代码:

pid_t c1_pid, c2_pid;

(c1_pid = fork()) && (c2_pid = fork()); // Creates two children

if (c1_pid == 0) {
    /* Child 1 code goes here */
} else if (c2_pid == 0) {
    /* Child 2 code goes here */
} else {
    /* Parent code goes here */
}

回答by MIGUEL A POLANCO

#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;
}

回答by HovaMegy

In this example

在这个例子中

他们只是随机睡了几秒钟。它也拥有所有pidpid,所以我们可以发送SIGNAL信号沟通...





Most of the #includes are commented cause they were useless where I compiled.大多数#includes 都被注释了,因为它们在我编译的地方没用。

#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;
}

回答by Wilton Rodrigues

Just a little contribution, if you want to create 2 childs from the same parent you could use this code below. In which one father create 2 child processes (lazy and active).

只是一点贡献,如果你想从同一个父级创建 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;
}

If you run this code, you should get a similar output:

如果您运行此代码,您应该得到类似的输出:

$ ./a.out 
FATHER:14501
ACTIVE CHILD:14503
LAZY CHILD:14502

回答by Abhinav Jayanthy

#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);
        }
    }
}