使用fork创建多个子孙和孙子? [英] Creating Multiple child and Grandchild using fork?

查看:87
本文介绍了使用fork创建多个子孙和孙子?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是一个使用fork创建两个childern的代码。我的问题是,我们如何能够同时创造出多元化的宏伟和伟大的宏伟。并且代码的第21行给出了意想不到的输出,即在一个父ID上它给出了三个id。





这是输出: -

这是一个child1进程,pid是3271

这是child2进程,pid是3272

父进程有pid 2206

父进程有pid 3270

父进程有pid 1.







Here is a code that creates two childern using fork. My question is how can we create mutiple grandchildern and great grandchildern at the same time . And the line 21 of code gives an unexpected output i.e instead on one parent id it gives three id's.


Here is the output :-
This is a child1 process and pid is 3271
This is child2 process and pid is 3272
The parent process has pid 2206
The parent process has pid 3270
The parent process has pid 1.



#include<stdio.h>
main()
{
  int child1,child2;
  int i;
  child1 = fork();
  if(child1==0)
  {
    printf("This is a child1 process and pid is %d\n", getpid());
  }
   else
    {
          child2=fork();     
	  if(child2==0)
	    {
              printf("This is child2  process and pid is %d\n",getpid());
	    }
      }
	sleep(1);
       printf("The parent process has pid %d\n",getppid());

          
}

推荐答案

子进程继承/复制大量资源,内存,父进程的代码和句柄。因此,sleep(1)和它后面的printf()由代码的所有分支执行,包括父代和两个子代。如果你想在生成两个孩子之后只通过原始父进程执行它,那么你必须将睡眠与printf一起移动到内部的else分支中,如果:

The child processes inherit/copy a lot of resources, memory, code and handles from the parent process. For this reason the sleep(1) and the printf() that follows it is executed by all branches of your code, both by the parent and the two children. If you want to execute it only by the original parent process after spawning both children then you have to move the sleep along with the printf into an else branch of the inner if:
if(child2==0)
{
   printf("This is child2  process and pid is %d\n",getpid());
} else {
   sleep(1);
   printf("The parent process has pid %d\n",getppid());
}



在产生两个孩子后,它只由原始父母执行。你可以通过在子进程中分叉一次来创建孙子孙女。你可以通过在一个盛大的子进程中分叉一次来创建一个好孩子......但是请记住,每个分叉的子代(如sleep和printf)都会复制大量资源和所有代码,并且执行流程随着语言流程而变化构造命令!



这是一段产生以下流程层次结构的代码:


There it is executed only by the original parent after spawning both children. You can create grandchildren by forking() once in the child process. You can create a great child by forking once in a grand child process... But remember, a lot of resources and all the code is copied by every forked children (like your sleep and printf) and the execution flow goes as the language flow constructs dictate!

Here is a piece of code that spawns the following process hierarchy:

parent
 +--child
     +--grandchild1
     +--grandchild2





这是一个不错的选择如何不写程序的例子。这是一个令人讨厌的意大利面条代码,其中许多错误可以轻松隐藏。



This is a good example of how not to write a program. This is a big piece of disgusting spaghetti code where many bugs can hide easily.

#include<stdio.h>

void variation1()
{
    pid_t child, grandchild1, grandchild2;
    int child_status, grandchild1_status, grandchild2_status;
    printf("The parent process has pid %d\n", getpid());
    child = fork();
    if(child == 0)
    {
        // child
        printf("This is a child process and pid is %d\n", getpid());

        grandchild1 = fork();
        if (grandchild1 == 0)
        {
            // grandchild1
            printf("This is grandchild1 and pid is %d\n", getpid());
            sleep(1);
            exit(5);
        }
        else if (grandchild1 > 0)
        {
            // child
            grandchild2 = fork();
            if (grandchild2 == 0)
            {
                // grandchild2
                printf("This is grandchild2 and pid is %d\n", getpid());
                sleep(1);
                exit(6);
            }
            else if (grandchild2 > 0)
            {
                // child
                waitpid(grandchild2, &grandchild2_status, 0);
                if (WIFEXITED(grandchild2_status))
                    printf("grandchild2 has exited with exit code %d\n", WEXITSTATUS(grandchild2_status));
                else
                    printf("grandchild2 has terminated abnormally\n");
            }
            else
            {
                printf("Error forking grandchild2!\n");
            }

            // child
            waitpid(grandchild1, &grandchild1_status, 0);
            if (WIFEXITED(grandchild1_status))
                printf("grandchild1 has exited with exit code %d\n", WEXITSTATUS(grandchild1_status));
            else
                printf("grandchild1 has terminated abnormally\n");
        }
        else
        {
            printf("Error forking grandchild1!\n");
        }
        exit(0);
    }
    else if (child > 0)
    {
        // parent
        waitpid(child, &child_status, 0);
        if (WIFEXITED(child_status))
            printf("child has exited with exit code %d\n", WEXITSTATUS(child_status));
        else
            printf("child has terminated abnormally\n");
    }
    else
    {
        printf("Error forking child!\n");
    }
}





这是一段代码应该做的几乎相同,但它更干净而且更容易理解。它以更好的方式设计,更容易修改/维护而不会引入错误:





Here is a piece of code that should do nearly the same but it is much cleaner and easier to understand. It is designed in a much better way and its easier to modify/maintain without introducing bugs:

// returns the exitcode of the child process
typedef int (*child_func_pointer_t)();

// returns -1 on error, child pid otherwise
pid_t fork_child_in_function(child_func_pointer_t child_func, const char* child_name)
{
    pid_t child_pid = fork();
    if (child_pid == 0)
    {
        printf("Hello! I'm child %s and I've just started with pid=%d (parent_pid=%d)\n", child_name, getpid(), getppid());
        exit(child_func());
    }
    if (child_pid < 0)
        printf("Error forking %s!\n", child_name);
    return child_pid;
}

void wait_child(pid_t child_pid, const char* child_name)
{
    int child_status;
    waitpid(child_pid, &child_status, 0);
    if (WIFEXITED(child_status))
        printf("%s has exited with exit code %d\n", child_name, WEXITSTATUS(child_status));
    else
        printf("%s has terminated abnormally\n", child_name);
}

void fork_and_wait_child(child_func_pointer_t child_func, const char* child_name)
{
    pid_t child_pid = fork_child_in_function(child_func, child_name);
    if (child_pid > 0)
        wait_child(child_pid, child_name);
}


int grandchild1_func()
{
    sleep(1);
    return 5;
}

int grandchild2_func()
{
    sleep(1);
    return 6;
}

int child_func()
{
    int grandchild1_pid, grandchild2_pid;
    grandchild1_pid = fork_child_in_function(grandchild1_func, "grandchild1");
    grandchild2_pid = fork_child_in_function(grandchild2_func, "grandchild2");
    if (grandchild1_pid > 0)
        wait_child(grandchild1_pid, "grandchild1");
    if (grandchild2_pid > 0)
        wait_child(grandchild2_pid, "grandchild2");
    return 0;
}

void variation2()
{
    fork_and_wait_child(child_func, "child");
}



我没有测试过这些代码中的任何一个,但这是一个非常好的伪代码,它展示了如何做好事并显示出差异在垃圾代码和精心设计的代码之间。


I haven't tested any of these codepieces but this is a very good "pseudo code" that shows how to do things well and shows the difference between junk code and well designed code.


这篇关于使用fork创建多个子孙和孙子?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