一 程序的装载和运行的基本知识补充

   1 当进程开始执行一个新的程序时,从父进程继承的所有页被释放,以便在新的用户地址空间开始执行新的计算,甚至进程的特权都可能发生改变,但是,进程的PID不会改变。

2 进程的信任状和权能

进程的信任状决定一个进程的权限,也就是能做什么,不能做什么。这对多用户系统,系统的稳定性很重要。

进程被创建时,总是继承父进程的信任状。

权能是引入进程信任状的另一种模式。他表示是否允许进程执行一个特定的操作或一组特定的操作。

3 目标文件不能被执行,因为它不含源代码文件所用的全局外部符号名的线性地址,这些地址的分配是由链接程序完成的。链接程序还分析程序所用的库函数。

4 静态链接生成的可执行文件不仅包含原程序的代码,还包含程序所引用的库函数的代码。缺点是占用大量的磁盘空间。

动态链接程序把一个共享库链接到进程时,不拷贝目标代码,仅执行一个内存映射,把库文件的相关部分映射到进程的地址空间中,缺点是程序的启动时间较长。

二 跟踪分析执行程序的系统调用execve()

2.1在以前的代码基础上添加

    

main()添加:

利用qemu查看调试结果(相关的基本设置可以参考前面博客)

设置断点:

执行,停在第一个断点处:

继续执行,停在do_open_exec:

继续执行:

输入exec:

发现程序停在:

执行:

接着执行:

分析:新的可执行程序是从哪里开始执行的?

我们知道只有pc能代表程序的执行流, 父进程fork创造椅子进程,子进程执行新的可执行程序,当子进程“获得”pc时,才是子进程(可执行程序)开始执行的地方。通过GDB跟踪以及阅读源码,

void start_thread(struct pt_regs *regs, unsigned long new_pc,
unsigned long new_sp)
{
regs->pr = 0;
regs->sr = SR_FD;
regs->pc = new_pc;
regs->regs[15] = new_sp; free_thread_xstate(current);
}

  可以看到在函数load_elf_binary()的最后调用了函数start_thread(regself_entrybprm->p),所以elf_entry是可执行程序开始执行的地方。

为什么execve系统调用返回后新的可执行程序能顺利执行?

因为在系统调用过程中,父进程的大部分资源被抛弃,堆栈被清空,新的可执行程序根据传递的参数和环境变量配置了一个新的堆栈。所以返回时能够正常执行。

对于静态链接的可执行程序和动态链接的可执行程序execve系统调用返回时会有什么不同?

在函数load_elf_binary中可以看到如下的一段代码:

