linux0.11是如何加载并执行一个二进制可执行文件和shell脚本文件的?

时间:2021-10-08 07:47:34
   1.linux0.11是如何加载并执行一个二进制可执行文件和shell脚本文件的?
  答:linux0.11仅支持ZMAGIC执行文件格式,并且执行文件代码都从逻辑地址0开始执行,因此不支持含有代码或数据重定位信息的执行文件。加载并执行一个二进制文件或脚本的主要函数是do_execve(),其主要功能为:
a.   执行对命令行参数和环境参数空间页面的初始化操作------设置初试空间起始指针,初试空间页面指针数组为NULL,根据执行文件名取执行对象的i节点,计算参数个数和环境变量个数,检查文件类型,执行权限。
b.  根据执行文件开始部分的头数据结构,对其中信息进行处理------根据被执行文件i节点读取文件头部信息(二进制可执行文件和shell脚本文件都是作为普通文件进行读取);若是shell脚本程序(第一行以“#!”开始),则分析shell程序名及其参数,并以被执行文件作为参数执行指定的shell程序(这也就解释了为什么shell脚本都要以“#!”放在文件第一行开头)。
c.   对当前调用进程在运行新程序前进行初始化操作------指向新执行文件的i节点,复位信号处理句柄,根据头结构信息设置局部描述符基址和段长。设置参数和环境参数页面指针,修改进程各执行字段内容。
d.  替换堆栈中原调用execve()程序的返回地址为新执行程序运行地址,运行新加载程序(这个新执行程序运行的起始地址在这个执行文件头部数据结构中)。
(2)    说明:在do_execve()执行过程中,系统会清掉fork()复制的原程序的页目录和页表项。并释放对应的页面。系统仅为新加载的程序代码重新设置进程数据结构中的信息。申请和映射了命令行参数和环境参数块所占用的内存页面,以及设置了执行代码执行点。此时内核并不从执行文件所在设备上加载程序的代码和数据,当该过程返回时即开始执行新的程序。但一开始执行肯定会引起缺页异常中断发生,因为代码和数据还未被从块设备上读入内存,此时缺页异常处理过程会根据引起异常的线性地址在主内存区为新进程申请内存页面,并从设备上读入引起异常的指定页面,同时还为该线性地址设置对应的页目录项和页表项。
2. linux0.11中进程是如何使用各自空间的?其虚拟内存映射机制(页目录,页表)是如何实现的?
(1)    答:fork()首先会为新进程申请一页内存用来复制父进程的任务数据结构(PCB)信息,然后会为新进程修改复制的任务数据结构的某些字段值,包括利用系统调用中断发生时逐步压入堆栈的寄存器信息。重新设置任务结构中的TSS结构的各个字段值。让新进程的状态保持父进程即将进入中断过程前的状态,然后为新进程确定在线性地址空间的起始位置(nr * 64MB)。对于CPU分段机制,linux0.11的代码段和数据段在线性地址空间中的位置和长度完全相同。接着系统会为新进程复制父进程的页目录项和页表项。对于linux0.11内核来说,所有程序共用一个位于物理内存开始位置处的页目录表,而新进程的页表则需另行申请一页内存来存放,并将页目录表相应项修改并映射到该页表。