C语言中fork的工作

发布于 2024-11-13 09:21:49 字数 809 浏览 6 评论 0原文

现在我在理解 fork() 系统调用的工作原理方面遇到了问题。 我编写了如下代码:

#include<stdio.h>
int main()
{
    int a, b;
    b=fork();

    printf("\n the value of b = %d",b);
}

该代码的输出如下:

现在我不明白为什么输出是这样的?

之后,我只需在代码中添加一行,输出就完全不同了。 我的代码如下:

int main()
{
    int a, b;
    b=fork();

当我运行代码时,输​​出如下 2389我的名字是 manish

 the value of b = 0

现在我对 fork() 调用的工作完全感到困惑。

我的问题如下:

  1. fork() 是如何工作的?
  2. fork() 调用后控件去了哪里?
  3. 任何人都可以解释为什么问题中编写的代码的输出吗?
  4. 为什么 b 的输出出现在不同的地方意味着在第一个代码中 b = 2260 的输出位于输出 b = 0 之前,而 b = 2389 的值不位于 b = 0?

请向我解释一下问题中编写的代码中 fork 的工作原理,以便我可以正确地学习它。

Now I have a problem in understanding the working of fork() system call.
I write a code which is following :

#include<stdio.h>
int main()
{
    int a, b;
    b=fork();

    printf("\n the value of b = %d",b);
}

The output of this code is following :

Now I don't understand why the output is like this ?

After that i just add a line to my code and output is completely different.
my code is following:

int main()
{
    int a, b;
    b=fork();

When i run the code the output is following
2389my name is manish

 the value of b = 0

Now I'm totally confused about the working of fork() call.

My question are following:

  1. How fork() works?
  2. Where the control goes after the fork() call?
  3. Can any body explain why the outputs of codes written in problem?
  4. Why the output of b occurring at different places means in first code
    the output of b = 2260 is just before the output b = 0 while the value of b = 2389 is not just before the b = 0?

Please explain me the working of fork in the code written in the problem so that I can learn it properly .

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

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

发布评论

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

评论(4

冷情妓 2024-11-20 09:21:49

首先理解为什么使用 fork 这个词来命名这个函数可能会有所帮助。听说过“岔路口”吗?在岔路口,该过程必须分路。

首先,有一个进程正常执行,直到到达 fork 调用为止。当调用 fork 时,会创建一个新进程,它几乎在所有方面都与原始进程相同,除了 fork 函数的返回值之外。新创建的进程称为子进程,因此产生它的进程被称为父进程。

由于您希望为派生的每个分支执行不同的任务,因此您需要能够区分子进程和父进程。这就是 fork 的返回值出现的地方:fork 将子进程(新创建的进程)的进程 id (pid) 返回给父进程;它向孩子返回 0。另外,如果fork执行出错,返回值为-1。

在您的代码中,您不区分子进程和父进程,因此两个进程都会运行 fork 调用之后的整个代码。

//what the child process looks like after fork is called
int main()
{
    int a, b;
    b=fork(); // <-- current line of execution: 0 is returned to b
    printf("\nmy name is manish\n");
    printf("\n my name is anil\n");
    printf("\n the value of b = %d",b);
}

// what the parent process looks like after fork is called
int main()
{
    int a, b;
    b=fork(); // <-- current line: child process id is returned
    printf("\nmy name is manish\n");
    printf("\n my name is anil\n");
    printf("\n the value of b = %d",b);
}

正如您所看到的,两个进程在分叉后都有相同的代码,因此输出是重复的。也许如果你希望父进程输出Manish,子进程输出Anil,那么你可以这样做:

int main()
{
    pid_t b; // note that the actual return type of fork is 
             // pid_t, though it's probably just an int typedef'd or macro'd

    b = fork();
    if (b == -1) perror("Fork failed");
    else if (b > 0) {
        printf("My name is Manish\n"); // parent process
    else
        printf("My name is Anil\n"); // child process

    printf("The value of b is %d\n", b);
    return 0;
}

最后,最后必须做的注释是,在你的代码中,输出似乎是由一个进程首先执行的整个过程,然后是另一个过程的整体。情况可能并非总是如此。例如,操作系统可能允许父进程执行“manish”输出,然后让该进程等待,并将 CPU 交给子进程,然后子进程执行“manish”。然而,子进程可以继续并执行“anil”和“b”输出,完成子进程的执行,从而将执行返回到父进程。现在父级通过输出“anil”和“b”本身来完成其执行。运行该程序的最终输出可能类似于:

my name is manish     // executed by parent
my name is anil       // child
the value of b = 0    // child
my name is anil       // parent
the value of b = 2244 // parent
manish.yadav@ws40-man-lin:~$ 

看一下 的手册页分叉
另请参阅 waitpid 以了解父进程对子进程的正确处理进程,这样你就不会创建僵尸。

编辑:为了回答您在评论中提出的问题,我将回答您如何简单地连续运行每个进程。

int main() 
{
     pid_t pid;
     int i;

     for (i=0; i<NUM_PROCESSES; i++)
     {
         pid = fork();
         if (pid == -1) 
         {
             perror("Error forking");
             return -1;
         }
         else if (pid > 0)
         {
             // parent process
             waitpid(-1, NULL, 0); //might want to look at man page for this
                                   // it will wait until the child process is done 
         }
         else 
         {
             // do whatever each process needs to do;
             // then exit()
             doProcess(i);
             exit(0);
         }
     }
     // do anything else the parent process needs to do
     return 0;
}

当然,这不是最好的代码,但它只是为了说明这一点。这里的主要思想是 waitpid 调用,它会导致父进程等待,直到它刚刚fork的子进程终止。子进程完成后,父进程在 waitpid 调用后继续,启动 for 循环的另一次迭代并派生另一个(下一个)进程。这一直持续到所有子进程都按顺序执行并且执行最终返回到父进程。

It might help to first understand why the word fork was used to name this function. Ever heard of a "fork on the road?" At a fork, the process has to split paths.

First there is a single process executing normally until you reach the fork call. When fork is called, a new process is created, which is identical in virtually every way as the original process, except for the return value of the fork function. The newly created process is called the child process, and hence the process that spawned it is referred to as the parent process.

Since you'd want to perform different tasks for each branch of the fork, it necessitates that you be able to distinguish the child process from the parent process. That's where the return value of fork comes in: fork returns the process id (pid) of the child (the newly created process) to the parent; it returns 0 to the child. Also, should the execution of fork go wrong, the return value is -1.

In your code, you don't distinguish between the child and parent process, so both processes run the entire code that follows after the fork call.

//what the child process looks like after fork is called
int main()
{
    int a, b;
    b=fork(); // <-- current line of execution: 0 is returned to b
    printf("\nmy name is manish\n");
    printf("\n my name is anil\n");
    printf("\n the value of b = %d",b);
}

// what the parent process looks like after fork is called
int main()
{
    int a, b;
    b=fork(); // <-- current line: child process id is returned
    printf("\nmy name is manish\n");
    printf("\n my name is anil\n");
    printf("\n the value of b = %d",b);
}

As you can see, both processes have the same code following the fork, hence the output is repeated. Perhaps if you want the parent process to output Manish and the child to output Anil, then you can do something like:

int main()
{
    pid_t b; // note that the actual return type of fork is 
             // pid_t, though it's probably just an int typedef'd or macro'd

    b = fork();
    if (b == -1) perror("Fork failed");
    else if (b > 0) {
        printf("My name is Manish\n"); // parent process
    else
        printf("My name is Anil\n"); // child process

    printf("The value of b is %d\n", b);
    return 0;
}

Finally, the last comment that must be made is that in your code, the output appears to have been executed first by one process in its entirety and then the other process in its entirety. That may not always be the case. For example, the operating system might allow the parent to execute the 'manish' output, then make this process wait, and handing the cpu over to the child process, which then executes 'manish'. However, the child process may continue and execute 'anil' and 'b' outputs, completing execution of the child process and thus returning execution back to the parent process. Now the parent finishes its execution by outputting 'anil' and 'b' itself. The final output of running this program may look something like:

my name is manish     // executed by parent
my name is anil       // child
the value of b = 0    // child
my name is anil       // parent
the value of b = 2244 // parent
manish.yadav@ws40-man-lin:~$ 

Take a look at the man page for fork.
Also look at waitpid for proper handling of child processes by parent processes so you don't create zombies.

Edit: In response to your questions in the comments, I'll answer how you can simply run each process consecutively.

int main() 
{
     pid_t pid;
     int i;

     for (i=0; i<NUM_PROCESSES; i++)
     {
         pid = fork();
         if (pid == -1) 
         {
             perror("Error forking");
             return -1;
         }
         else if (pid > 0)
         {
             // parent process
             waitpid(-1, NULL, 0); //might want to look at man page for this
                                   // it will wait until the child process is done 
         }
         else 
         {
             // do whatever each process needs to do;
             // then exit()
             doProcess(i);
             exit(0);
         }
     }
     // do anything else the parent process needs to do
     return 0;
}

Of course, isn't the best code, but it's just to illustrate the point. The big idea here is the waitpid call, which causes the parent process to wait until the child process it just forked to terminate. After the child prcoess completes, the parent continues after the waitpid call, starting another iteration of the for loop and forking another (the next) process. This continues until all child process have executed sequentially and execution finally returns to the parent.

鹿! 2024-11-20 09:21:49
  1. Fork 创建当前进程的副本。
  2. 原始文件和副本都从调用 fork() 的位置继续执行。
  3. 因为您的代码执行了两次,所以您的 print 语句也被评估两次。在复制的进程中,b的值为0。在原进程中,b的值为复制进程的进程ID。
  4. 一旦您的进程开始并发运行,它们将由您的操作系统独立调度,因此您无法保证它们何时实际运行。
  1. Fork creates a copy of your current process.
  2. Both the original and the copy continue executing from the point at which fork() was called.
  3. Because your code is executed twice, your print statements are also evaluated twice. In the copied process, the value of b is 0. In the original process, the value of b is the process ID of the copied process.
  4. Once your processes start running concurrently, they will be scheduled independently by your operating system and thus you have no guarantees about when they will actually be run.
此岸叶落 2024-11-20 09:21:49
  1. 分叉是由操作系统实现的。它基本上创建一个子进程并在fork()之后开始运行它。

  2. 父进程接收文件进程的进程id:b=fork();b有进程id。子进程获得的 pid 为零。

  3. (和 4)因为两个进程都可以并行运行或进行时间切片,所以您的输出将会有所不同。

您可能想查看一下:http://en.wikipedia.org/wiki/Fork_(operating_system) )

  1. Forking is implemented by the OS. It basically creates a child process and starts running it after the fork().

  2. The parent process receives the process id of the file process: b=fork(); b has the process id. The child process get a pid of zero.

  3. (and 4) Because both process can either run in parallel or be time sliced, your output will vary.

You may want to check this out: http://en.wikipedia.org/wiki/Fork_(operating_system)

扬花落满肩 2024-11-20 09:21:49

你最好从这个开始。

在这里您可以找到解释和代码示例。

You'd better start from this.

Here you find explanation and code example.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文