887	if (elf_interpreter) {
888 unsigned long interp_map_addr = 0;
889
890 elf_entry = load_elf_interp(&loc->interp_elf_ex,
891 interpreter,
892 &interp_map_addr,
893 load_bias);
894 if (!IS_ERR((void *)elf_entry)) {
895 /*
896 * load_elf_interp() returns relocation
897 * adjustment
898 */
899 interp_load_addr = elf_entry;
900 elf_entry += loc->interp_elf_ex.e_entry;
901 }
902 if (BAD_ADDR(elf_entry)) {
903 retval = IS_ERR((void *)elf_entry) ?
904 (int)elf_entry : -EINVAL;
905 goto out_free_dentry;
906 }
907 reloc_func_desc = interp_load_addr;
908
909 allow_write_access(interpreter);
910 fput(interpreter);
911 kfree(elf_interpreter);
912 } else {
913 elf_entry = loc->elf_ex.e_entry;
914 if (BAD_ADDR(elf_entry)) {
915 retval = -EINVAL;
916 goto out_free_dentry;
917 }

 我们知道 elf_entry是系统调用返回时可执行文件开始执行的地方,由以上代码,通过静态链接返回时,elf_entry代表的是可执行文件规定的头部,而动态链接,elf_entry代表的是动态链接器的起点。

三 总结

自己对“Linux内核装载和启动一个可执行程序”的理解

通过以上的学习,我们知道装载和启动一个可执行程序主要是通过系统调用execve()来实现的,和普通的系统调用不同,execve系统调用返回时不是INT $0x80语句的后面一条语句,而是变成了一个新的进程,按照用户要求(参数和环境变量)创建的可执行程序。

通过一系列函数调用:do_execve()->do_execve_common()->exec_binprm()->search_binary_handler()->list_for_each_entry()->load_binary()->load_elf_binary()->start_thread(),

start_thread(regself_entrybprm->p)中修改了ip,elf_entry是可执行程序开始执行的地方。

by:方龙伟

原创作品 转载请注明出处

《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000

linux内核学习之七 可执行程序的装载和运行的更多相关文章

  1. Linux内核分析之可执行程序的装载和启动

    一.内容分析 1.可执行文件的创建 (1)预处理阶段 预处理过程读入源代码,检查包含预处理指令的语句和宏定义,并对源代码进行相应的转换,预处理过程还会删除程序中的注释和多余的空白字符.其中预处理指令主 ...

  2. Linux第七周学习总结——可执行程序的装载

    Linux第七周学习总结--可执行程序的装载 作者:刘浩晨 [原创作品转载请注明出处] <Linux内核分析>MOOC课程http://mooc.study.163.com/course/ ...

  3. Linux内核分析——Linux内核学习总结

    马悦+原创作品转载请注明出处+<Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 Linux内核学习总结 一 ...

  4. Linux内核学习期末总结(网课)

    标签(空格分隔): 20135321余佳源 余佳源(原创作品转载请注明出处) <Linux内核分析> MOOC课程http://mooc.study.163.com/course/USTC ...

  5. 关于Linux内核学习的一点点总结

    关于Linux内核学习的一点点总结 关键词:Linux, 操作系统,内核 博客列表 由反汇编C程序来理解计算机是如何工作的 通过分析一个简化版时间片轮转多道程序内核代码来认识操作系统中的进程调度 通过 ...

  6. linux内核学习之二:编译内核

    在linux内核学习系列的第一课中讲述了搭建学习环境的过程(http://www.cnblogs.com/xiongyuanxiong/p/3523306.html),环境搭好后,马上就进入到下一环节 ...

  7. Linux内核学习笔记-1.简介和入门

    原创文章,转载请注明:Linux内核学习笔记-1.简介和入门 By Lucio.Yang 部分内容来自:Linux Kernel Development(Third Edition),Robert L ...

  8. 20135316王剑桥Linux内核学习笔记

    王剑桥Linux内核学习笔记 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 计算机是如何工作的 个人理 ...

  9. Linux 内核学习的经典书籍及途径

    from:http://www.zhihu.com/question/19606660 知乎 Linux 内核学习的经典书籍及途径?修改 修改 写补充说明 举报   添加评论 分享 • 邀请回答   ...

随机推荐

  1. UAT SIT QAS DEV PET

    UAT: User Acceptance Testing 用户验收测试SIT: System Integration Testing 系统集成测试PET: Performance Evaluation ...

  2. Rails中的缓存

    最近学习Rails. 看到如下代码: <% if notice %> <p id="notice"><%= notice %></p> ...

  3. left和offsetLeft

    left: 1.当该对象的定位position为absolute时left是相对于拥有定位属性(position的值为默认值"static"时除外)的父级对象的左边距. 例1:当父 ...

  4. Log4net(1):配置的简单说明

    基础代码下载地址:https://github.com/zhangsai521314/StudyLog4net 1:按日期分隔日志 <configSections> <section ...

  5. [转] - 在mac的终端中使用sublime打开文件

    在mac的终端中使用sublime打开文件 使用sublime提供的命令行工具.这个命令行工具位于 /Applications/Sublime\ Text\ 2.app/Contents/Shared ...

  6. 慕课网__css_ float

  7. 01.总结的javascript-DOM/BOM集合

    javascript总结: javascript 主要包括三个部分:1.DOM; 2.BOM; 3.ECMAscript 一.DOM(对象文档模型) 1.几个重要概念: 1)dom节点:元素,属性,文 ...

  8. 打开hibernate文件报警告

    在web工程中新建一个,Hibetnate项目,打开配置文件报警高错误,This project is not a MyEclipse Hiberbate Project. Assuming Hibe ...

  9. 图表,列表在同一DIV里切换显示()

    JS: function changeTable(){ $(".countTable").slideDown(); $(".countChart").css(& ...

  10. caffe中关于数据进行预处理的方式

    caffe的数据层layer中再载入数据时,会先要对数据进行预处理.一般处理的方式有两种: 1. 使用均值处理 transform_param { mirror: true crop_size: me ...