0.sys_execve:系统调用,让进程执行某个程序
(1)在系统空间建立一个路径名的副本(见1)
(2)do_execve()(见2)
(3)释放路径名副本(即作为缓冲区的管理页面)
1.getname()
(1)在系统空间定义一个缓冲指针
(2)分配一个物理页面作为缓冲区
(3)将路径名从用户空间复制到缓冲区
(4)缓冲区指针指向这个物理页面
2.do_execve()
(1)打开可执行文件(结合文件系统来阅读)
(2)初始化bprm数据结构(见3)
bprm是用于保存可执行文件上下文的数据结构
(3)用formats队列中相应的“代理人”来可执行文件装入(4)
formats队列中的成员代表着各种可执行文件的代理人,每个成员只认识且处理一种特定格式的可执行文件的运行
3.初始化bprm数据结构(bprm是用于保存可执行文件上下文的数据结构)
(1)初始化各个成员变量
(2)统计参数个数和环境变量个数
(3)从可执行文件中读入开头128个字节到bprm缓冲区
不管是什么格式的可执行文件,开头的128个字节包含了关于可执行文件属性的必要成充分的信息
(4)把filename从系统空间复制到bprm
(5)把参数从用户空间复制到bprm
(6)把环境变量从用户空间复制到bprm
4.search_binary_handler()
(1)依次让formats队列中的每个成员尝试它们的load_binary()函数
load_binary()用于装入可执行程序。假设是a.out格式的可执行文件,以load_aout_binary()为例说明load_binary()的过程(见5)
(2)若尝试成功(那么一定已经装入成功),则让可执行文件投入运行
(3)若全部失败,则装入相应的模块,再从step1开始再尝试一次(一共只尝试两次)
5.load_aout_binary():将a.out格式的可执行文件
(1)各种检查(见6)
(2)与父进程“决裂”(见7)
拥有独立的信号处理表、用户空间、文件打开信息等,不再与父进程共享
(3)当前进程的一些初始化(见10)
(4)根据a.out具体的不同格式,以不同的方式装入代码段和数据段(见11)
(5)将入bss段
调用do_brk()函数,为bss段分配空间,并建立映射
(6)将入堆栈段(见12)
(7)设置regs指针
regs指向保留在当前进程的系统空间堆栈中的各个寄存器副本。当进程从系统调用返回时,这些值就会被“恢复”到CPU的各个寄存器中
6.各种检查
(1)检查目标文件的格式,是不是a.out格式的可执行文件
(2)data段和bss段总和不能超过某个限制
7.flush_old_exec
(1)建立独立的信号处理表,不再与父进程共享(见8)
(2)释放从父进程继承来的用户空间(见9)
运行后子进程有了独立的用户空间,但是大小为0
即放弃从父进程继承来的全部空间,不管是通过复制不断是通过共享 (3)修改程序名
(4)如果当前进程曾是父进程的一个线程,共享父进程的用户空间,则从线程组中脱离,因为有了独立的空间
(5)关闭文件
打开文件的信息也是从父进程继承过来的。扫描文件位图指示,把打开的文件关掉
8.建立独立的信号处理表
(1)为独立的信号处理表开辟空间并复制或赋值
(2)递减父进程信号处理表的引用计数
(3)若父进程信号处理表的引用计数减为0,则释放
(4)若信号处理表的表项指向用户空间的子程序,则改为SIG_DFL
中断向量表的表项一定指向一个中断服务程序
信号处理表的表项有三种:忽略SIG_IGN,默认SIG_DFL,指向用户空间的子程序
因为用户空间已经被释放了,所以要改
9.exec_mmap:释放从父进程释放的用户空间
(1)若子进程的用户空间是通过复制得到的,则
A.唤醒父进程
B.释放mm_struct中所有的vm_area_struct结构
C.页面表的表项清0
D.使高速缓存与内存一致
(2)若子进程的用户空间是通过共享得到的,则
A.为进程分配一个mm_struct结构
B.把新的mm_struct结构加入到全局的mm_struct队列中
C.设置mm_struct为进程的当前用户空间
D.切换到当前用户空间
E.唤醒父进程
F.若父进程用户空间的引用计数减为0,则释放(移出全局的mm_struct队列,并释放空间)
G.释放一个临时的mm_struct(只是减少引用计数)
10.一些初始化
(1)设置代码段、数据段、bss段要存放的位置
数据段存放的是已经初始化的全局变量和静态变量
bss段存放的是未初始化的全局变量和静态变量
(2)计算权限
11.根据a.out具体的不同格式,以不同的方式装入代码段和数据段
(1)若是OMAGIC类型,则:
A.为代码段和数据段合在一起分配空间
B.把代码段和数据段从文件是读来
(2)若不是OMAGIC类型,则:
A.分别将文件中的代码和数据段映射到进程的用户空间,映射地址与装入的地址一致
12.装入堆栈段
(1)在用户空间的堆栈区顶部建立一个卡虚存空间,将参数与环境变量所占的物理页面与些虚存区间建立映射
由此可见,堆栈的起始位置不是严格地从3G位置开始的
(2)在堆栈的栈顶构筑envp[],argv[]和argc