学号:sa×××310 姓名:××涛
通过上面一些对进程的学习和一些代码的验证,我们对Linux下的进程方面的知识有了一个很好的了解。
相关的文章:
Linux操作系统分析(2)- 进程的创建与可执行程序的加载
下面来简单总结一些内核装载ELF的过程总结。
简单的说,整个流程分为三步:
1)创建一个独立的虚拟地址空间;
2)读取可执行文件头,并且建立虚拟空间与可执行文件的映射关系;
3)将cpu的指令寄存器设置成可执行文件的入口地址。
过程的基本流程如下图
首先,在用户层,bash进程会调用fork()系统调用创建一个新的进程,然后新的进程调用exeve()系统调用执行制定的ELF文件,原先的bush进程继续返回等待刚才启动的新进程结束,然后继续等待命令输入。
exeve系统调用的原型如下:
int exeve(const char *filename, char *constt argv[], char *const envp[]);
三个参数分别是被执行的程序文件名,执行参数和环境变量。
在进入exeve()系统调用之后,Linux内核就开始进行真正的装载工作。在内核中,execve()系统调用相应的入口是sys_execve(), sys_execve进行一些参数的检查复制之后,调用do_execve (),doexecve()会首先查找被执行的文件,如果找到文件,则读取文件的前128个字节,之后调用scarch_binary_handle ()去搜索和匹配何时的可执行文件装载处理过程,对于ELF文件,相应的加载过程就是load_elf_binary().它的主要步骤是:
1)检查ELF可执行文件格式的有效性,比如魔数等;
2)寻找动态链接的“.interp”端,设置动态链接路径;
3)根据ELF课执行文件的程序投标的描述,对ELF文件进行映射,比如代数、数据、只读数据;
4)初始化ELF进程环境;
5)将系统调用的返回地址修改成ELF可执行文件的入口,这个入口点取决于程序的链接方式,对于静态链接的可执行文件,这个程序入口点就是ELF文件的文件头中e_entry所指地址;对于动态链接的ELF可执行文件,程序入口点就是动态链接器。
当load_elf_binary()执行完毕,返回至do_execve()再返回至sys_execve()时,第五步中已经把系统调用的返回地址改成了被装载的ELF程序的入口地址了。所以当sys_execve()系统调用从内核态返回到用户态时,eip寄存器直接跳转到ELF程序的入口地址,于是新的程序开始执行,ELF可执行文件装载完成。