接下来我们介绍进程加载
进程加载是指我们用户的应用程序
通过系统调用exec()加载
来完成一个新的可执行文件的加载
那在这里头呢
我们前面已经在介绍fork的时候
已经说过它的使用
用exec()这个系统调用
就可以加载一个新的可执行文件
到内存当中覆盖原来的
那个当前进程的地址空间
然后开始执行
那在这儿呢我们会来说
这个加载到底它在怎么做
那我们还知道
大家在系统加载的时候是啥样
我们CPU加电
加电之后去起动从BIOS里的程序
BIOS里的程序运行之后
就从硬盘上去加载引导扇区
引导扇区加载完了之后
是我的bootloader
bootloader然后再到我的内核映像
内核做了一系列工作之后
现在到我们的应用程序这个地方
那用户要想通过exec()
加载一个可执行程序
它类似于我们前面的
这种系统加载一样的
我把一个映像加载到内存当中
然后我得跳过去到指定的位置来执行
实际上这些呢中间就是有
关于可执行文件格式的识别的问题
不同的系统呢它可以加载的
可执行文件的格式是不一样的
这是我们首先要说的
然后再由这里头我们加载的时候
用户需要指定加载时候的参数
你比如说在我们exec()里头
要指定你后面有几个参数
然后每个参数分别是什么
好指定完了之后那这样的话
如果成功
加载成功了
那这时候呢它是相同的
跟加载之前是相同一个进程
ID是一样的
但是它执行了完全不同的程序
那这时候你的代码 堆栈 堆 数据等等
完全都被重写了
这是程序加载的过程
那在这里头实现这个加载的功能呢
相对来说也比较单一
也就是说我从外存上
把可执行文件加载进来
并且跳转到上面去执行就可以了
这和我们引导扇区不一样
引导扇区我读一块内容放那儿去
我对它的格式是没有任何理解的
但是我们现在
到执行一个应用程序的时候
你里头那可执行文件的格式
是非常复杂的
所以在这里呢主要的工作就是
你可执行文件格式的识别
那具体说起来呢在这儿呢
分成三个主要的函数
一个是sys_exec
一个是do_execve
一个是load_icode
那第一个呢
实际上是我在这里获取相应的参数
核心加载功能是在这里头
而在这里头呢最核心的部分呢
是load_icode这实际上是
识别你的可执行文件的格式
并且把它加载到
在内存里加载相应对应的段
然后开始执行
那在ucore里呢
有一个sys_exec()这样一个内核函数
它完成的呢
就是获取我们创建进程的参数
然后到这边呢它获取这些参数之后
最后调到的结果
我们可以从这儿可以看到do exec()
这是内核关于
进程加载执行的最主要的函数
在这个函数里头呢
它主要要做的工作呢
是在这里创建新进程所需要的
内存的相关的这些段结构
比如在这儿
这个地方是打开文件
读你ELF文件的内容
进来进行相应的创建
然后下面这地方呢
是它所需要的内存地址空间的
映射的创建 mm_create()
然后这地方是设置页表的基址
然后这是我们刚才在那里看到的
load_icode()这个函数
这个函数在我们这里呢
主要是解析相应的
可执行文件的格式
我们可以看到它在这里头的控制流图
那在这里头呢
它最主要的一个部分就是去读文件
那这是它最主要的操作
然后更具体的相关的实现呢
希望大家下去之后
利用这些工具可以很方便的看到
好在加载完了之后呢
那我们程序就开始执行了
实际上我们在前面讲创建的时候
也已经说过了
我的系统里的第一个线程
是在那个proc_init()里头来进行的
proc_init()那在这里呢
它手工的构造出一个进程控制块
然后把它放到就绪队列里头
然后开始执行
这时候它起动的第一个用户态的程序
就是这个init_main()
在这里头呢做了
我们下面会去走的shell的程序
那在这里头具体的执行过程呢
我们通过相应的实际代码阅读来完成
接下来我们说ucore创建的第一个进程
创建进程的函数呢
是我们这里的proc_init()
在这个函数里头呢
我们刚才已经从kern_init()里头
看到过这个函数
它完成两个内核线程的创建
idleproc()initproc()
那在这儿呢我们可以通过
它的流程图来给出一个简要的
这是proc_init()的流程图
好那在这里头我们看到
它创建第一个标志性的操作呢
是在这儿idleproc()
在这里给它复制相应的状态信息
这是利用alloc_proc()来创建
idleproc的进程控制块数据结构
然后下边这边呢就是initproc
这是在这里呢
用这里头kernel_thread()这个函数
来创建一个内核线程
执行的函数是init _main
这个内核线程创建完毕之后呢
它被赋值通过ID找
赋值然后确认它就是initproc
这是我们要找到的创建的第二个函数
然后在这个init _main这个函数里
它做了一些什么呢
实际上它这里
又创建了两个内核线程
那这两个内核线程
从这儿呢我们可以很清楚地看到
这是第一个
然后这是第二个