【问题标题】:How does the fork() know whether it is in child process and in parent process? [closed]fork() 如何知道它是在子进程中还是在父进程中? [关闭]
【发布时间】:2014-01-27 17:19:15
【问题描述】:

当 fork() 系统调用被执行时,处理器进入内核模式。

因此,在 fork 调用结束时,产生了一个新进程,其中包含调用进程的几乎所有构造(如堆栈、用户数据和用户程序等)的副本。

从许多得到很好回答的解释中也可以清楚地看出,进程(程序员)如何识别子进程和父进程之间的区别。根据 SO 和其他地方的许多记录在案的答案:

如果对fork() 的调用返回0,这意味着它是调用fork() 的子进程。而如果fork()的返回值为正整数,则表示fork()是在父进程中执行的,返回的正整数是子进程的PID。为简洁起见,忽略返回负值的情况。

希望我上面的理解是正确的:fingers_crossed:

但是,以下是我试图更好地理解并希望更详细/深入的内容:

(请原谅我对这个主题的无知。我只是想从内部角度更好地理解这一点。这个主题以及我想要更清楚地了解它的想法现在已经开始劫持我的梦想:P)

系统调用(当 fork() 被调用时被调用)如何知道现在它正在作为子进程的一部分执行因此应该返回0?

或者说,系统调用如何知道它正在父进程的上下文中执行因此它现在应该返回子进程的 PID 而不是 0? p>

或者是这样的,在这两个进程中,由于两个都是精确的副本,其中一个随机将返回值作为 0,另一个作为 PID然后根据哪个得到什么返回值,它被认为是父母和孩子? :thinking_face:

我很乐意在我应该通过的任何资源的方向上得到指导。我真的很感激在这个方向上的任何帮助。 :祈祷:

【问题讨论】:

  • 请花几个小时阅读Advanced Linux Programming,它很好地解释了这个棘手的问题。另请阅读fork syscall 上的维基页面。我们没有时间在这里教你。
  • 一个提示。查看进程 ID (PID)。父进程维护原始 PID,而子进程接收新的 PID。另外,前者被设置为后者的父PID。
  • fork() 被调用一次,但最终在两个不同的进程中返回两次。 O/S 负责确保发生这种情况;它会创建流程的副本并确保两个返回正确发生。
  • 当 fork 复制当前进程时,它不是一个精确副本。不同之处之一是 fork() 返回的值。

标签: linux process operating-system fork exec


【解决方案1】:

fork() 被调用时,进程会产生一个具有共享或重复进程段的子进程。这意味着在一个程序中,在调用fork() 之前,只有一个进程或一个执行单元。 fork() 返回后,有两个进程同时运行。由于此时两个进程具有相同的调用堆栈,因此它看起来每个进程就好像它刚刚调用了fork()。在父进程中,fork()的返回值是子进程的PID。在子进程中,fork()的返回值为0。

您可以通过一个非常简单的演示来了解这一点:

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

int main(){
    pid_t parent = getpid();
    pid_t child = fork();

    if(child != 0){
        printf("I am the parent process. My PID is %d\n", parent);
        printf("Parent process terminating\n");
    }
    else{
        printf("I am the child process. My PID is %d\n", getpid());
        printf("    My parent's PID is %d\n", parent);
        printf("Child process terminating\n");
    }
    return 0;
}

这是在我的笔记本电脑上运行的示例:

$ gcc -o fork fork.c
$ ./fork
I am the parent process. My PID is 16048
Parent process terminating
I am the child process. My PID is 16049
    My parent's PID is 16048
Child process terminating
$

请注意,当您运行此程序时,PID 会有所不同。另外,输出会受到竞争条件的影响,所以有时,父进程会在子进程完成打印之前返回到 shell,所以它可能看起来像这样:

$ ./fork
I am the parent process. My PID is 16265
Parent process terminating
$ I am the child process. My PID is 16266
    My parent's PID is 16265
Child process terminating

重要的是要了解fork() 导致单个执行过程分成两个独立的单元。由于每个进程仍然是从同一个程序(或源代码)产生的,因此两个进程的行为是相同的。它们的输出不同的原因只是因为fork() 为父进程或子进程返回了不同的值。

【讨论】:

  • 我想他是在问 fork 如何知道返回什么。不是根据 fork 的返回值来判断的。
  • 对我来说,他的问题表明了对使用分叉的普遍混淆,考虑到它与典型的单线程执行模型的偏差,这是可以理解的。我认为演示会比将他发送到技术参考更清楚。
  • 是的,fork() 究竟是如何知道在子进程和父进程中返回什么的???
  • 第一个(父)进程调用fork() 系统调用,操作系统计算出如何创建具有相同结构的第二个(子)进程。这取决于操作系统,但我们可以假设任何操作系统都有跟踪正在运行的进程的方法。由于系统调用能够像函数一样返回值,因此系统调用将子PID返回给父进程,将0返回给子进程。它通过内部流程簿记知道将哪个值返回给哪个流程。
  • @millinon 我认为,问题仍然存在。请允许我改写一下,以便更清楚地了解这里的问题:系统调用如何知道现在它正在作为子进程的一部分执行,因此应该返回 0?或者说,系统调用如何知道它是在父进程的上下文中执行的,因此它这次应该返回子进程的 PID 而不是 0?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-02-09
  • 2018-08-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多