21.一个新进程的诞生

21.一个新进程的诞生

一个新进程的诞生,从操作系统的源码角度来说,其实就两行代码。而关于创建进程的重点,其实就一行代码,就是大名鼎鼎的 fork 函数。

我们先来看一张图,看看操作系统从开机到怠速都做了些什么事情。

图片

你看,第一部分和第二部分,为我们这个第三部分做了充足的铺垫工作。

第一部分 进入内核前的苦力活

第二部分 大战前期的初始化工作

到了第三部分,简单说就是从内核态切换到用户态,然后通过 fork 创建出一个新的进程,再之后老进程进入死循环。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
void main(void) {    
    // 第二部分的内容,各种初始化工作    
    ...    
    // 第三部分的内容,一个新进程的诞生    
    move_to_user_mode();    
    if (!fork()) {        
        // 新进程里干了啥,是第四部分的内容        
        init();    
    }    
    // 死循环,操作系统怠速状态    
    for(;;) pause();
}

至于 fork 出来的新进程做了什么事,就是 init 函数里的故事里,这个不在第三部分的讨论范畴。

所以你看,一共就两行代码,顶多再算上最后一行的死循环,三行,就把创建新进程这个事搞定了。

再加上新进程里要做的 init 函数,一共四行代码,就走到了 main 函数的结尾,也就标志着操作系统启动完毕!

但就是这没有多少个字母的四行代码,是整个操作系统的精髓所在,也是最难的四行代码。

理解了它们,你就会有原来操作系统就是这破玩意的感叹了~

今天我们就总览一下这四句,很轻松。

第一句是 move_to_user_mode

直译过来即可,就是转变为用户态模式。

因为 Linux 将操作系统特权级分为用户态与内核态两种,之前都处于内核态,现在要先转变为用户态,仅此而已。

一旦转变为了用户态,那么之后的代码将一直处于用户态的模式,除非发生了中断,比如用户发出了系统调用的中断指令,那么此时将会从用户态陷入内核态,不过当中断处理程序执行完之后,又会通过中断返回指令从内核态回到用户态。

图片

整个过程被操作系统的机制拿捏的死死的,始终让用户进程处于用户态运行,必要的时候陷入一下内核态,但很快就会被返回而再次回到用户态,是不是非常无奈?

第二句是 fork

这是创建一个新进程的意思,而且所有用户进程想要创建新的进程,都需要调用这个函数。

原来操作系统只有一个执行流,就是我们一直看过来的所有代码,就是进程 0,只不过我们并没有意识到它也是一个进程。调用完 fork 之后,现在又多了一个进程,叫做进程 1。

当然,更准确的说法是,我们一路看过来的代码能够被我们自信地称作进程 0 的确切时刻,是我们在 第18回 | 进程调度初始化 sched_init 里为当前执行流添加了一个进程管理结构到 task 数组里,同时开启了定时器以及时钟中断的那一个时刻。

图片

因为此时时钟中断到来之后,就可以执行到我们的进程调度程序,进程调度程序才会去这个 task 数组里挑选合适的进程进行切换。所以此时,我们当前执行的代码,才真正有了一个进程的身份,才勉强得到了一个可以被称为进程 0 的资格,毕竟还没有其他进程参与竞争。

如果你觉得这些话很困惑,就对了,在理解了整个这一块的细节之后,尤其是对于进程调度这种被人赋予了好多虚头巴脑的名词的地方,你会豁然开朗的。

第三句是 init

只有进程 1 会走到这个分支来执行。这里的代码可太多了,它本身需要完成如加载根文件系统的任务,同时这个方法将又会创建出一个新的进程 2,在进程 2 里又会加载与用户交互的 shell 程序,此时操作系统就正式成为了用户可用的一个状态了。

当然,当你知道了新进程诞生的过程之后,进程 2 的创建,就和进程 1 的创建一样了,在后面的章节中你将不会再困惑创建新进程的过程,减轻了学习负担。所以这一部分,又是作为下一部分的重要基础,环环相扣。

我们的教育,往往是强调知识点。但我认为,整个知识都是成体系的,没有哪个地方可以单点立起整个的理解大厦,必须一环扣一环。幸运的是,每一环都是十分简单且纯粹的。

第四句是 pause

当没有任何可运行的进程时,操作系统会悬停在这里,达到怠速状态。没啥好说的,我一直强调,操作系统就是由中断驱动的一个死循环。

一共四句话,切换到用户态,创建新进程,初始化,然后悬停怠速。

乍一看,是不是特别简单?是的,不过当你展开每一段代码的细节后你会发现,一个庞大的世界让你无从下手。但当你把全部细节都捋顺了之后你又会发现,不过如此。

updatedupdated2024-05-102024-05-10