在 OS 中创建新流程
Creation of A New Process in an OS
在书 'Operating System Concepts' - 第 9 版 - 第 3 章 - 第 117 页 - 第 120 页它说:
Both processes (the parent and the child) continue execution at the instruction after the fork(), with one difference: the return code for the fork() is zero for the new (child) process, whereas the (nonzero) process identifier of the child is returned to the parent.
The only difference is that the value of pid (the process identifier) for the child process is zero, while that for the parent is an integer value greater than zero (in fact, it is the actual pid of the child process).
谁能给我解释一下这个概念。
当您在代码中调用 fork 时,它 return 有两个值以防调用成功,一个是 parent(代码 运行 by parent),另一个是零对于 child(child 的代码 运行)
int childparent;
childparent = fork();
if (childparent >=0)
{
if (childparent==0)
//child code
if (childparent>0)
//parent code
}
你的句子中提到的 pid 0 不是 shell 命令显示的进程 ID ps
编辑:是的,parent(如果 childparent>0)案例中的代码 运行ning 在上下文中是 运行ning具体 child 刚刚创建。所以 return 到 parent 的值是 child 实际进程 ID (PID)。如果你分叉你的简单代码并在代码中睡很长时间足以运行 ps 你可以匹配 PS 中显示的 PID 和 parent 中的 printf return fork() 的值 (printf("%d",childparent))
每当处理器(CPU) 运行是一个程序时,它都会存储它正在执行的代码的行号(更正式的地址是指向该指令的地址)。计算机将它存储在一个称为堆栈指针的寄存器(一种变量)。所以堆栈指针(SP)将存储当前处理器必须执行的指令(或运行)。这样计算机就会跟踪应该执行哪条指令。
当程序 运行s 时,它会在计算机的主 memory.Here 中分配一些小内存,我们所有的代码以及重要的寄存器(包括 SP)都在其中,这有助于处理器跟踪running.Too 进程由进程 ID (PID) 唯一标识时的程序。
现在让我来回答你的问题。每当我们调用 fork 时,都会创建您调用 fork 的程序的副本。此副本称为 "child process",我们的原始进程称为 parent 进程。
创建副本时,您的程序分配的所有内存都被复制到内存中的某个其他位置(现在是 child 进程的内存)。所以一个相同的 运行ning 程序(进程)已创建。
现在这个复制的内存包含 parent 进程的 SP,所以每当处理器 运行 发送程序时,它直接 运行 发送来自同一个 fork 调用行的程序(因为SP 将在创建进程时将此行存储为当前指令)。由于我们的 fork 调用成功,它必须 return 一个 non-negative 值(表示 fork 系统调用成功)所以它 return 0 到 child 进程,child 进程 ID 到 parent(因为当前进程 ID 也指向这里)。
将 Child 进程 ID 返回到 parent 很划算,因为 parent 可以更好地跟踪从 it.Too 创建的 child 进程returning child a 0 使交易变得更好,因为我们必须 return a non-negative 数字和其他正数可能是某个进程的 PID。
运行 cd /proc 在你的 linux 系统中。所有具有一些数字名称的目录都是某个进程的 pid(可能是 active/inactive)。阅读更多关于它的信息以清除概念。
希望这能消除您的疑虑:)。
fork()
通过创建一个新进程然后用当前进程填充它来制作当前进程的完整副本。它选择一个作为 parent,另一个作为 child。仅通过调整fork()
的return值来表示差异。如果进程忽略 return 值,则它们的行为相同。 (与信号处理和传递、使用特殊属性打开的文件描述符、内存映射等相关的进程之间存在一些很少见的其他差异)
当您认为自己开始理解它时,请查看 this 看看您是否理解。
我看书的时候也有这个疑惑。答案如下:
当主程序(parent)执行fork()时,会创建一个其地址space的副本,包括程序和所有数据。系统调用 fork() returns child 进程 ID 到 parent 和 returns 0 到 child 进程。 parent 和 child 进程现在都可以从 fork 系统调用后的下一行开始执行。
让我用一个简单的例子来说明这一点。
考虑这段代码:
main()
{
pid=fork();
if(pid == 0) // Condition to determine Parent/Child Process
ChildProcess();
else
ParentProcess();
}
void ChildProcess()
{
//Some Arbitrary Code
}
void ParentProcess()
{
//Some Arbitrary Code
}
此代码段解释了基于条件,进程(parent 和 child)现在可以以它们自己的 pre-defined 方式执行。
在上面的例子中,假设 child 的进程 ID 是 3456,那么 parent 将从 fork 中获取该 ID 作为 return 值。但是,child 总是将 process-id 设为 0,然后继续执行。
fork() 调用的设计是因为 child 进程的完整管理现在可以由 parent 处理,而 parent 始终可以通过 implicitly/explicitly 调用 exit() 系统调用,记录哪些 child 进程正常或异常终止。 parent 也可以通过 wait() 系统调用简单地等待 child,然后 return child 的 pid,这样 parent 可以记下 child 已终止。
这就是 child 进程创建和终止的处理方式。
我想在这里补充一件事,它与问题不完全相关,但我认为会有所帮助。
您还会注意到本书讨论后立即对 exec() 系统调用的描述。简而言之,这两个讨论都解释了这一点:
Forking provides a way for an existing process to start a new one, but
what about the case where the new process is not part of the same
program as parent process? This is the case in the shell; when a user
starts a command it needs to run in a new process, but it is unrelated
to the shell.
This is where the exec system call comes into play. exec will replace
the contents of the currently running process with the information
from a program binary.
Thus the process the shell follows when launching a new program is to
firstly fork, creating a new process, and then exec (i.e. load into
memory and execute) the program binary it is supposed to run.
如果您想了解有关 fork() 系统调用的更多信息,那么您还应该了解其内部实现,尤其是 clone() 系统调用的工作原理。
参考站点:
在书 'Operating System Concepts' - 第 9 版 - 第 3 章 - 第 117 页 - 第 120 页它说:
Both processes (the parent and the child) continue execution at the instruction after the fork(), with one difference: the return code for the fork() is zero for the new (child) process, whereas the (nonzero) process identifier of the child is returned to the parent.
The only difference is that the value of pid (the process identifier) for the child process is zero, while that for the parent is an integer value greater than zero (in fact, it is the actual pid of the child process).
谁能给我解释一下这个概念。
当您在代码中调用 fork 时,它 return 有两个值以防调用成功,一个是 parent(代码 运行 by parent),另一个是零对于 child(child 的代码 运行)
int childparent;
childparent = fork();
if (childparent >=0)
{
if (childparent==0)
//child code
if (childparent>0)
//parent code
}
你的句子中提到的 pid 0 不是 shell 命令显示的进程 ID ps
编辑:是的,parent(如果 childparent>0)案例中的代码 运行ning 在上下文中是 运行ning具体 child 刚刚创建。所以 return 到 parent 的值是 child 实际进程 ID (PID)。如果你分叉你的简单代码并在代码中睡很长时间足以运行 ps 你可以匹配 PS 中显示的 PID 和 parent 中的 printf return fork() 的值 (printf("%d",childparent))
每当处理器(CPU) 运行是一个程序时,它都会存储它正在执行的代码的行号(更正式的地址是指向该指令的地址)。计算机将它存储在一个称为堆栈指针的寄存器(一种变量)。所以堆栈指针(SP)将存储当前处理器必须执行的指令(或运行)。这样计算机就会跟踪应该执行哪条指令。
当程序 运行s 时,它会在计算机的主 memory.Here 中分配一些小内存,我们所有的代码以及重要的寄存器(包括 SP)都在其中,这有助于处理器跟踪running.Too 进程由进程 ID (PID) 唯一标识时的程序。
现在让我来回答你的问题。每当我们调用 fork 时,都会创建您调用 fork 的程序的副本。此副本称为 "child process",我们的原始进程称为 parent 进程。
创建副本时,您的程序分配的所有内存都被复制到内存中的某个其他位置(现在是 child 进程的内存)。所以一个相同的 运行ning 程序(进程)已创建。
现在这个复制的内存包含 parent 进程的 SP,所以每当处理器 运行 发送程序时,它直接 运行 发送来自同一个 fork 调用行的程序(因为SP 将在创建进程时将此行存储为当前指令)。由于我们的 fork 调用成功,它必须 return 一个 non-negative 值(表示 fork 系统调用成功)所以它 return 0 到 child 进程,child 进程 ID 到 parent(因为当前进程 ID 也指向这里)。
将 Child 进程 ID 返回到 parent 很划算,因为 parent 可以更好地跟踪从 it.Too 创建的 child 进程returning child a 0 使交易变得更好,因为我们必须 return a non-negative 数字和其他正数可能是某个进程的 PID。
运行 cd /proc 在你的 linux 系统中。所有具有一些数字名称的目录都是某个进程的 pid(可能是 active/inactive)。阅读更多关于它的信息以清除概念。
希望这能消除您的疑虑:)。
fork()
通过创建一个新进程然后用当前进程填充它来制作当前进程的完整副本。它选择一个作为 parent,另一个作为 child。仅通过调整fork()
的return值来表示差异。如果进程忽略 return 值,则它们的行为相同。 (与信号处理和传递、使用特殊属性打开的文件描述符、内存映射等相关的进程之间存在一些很少见的其他差异)
当您认为自己开始理解它时,请查看 this 看看您是否理解。
我看书的时候也有这个疑惑。答案如下:
当主程序(parent)执行fork()时,会创建一个其地址space的副本,包括程序和所有数据。系统调用 fork() returns child 进程 ID 到 parent 和 returns 0 到 child 进程。 parent 和 child 进程现在都可以从 fork 系统调用后的下一行开始执行。 让我用一个简单的例子来说明这一点。
考虑这段代码:
main()
{
pid=fork();
if(pid == 0) // Condition to determine Parent/Child Process
ChildProcess();
else
ParentProcess();
}
void ChildProcess()
{
//Some Arbitrary Code
}
void ParentProcess()
{
//Some Arbitrary Code
}
此代码段解释了基于条件,进程(parent 和 child)现在可以以它们自己的 pre-defined 方式执行。
在上面的例子中,假设 child 的进程 ID 是 3456,那么 parent 将从 fork 中获取该 ID 作为 return 值。但是,child 总是将 process-id 设为 0,然后继续执行。
fork() 调用的设计是因为 child 进程的完整管理现在可以由 parent 处理,而 parent 始终可以通过 implicitly/explicitly 调用 exit() 系统调用,记录哪些 child 进程正常或异常终止。 parent 也可以通过 wait() 系统调用简单地等待 child,然后 return child 的 pid,这样 parent 可以记下 child 已终止。
这就是 child 进程创建和终止的处理方式。
我想在这里补充一件事,它与问题不完全相关,但我认为会有所帮助。
您还会注意到本书讨论后立即对 exec() 系统调用的描述。简而言之,这两个讨论都解释了这一点:
Forking provides a way for an existing process to start a new one, but what about the case where the new process is not part of the same program as parent process? This is the case in the shell; when a user starts a command it needs to run in a new process, but it is unrelated to the shell.
This is where the exec system call comes into play. exec will replace the contents of the currently running process with the information from a program binary.
Thus the process the shell follows when launching a new program is to firstly fork, creating a new process, and then exec (i.e. load into memory and execute) the program binary it is supposed to run.
如果您想了解有关 fork() 系统调用的更多信息,那么您还应该了解其内部实现,尤其是 clone() 系统调用的工作原理。
参考站点: