如何在处理器中创建进程?
How a process is created in a processor?
当我在 unix/Linux 中执行程序时,幕后到底发生了什么?
谁负责创建进程?
我是否需要调用内核来启动进程(我的程序实例)?从这个意义上说,我的程序应该 运行 在处理器上进行内核调用,对吗?那么第一个内核调用是如何发生在一个进程的启动上的呢? .这就像一个僵局吗?那么内核首先出现在哪里?
抱歉,我刚刚阅读了很多关于所有这些的文档,但仍然无法连接点或了解全貌。有人可以详细说明一下吗?
你的程序是别人启动的,不是你的程序启动的(否则就是先有鸡还是先有蛋的悖论)。假设您 运行 来自某些 shell 的程序,shell 对负责启动新进程的 Linux 内核函数进行内核调用。它启动您的程序所需的内存 space 并调用其 main.现在,每次您的程序需要需要 cpl3 的东西时,它都会调用内核函数。
在 Unix 系统(以及大多数现代非 Unix 系统)上,进程是一棵树 - 每个进程都有一个父进程(进程 ID 为 1 的进程除外,init 进程由启动时的内核)。
当您登录系统时,您通常登录到“shell”程序的一个实例(程序=可执行文件,shell=用户交互)。在Windows上,Explorer.exe
是shell。在 Unix 系统上,传统上您的 shell 类似于 bash
。在 Linux 桌面上,您有一个像 Gnome 这样的图形环境,它是您的 shell,您可以将它用于 运行 程序,例如 gnome-terminal
恰好 运行另一个程序恰好是基于文本的 shell,如 bash
而不是图形 shell.
无论你的 运行 你的程序来自 Gnome,来自 bash
,还是来自任何其他程序 P
,无论是否交互,P
是的父进程您的进程,我们称之为 C
,因此 P
是启动创建 C
.
的进程
它在 Unix 中的工作方式,通常是这样的:
P
实际上是 运行 宁 CPU.
P
调用fork()
系统调用,这是一个内核API.
- 作为响应,内核创建进程
P
的副本作为新进程,C
。
- 那时,
C
不在任何 CPU 上 运行。
- 现在你有 2 个进程,
P
和 C
是同一程序的两个独立实例。
- 当内核的调度程序决定 运行
C
的时候,它选择一个 CPU,并设置 CPU 的堆栈指针,数据指针,代码指针和页表指向 C
内存中的适当地址。
- CPU 基本上是硬件,运行 是一个始终执行下一个代码指针(“指令指针”)的循环,因此一旦将代码指针设置为新代码,它将 运行 新代码。
- 请注意,
C
中的新代码仍然是 P
中旧代码的副本。
- 现在
C
是运行ning,它调用execve()
系统调用,这是另一个内核API。
- 这是启动程序的父进程逻辑的一部分 - 您调用
fork()
,然后检查您是原始 P
还是克隆 C
,如果你是 C
,你会打电话给 execve()
。
- 作为响应,内核创建一个新内存space(“地址space”),其中将包含新程序的堆、堆栈、代码等,将可执行文件加载到该内存中,然后将这个新内存声明为“process
C
”。
- 将可执行文件加载到内存中的一部分是为 CPU 最终可以指向的堆栈指针、数据指针、代码指针和页表创建新的适当地址。
- 特别地,代码指针的地址是新程序入口点的地址。
- (我在这里简化)内核的调度程序然后再次将 CPU 的指针设置为那些
C
- 本质上是“重新调度”它。只有现在那些指向新内存 space.
- 当控制权从内核返回到
C
时,它现在指向新程序的入口点,最终将调用 main()
。
当我在 unix/Linux 中执行程序时,幕后到底发生了什么?
谁负责创建进程?
我是否需要调用内核来启动进程(我的程序实例)?从这个意义上说,我的程序应该 运行 在处理器上进行内核调用,对吗?那么第一个内核调用是如何发生在一个进程的启动上的呢? .这就像一个僵局吗?那么内核首先出现在哪里?
抱歉,我刚刚阅读了很多关于所有这些的文档,但仍然无法连接点或了解全貌。有人可以详细说明一下吗?
你的程序是别人启动的,不是你的程序启动的(否则就是先有鸡还是先有蛋的悖论)。假设您 运行 来自某些 shell 的程序,shell 对负责启动新进程的 Linux 内核函数进行内核调用。它启动您的程序所需的内存 space 并调用其 main.现在,每次您的程序需要需要 cpl3 的东西时,它都会调用内核函数。
在 Unix 系统(以及大多数现代非 Unix 系统)上,进程是一棵树 - 每个进程都有一个父进程(进程 ID 为 1 的进程除外,init 进程由启动时的内核)。
当您登录系统时,您通常登录到“shell”程序的一个实例(程序=可执行文件,shell=用户交互)。在Windows上,Explorer.exe
是shell。在 Unix 系统上,传统上您的 shell 类似于 bash
。在 Linux 桌面上,您有一个像 Gnome 这样的图形环境,它是您的 shell,您可以将它用于 运行 程序,例如 gnome-terminal
恰好 运行另一个程序恰好是基于文本的 shell,如 bash
而不是图形 shell.
无论你的 运行 你的程序来自 Gnome,来自 bash
,还是来自任何其他程序 P
,无论是否交互,P
是的父进程您的进程,我们称之为 C
,因此 P
是启动创建 C
.
它在 Unix 中的工作方式,通常是这样的:
P
实际上是 运行 宁 CPU.P
调用fork()
系统调用,这是一个内核API.- 作为响应,内核创建进程
P
的副本作为新进程,C
。
- 那时,
C
不在任何 CPU 上 运行。 - 现在你有 2 个进程,
P
和C
是同一程序的两个独立实例。
- 当内核的调度程序决定 运行
C
的时候,它选择一个 CPU,并设置 CPU 的堆栈指针,数据指针,代码指针和页表指向C
内存中的适当地址。 - CPU 基本上是硬件,运行 是一个始终执行下一个代码指针(“指令指针”)的循环,因此一旦将代码指针设置为新代码,它将 运行 新代码。
- 请注意,
C
中的新代码仍然是P
中旧代码的副本。
- 现在
C
是运行ning,它调用execve()
系统调用,这是另一个内核API。
- 这是启动程序的父进程逻辑的一部分 - 您调用
fork()
,然后检查您是原始P
还是克隆C
,如果你是C
,你会打电话给execve()
。
- 作为响应,内核创建一个新内存space(“地址space”),其中将包含新程序的堆、堆栈、代码等,将可执行文件加载到该内存中,然后将这个新内存声明为“process
C
”。
- 将可执行文件加载到内存中的一部分是为 CPU 最终可以指向的堆栈指针、数据指针、代码指针和页表创建新的适当地址。
- 特别地,代码指针的地址是新程序入口点的地址。
- (我在这里简化)内核的调度程序然后再次将 CPU 的指针设置为那些
C
- 本质上是“重新调度”它。只有现在那些指向新内存 space. - 当控制权从内核返回到
C
时,它现在指向新程序的入口点,最终将调用main()
。