Linux0.11源代码中的execve函数实现源代码分析

概述

在阅读Linux0.11源代码的过程中,在init函数的执行过程中遇到了execve系统调用,对其实现不甚理解,
因此特地阅读其实现代码,深入理解其代码背后的底层执行过程。

该系统调用在system_call.s中的实现代码比较短,如下,但是其中调用了_do_execve函数,该函数在
kernel/exec.c中实现,后面主要关注该函数的实现

1
2
3
4
5
6
7
align 4
_sys_execve:
lea eax,[R_EIP+esp]
push eax
call _do_execve
add esp,4 ;// 丢弃调用时压入栈的R_EIP 值。
ret

do_execve

我们不关注该函数起始部分的一些变量声明行为,该函数的执行功能表述如下:

  1. 为进程初始化一个长度为32的页表
  2. 根据传入的filename信息,获取其inode信息,出错返回。
  3. 计算命令行参数个数和环境变量参数。
  4. 判断inode是否为一个常规文件,不是则返回出错信息。
  5. 检查inode用户相关权限信息,没有执行权限则出错返回。
  6. 前述执行通过,读取inode的第一块数据到缓冲区内,出错要返回。
  7. 读取可执行文件的头部数据结构,该数据结构的类型exec定义在a.out.h中。
  8. 判断程序文件的开头是否为#!,如果是,则需要进一步处理。
  9. 对7中读取的可执行文件头进行判断
  10. 将当前进程任务结构体的executable设置为程序文件的inode。
  11. 设置当前任务结构的sigaction的句柄设置为null。
  12. 释放程序代码段和数据段对应的页表
  13. 处理协处理器相关内容
  14. 在ldt局部描述符表中设置代码段基地址和段限长等等
  15. 创建环境之参数变量指针表
  16. 设置进程堆栈指针所在页面为堆栈指针所在页面
  17. 初始化bss段
  18. 将程序计数器指向本程序开始的代码
  19. 将堆栈指针设置为本程序堆栈段开始的地方。

待整理

change_ldt

create_tables