概述
在阅读Linux0.11源代码的过程中,在init函数的执行过程中遇到了execve系统调用,对其实现不甚理解,
因此特地阅读其实现代码,深入理解其代码背后的底层执行过程。
该系统调用在system_call.s中的实现代码比较短,如下,但是其中调用了_do_execve函数,该函数在
kernel/exec.c中实现,后面主要关注该函数的实现
1 | align 4 |
do_execve
我们不关注该函数起始部分的一些变量声明行为,该函数的执行功能表述如下:
- 为进程初始化一个长度为32的页表
- 根据传入的filename信息,获取其inode信息,出错返回。
- 计算命令行参数个数和环境变量参数。
- 判断inode是否为一个常规文件,不是则返回出错信息。
- 检查inode用户相关权限信息,没有执行权限则出错返回。
- 前述执行通过,读取inode的第一块数据到缓冲区内,出错要返回。
- 读取可执行文件的头部数据结构,该数据结构的类型exec定义在a.out.h中。
- 判断程序文件的开头是否为#!,如果是,则需要进一步处理。
- 对7中读取的可执行文件头进行判断
- 将当前进程任务结构体的executable设置为程序文件的inode。
- 设置当前任务结构的sigaction的句柄设置为null。
- 释放程序代码段和数据段对应的页表
- 处理协处理器相关内容
- 在ldt局部描述符表中设置代码段基地址和段限长等等
- 创建环境之参数变量指针表
- 设置进程堆栈指针所在页面为堆栈指针所在页面
- 初始化bss段
- 将程序计数器指向本程序开始的代码
- 将堆栈指针设置为本程序堆栈段开始的地方。
待整理
change_ldt
create_tables