《Linux内核与分析》第七周
by 21035130王川东
Linux内核如何装载和启动一个可执行程序
一、 EIF文件格式:
1、ELF头部在文件的开始,描述文件的总体格式,保存了路线图,描述该文件的组织情况,即生成该文件系统的字的大小和字节顺序 段头部表用来描述ELF可执行文件与连续的存储段之间的映射关系。节头表包含了描述文件节区的信息,每个节区在表中都有一个项,给出节区的名称、节区大小这类心里。用于链接的目标文件(可重定向文件)必须包含节区头部表,而可执行文件可以没有。
2、一个可重定位文件保存着代码和适当的数据,用来和其他的object文件一起来创建一个可执行文件或者是一个共享文件。一个可执行文件保存着一个用来执行的程序;该文件指出了exec(BA_OS)如何来创建程序进程映象。一个共享object文件保存着代码和合适的数据,用来被下面的两个链接器链接。第一个是连接编辑器[请参看ld(SD_CMD)],可以和其他的可重定位和共享object文件来创建其他的object。第二个是动态链接器,联合一个可执行文件和其他的共享object文件来创建一个进程映象。
3、ELF头描述了该文件的组织情况,程序投标告诉系统如何创建一个进程的内存映像,section头表包含了描述文件sections的信息。当系统要执行一个文件的时候,理论上讲,他会把程序段拷贝到虚拟内存中某个段。
4、程序从0x804800开始,可执行文件加载到内存中开始执行的第一行代码,一般静态链接将会把所有代码放在同一个代码段,动态连接的进程会有多个代码段
EIF文件头包含的内容:

可执行文件的生成过程:

可执行程序的执行环境:
(1)命令行参数和shell环境,一般我们执行一个程序的Shell环境,实验中直接使用execve系统调用:
(2)Shell本身不限制命令行参数的个数,命令行参数的个数受限于命令自身
(3)Shell会调用execve将命令行参数和环境参数传递给可执行程序的main函数
(4)库函数exec*都是execve的封装例程
可执行程序的装载:
(1)do_execve()
在用户态下调用execve(),引发系统中断后,在内核态执行的相应函数是do_sys_execve(),而do_sys_execve()会调用do_execve()函数。do_execve()首先会读入可执行文件,如果可执行文件不存在,会报错。然后对可执行文件的权限进行检查。如果文件不是当前用户是可执行的,则execve()会返回-1,报permissiondenied的错误。否则继续读入运行可执行文件时所需的信息。
(2)search_binary_handler()
接着系统调用search_binary_handler(),根据可执行文件的类型,查找到相应的处理函数。系统为每种文件类型创建了一个structlinux_binfmt,并把其串在一个链表上,执行时遍历这个链表,找到相应类型的结构。然后执行相应的load_binary()函数开始加载可执行文件。
(3) load_elf_binary()
加载elf类型文件的handler是load_elf_binary(),它先读入ELF文件的头部,根据ELF文件的头部信息读入各种数据(headerinformation)。再次扫描程序段描述表,找到类型为PT_LOAD的段,将其映射(elf_map())到内存的固定地址上。如果没有动态链接器的描述段,把返回的入口地址设置成应用程序入口。完成这个功能的是start_thread(),start_thread()并不启动一个线程,而只是用来修改了pt_regs中保存的PC等寄存器的值,使其指向加载的应用程序的入口。这样当内核操作结束,返回用户态的时候,接下来执行的就是应用程序了。
(4) load_elf_interp()
如果有动态链接库的存在,那么我们还需要映射动态链接库到共享区域,还要把控制权交给动态连接器(programinterpreter,ld.soinlinux)以处理动态链接的程序。内核搜寻段表,找到标记为PT_INTERP的段中所对应的动态连接器的名称,并使用load_elf_interp()加载其映像,并把返回的入口地址设置成load_elf_interp()的返回值,即动态链接器入口。当execve退出的时候动态链接器接着运行。动态连接器检查应用程序对共享连接库的依赖性,并在需要时对其进行加载,对程序的外部引用进行重定位。然后动态连接器把控制权交给应用程序,从ELF文件头部中定义的程序进入点开始执行。
注:(1)ELF可执行文件默认映射到0x8048000这个地址,需要动态链接的可执行文件先加载连接器ld,否则直接把elf文件entry地址赋值给entry即可。start_thread(regs, elf_entry, bprm->p)会将CPU控制权交给ld来加载依赖 库并完成动态链接;对于静态链接的文件elf_entry是新程序执行的起点。
(2)execve与fork是比较特殊的系统调用,execve用它加载的可执行文件把当前的进程覆盖掉,返回之后就不是原来的程序而是新的可执行程序起点
(3)sys_execve内部会解析可执行文件格式:do_execve -> do_execve_common -> exec_binprm,earch_binary_handler符合寻找文件格式对应的解析模块
实验过程:
1、更新menu内核

2、查看test.c文件:增加了exec系统调用

3、查看Makefile

4、启动内核,

可以看到exec函数的存在。
5、启动GDB调试进行调试,先停在sys_execve处

6、使用new_ip返回到用户态的第一条指令
退出调试状态,输入redelf -h hello可以查看hello的EIF头部

