如何从单个父进程创建两个进程

发布于 2024-11-18 03:15:55 字数 110 浏览 3 评论 0原文

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

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..)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

电影里的梦 2024-11-25 03:15:55

要创建第二个进程,请再次调用 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 */
    }
}

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).

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


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 */
    }
}
挽你眉间 2024-11-25 03:15:55

另一个使用 && 运算符的奇特代码:

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

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 */
}
眸中客 2024-11-25 03:15:55
#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
#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
最冷一天 2024-11-25 03:15:55

您可以将 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() 和 Err_Print() 是内部函数,但非常明显,所以我让它们保持原样。

变量有一个方面需要解释。 nSonnSonAsked 应声明为全局变量而不是堆栈变量。这样,它们的价值就会在分叉过程中持续存在。这意味着 nSon 变量在每个子项中将具有不同的值。这使得它具有比 ownpid() 数字更简单的编号方案。

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

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

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.

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

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 same one. 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).

深海不蓝 2024-11-25 03:15:55
#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);
        }
    }
}
#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);
        }
    }
}
终遇你 2024-11-25 03:15:55

在这个例子中

they are just sleeping for a few random sec. It also has all the pid, so we can send SIGNAL to communicate...

Most of the #includes are commented cause they were useless where I compiled.

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

In this example

they are just sleeping for a few random sec. It also has all the pid, so we can send SIGNAL to communicate...

Most of the #includes are commented cause they were useless where I compiled.

#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;
}
画▽骨i 2024-11-25 03:15:55

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

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).

#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
Oo萌小芽oO 2024-11-25 03:15:55
#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;
}
#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;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文