Linux内核如何装载和启动一个可执行程序

本文通过实验演示了如何使用gdb调试工具逐步跟踪Linux系统中的execve系统调用,详细介绍了从删除并重新克隆menu项目开始,直至设置断点并观察execve系统调用的具体流程。同时,分析了execve系统调用内部如何加载和执行可执行文件的过程。

一、实验过程

1.打开控制台,进入Linux目录下,然后输入命令rm menu -rf 删除menu,然后输入命令Git clone https://github.com/mengning/menu.git 重新克隆一个menu,实验结果如图所示。
这里写图片描述
2.用test_exce.c 代替test.c
这里写图片描述
3.输入make rootfs对程序进行编译,并启动MENUOS,如图所示。
这里写图片描述
4.使用gdb来调试
这里写图片描述
5.在gdb中输入命令 b execve,b load_elf_binary,b start_thread设置断点,然后利用gdb进行跟踪调试。实验结果如下图所示。
这里写图片描述
6. 在menuos的命令提示符下输入exec命令,可以发现exec命令卡住了如下图所示
这里写图片描述
7. 此时可以在gdb调式窗口继续输入c发现gdb停留在load_elf_binary断点处,输入list命令可以查看断点处相应的代码。继续输入c命令,程序执行到start_thread断点处,如下图所示
这里写图片描述
8. 接着输入s可以一步一步跟踪发现start_thread是如何设置进程内核堆栈的EIP的,实验及图如下所示
这里写图片描述
以上只是设置了exeve系统调用过程中比较重要几个断点进行跟踪调试,其实我们还可以设置更为详细的断点来仔细了解内核是如何加载和启动可执行程序的。

二、分析exec*函数对应的系统调用处理过程

在使用exec*函数的时候,一般首先需要调用一个fork来生成一个新的子进程(否则原有的进程将会被覆盖掉),然后新的进程调用execve()系统调用来执行指定的ELF文件。内核调用sys_execve函数来实现execve。
sys_execve通过调用 do_execve_common,首先访问需要加载文件所在的目录文件,然后通过search_binary_handle在目录中检索需要执行的文件,并根据文件类型来采用对应的加载函数对其进行加载。在加载的过程中,将原来进程的代码段、以及堆栈等利用所加载的文件中的对应值进行替换,最后重新设定EIP和ESP来使可执行文件运行起来。
至于运行参数以及环境变量,则是首先传递到系统调用,然后传递到一个struct linux_binprm类型的结构体中,最后,该结构体变量作为参数参与load工作,将程序的运行参数以及环境变量参数应用到可执行程序上。

陈涛 + 原创作品转载请注明出处 + 《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值