总结:
多进程、多用户、虚拟存储的操作系统出现以后,可执行文件的装载过程变得非常复杂。引入了进程的虚拟地址空间;然后根据操作系统如何为程序的代码、数据、堆、栈在进程地址空间中分配,它们是如何分布的;最后以页映射的方式将程序映射进程虚拟地址空间。
动态链接是一种与静态链接程序不同的概念,即一个单一的可执行文件模块被拆分成若干个模块,在程序运行时进行链接的一种方式。然后根据实际例子do_exece()分析了ELF装载的大致过程,中间实现了动态链接。
Linux系统的运行方式与其他系统有所不同,,虽然有点难懂,但还是尽力学习,习了以后感觉很有趣,越来越有兴趣学习它了
《Linux内核与分析》第七周的更多相关文章
- Linux内核及分析 第七周 可执行程序的装载
实验步骤 1. 更新menu,用test.c覆盖test_exec.c 2. 把init 和 hello 放到了rootfs.img目录下,执行exec命令的时候自动加载了hello程序 3. 执行e ...
- 2019-2020-1 20199303 《Linux内核原理分析》 第一周作业
2019-2020-1 20199303 <Linux内核原理分析> 第一周作业 1. 环境准备 在众多的Linux发行版中,Ubuntu,小红帽还有类Unix系统的BSD系统,我选择了目 ...
- Linux内核及分析 第八周 进程的切换和系统的一般执行过程
学习笔记: 一.进程调度与进程调度的时机分析 1.不同类型的进程有不同需求的调度需求: 第一种分类: —I/O-bound:频繁的进行I/O,通常会花费很多时间等待I/O操作的完成 —CPU-boun ...
- Linux内核及分析 第六周 分析Linux内核创建一个新进程的过程
实验过程 1.github上克隆相应的mengning/menu.git 2.测试menuOS,测试fork直接执行结果 3.配置调试系统,进入gdb调试,利用file linux-3.18.6/vm ...
- Linux内核及分析 第五周 扒开系统调用的三层皮(下)
实验内容: 1.执行rm menu -rf命令,强制删除原有的menu 2.使用git命令 git clone https://github.com/mengning/menu.git 克隆新的men ...
- Linux内核及分析 第三周 Linux内核的启动过程
实验过程: 打开shell终端,执行以下命令: cd LinuxKernel/ qemu -kernel linux-3.18.6/arch/x86/boot/bzImage-initrd rootf ...
- LINUX内核分析第七周学习总结:可执行程序的装载
LINUX内核分析第七周学习总结:可执行程序的装载 韩玉琪 + 原创作品转载请注明出处 + <Linux内核分析>MOOC课程http://mooc.study.163.com/cours ...
- Linux内核分析 第七周 可执行程序的装载
张嘉琪 原创作品转载请注明出处 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 Linux内核分析 第七 ...
- LINUX内核分析第七周学习总结
LINUX内核分析第七周学习总结 标签(空格分隔): 20135328陈都 陈都 原创作品转载请注明出处 <Linux内核分析>MOOC课程 http://mooc.study.163.c ...
- Linux内核分析第七周———可执行程序的装载
Linux内核分析第七周---可执行程序的装载 李雪琦+原创作品转载请注明出处 + <Linux内核分析>MOOC课程http://mooc.study.163.com/course/US ...
随机推荐
- mysql-8.0.15允许外网访问
1.进MySQL之后, 2.输入以下语句,进入mysql库: use mysql3.更新域属性,'%'表示允许外部访问: update user set host='%' where user ='r ...
- mysql截取字段并插入到新的字段中
例如:在产品表product表中字段content值为["10"],然后在产品表中新建一个字段product_id,提出字段content的值10,如何实现呢? 解: update ...
- nginx 源码安装以及后续升级https
事情的来源是,公司要将网站从http升级到https,由于历史遗留原因,才发现现有的nginx是通过源码安装的,并没有安装ssl模块,需要现安装sll模块,这个nginx是整个公司最前端的一个代理,涉 ...
- Learning notes | Data Analysis: 1.1 data evaluation
| Data Evaluation | - Use Shift + Enter or Shift + Return to run the upper box so as to make it disp ...
- golang基础--strcut结构体
结构体struct类似python语言中的类class,结构体类的元素可以是一个变量,或者函数或者其它的类型,好比python的属性和方法. // struct结构体,类似python语言中的clas ...
- Opencv3.0-python: 编译报错color.cpp:7456: error: (-215) scn == 3 || scn == 4 的解决方案
结合Opencv3.0读取视频时,出现报错:C:\projects\opencv-python\opencv\modules\imgproc\src\color.cpp:11111: error: ( ...
- DataTable 递归 简单的程序,来实现无限级列表 结合 jquery.table.js 实现
protected void DiGuiDataTable(DataTable FromDataTable, DataTable ToDataTable, object pid) { ) { fore ...
- 20155226 2016-2017-2 《Java程序设计》第一周学习总结
20155226 2006-2007-2 <Java程序设计>第一周学习总结 教材学习内容总结 第一周主要学习了一二章的内容,也浏览了剩余章节,以下是本周主要学习内容总结 1.首先了解了[ ...
- 预备作业03:虚拟机安装及Linux操作系统练习
安装虚拟机 安装时遇到的问题 在打开虚拟机时出现以下问题: 经查询该问题只需要更改其兼容性,使其"以管理员身份运行". 常用的Linux命令 $ who am i:查看当前伪终端的 ...
- 20155235 2016-2017-1 《Java程序设计》第3周学习总结
20155235 2016-2017-1 <Java程序设计>第3周学习总结 教材学习内容总结 第四章 认识对象 类与对象 定义类 使用标准类 对象指定与相等性 基本类型打包器 打包基本类 ...