一、理论知识

Linux中,可以从c源代码生产一个可执行程序,这其中要经过预处理、编译和链接的过程。可以参考以下图来理解这个过程:

其中,目标文件中至少有编译后的机器指令代码、数据,也还包括了链接时所须要的一些信息,比如符号表、调试信息、字符串等。这Linux中,可执行文件的格式现在主要是ELF格式(对应于Windows中PE格式)。ELF的格式如下:

其详细介绍,参见:http://www.muppetlabs.com/~breadbox/software/ELF.txt,这里还有个中文版:http://www.xfocus.net/articles/200105/174.html

链接,是收集、组织程序所需的不同代码和数据的过程,以便程序能被装入内存并被执行。链接过程分为两步:1.空间与地址分配;2.符号解析与重定位。

在Linux中,一个程序的执行是做为一个新的进程,使用execve系统调用完成的。execve对应的系统调用是sys_execve,在其内部会解析可执行文件格式。对应的内核代码,就是,在search_binary_handler中寻找符合文件格式对应的解析模块,关键代码如下:

对于ELF文件,retval = fmt->load_binary(bprm)实际上执行的就是load_elf_binary,其内部就是按照ELF文件格式来加载ELF文件的。这里,我们也可以看到Linux是可以支持多种可执行文件格式的,所有的格式处里信息用一个结构体存储在一个链表中,其中的load_binary是一个函数指针,对应于该中格式的可执行文件的加载方式;要想支持一种新的可执行文件,只需要向链表中注册一个新的format结构体就可以了,此种设计类似观察者模式,具有很好的扩展性。

二、实验过程

打开实验楼中的虚拟机,在shell中依次运行以下命令,获取本次实验的代码,并编译运行

cd LinuxKernel

rm menu -rf

git clone https://github.com/mengning/menu.git

cd menu

mv test_exec.c test.c

make rootfs

效果如下:

关闭QEMU窗口,在shell窗口中,cd LinuxKernel回退到LinuxKernel目录,使用下面的命令启动内核并在CPU运行代码前停下以便调试:

qemu -kernel linux-3.18.6/arch/x86/boot/bzImage -initrd rootfs.img -s -S

接下来,我们就可以水平分割一个新的shell窗口出来,依次使用下面的命令启动gdb调试

gdb

(gdb) file linux-3.18.6/vmlinux

(gdb) target remote:1234

并在系统调用sys_execve的入口处设置断点

(gdb) b sys_execve

继续运行程序,在QEMU窗口中输入exec,系统就会停在上面设置的断点处,如图:

接下来我们可以单步跟踪sys_execve的内核代码,也可以通过设置以下断点

b load_elf_binary

b start_thread

来完整地跟踪进程的创建和启动代码!

三、总结

Linux系统可以通过execve API启动一个新进程,该API又呼叫sys_execve系统调用,负责将新的程序代码和数据替换到新的进程中,打开可执行 文件,载入依赖的库文件,申请新的内存空间,最后执行 start_thread(regs, elf_entry, bprm->p) ,设置 new_ip, new_sp ,完成新进程的代码和数据替换,然后返回,接下来就是执行新的进程代码了。

Linux内核分析7的更多相关文章

  1. linux内核分析作业8:理解进程调度时机跟踪分析进程调度与进程切换的过程

    1. 实验目的 选择一个系统调用(13号系统调用time除外),系统调用列表,使用库函数API和C代码中嵌入汇编代码两种方式使用同一个系统调用 分析汇编代码调用系统调用的工作过程,特别是参数的传递的方 ...

  2. Linux内核分析作业7:Linux内核如何装载和启动一个可执行程序

            1.可执行文件的格式 在 Linux 平台下主要有以下三种可执行文件格式: 1.a.out(assembler and link editor output 汇编器和链接编辑器的输出) ...

  3. linux内核分析作业6:分析Linux内核创建一个新进程的过程

    task_struct结构: struct task_struct {   volatile long state;进程状态  void *stack; 堆栈  pid_t pid; 进程标识符  u ...

  4. linux内核分析作业5:分析system_call中断处理过程

    1.增加 Menu 内核命令行 调试系统调用. 步骤:删除menu git clone        (tab) make rootfs 这就是我们将 fork 函数写入 Menu 系统内核后的效果, ...

  5. linux内核分析作业:以一简单C程序为例,分析汇编代码理解计算机如何工作

    一.实验 使用gcc –S –o main.s main.c -m32 命令编译成汇编代码,如下代码中的数字请自行修改以防与他人雷同 int g(int x) { return x + 3; } in ...

  6. linux内核分析作业:操作系统是如何工作的进行:完成一个简单的时间片轮转多道程序内核代码

    计算机如何工作 三个法宝:存储程序计算机.函数调用堆栈.中断机制. 堆栈 函数调用框架 传递参数 保存返回地址 提供局部变量空间 堆栈相关的寄存器 Esp 堆栈指针  (stack pointer) ...

  7. linux内核分析作业3:跟踪分析Linux内核的启动过程

    内核源码目录 1. arch:录下x86重点关注 2. init:目录下main.c中的start_kernel是启动内核的起点 3. ipc:进程间通信的目录 实验 使用实验楼的虚拟机打开shell ...

  8. linux内核分析作业4:使用库函数API和C代码中嵌入汇编代码两种方式使用同一个系统调用

    系统调用:库函数封装了系统调用,通过库函数和系统调用打交道 用户态:低级别执行状态,代码的掌控范围会受到限制. 内核态:高执行级别,代码可移植性特权指令,访问任意物理地址 为什么划分级别:如果全部特权 ...

  9. 《Linux内核分析》期末总结

    Linux内核设计期中总结 版权声明:本文为博主原创文章,未经博主允许不得转载. 前八周博客汇总及总结 Linux内核设计第一周——从汇编语言出发理解计算机工作原理 我们学习了汇编语言的基础知识,这一 ...

  10. 《Linux及安全》期中总结&《Linux内核分析》期终总结

    [5216 原创作品转载请注明出处 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000] WEEK NINE ...

随机推荐

  1. HTML基本代码教学片,认识HTML

    今儿头午有点晕晕的感觉,咳咳,甩甩头开课 HTML 定义:超文本标记语言 (记不住的可以这么记:how to make love ! 哈哈,准备开车,粗人一个,长的不行) 其实理解起来很简单,超越文本 ...

  2. LDPC译码算法代码概述

    程序说明 V0.0 2015/1/24 LDPC译码算法代码概述   概述   本文介绍了包括LDPC_Simulation.m, ldpcdecoderbp1.m,ldpcdecoderminsum ...

  3. 《零基础学JavaScript(全彩版)》学习笔记

    <零基础学JavaScript(全彩版)>学习笔记 二〇一九年二月九日星期六0时9分 前期: 刚刚学完<零基础学HTML5+CSS3(全彩版)>,准备开始学习JavaScrip ...

  4. 4星|《财经》2018年第13期:年轻人大多从大三和大四起开始就从QQ向微信转移

    <财经>2018年第13期 总第530期 旬刊 本期主要话题是快递业,其他我感兴趣的重要话题还有:香港9价HPV疫苗断供风波:华盛顿邮报被贝佐斯收购后这几年的变化:北京二中朝阳学校的划片风 ...

  5. SVN部署与简单使用

    原文发表于cu:2016-05-24 参考文档: http://www.tuicool.com/articles/Yv2iyu7 http://www.centoscn.com/CentosServe ...

  6. [转载] Centos7的安装、Docker1.12.3的安装,以及Docker Swarm集群的简单实例

    1.环境准备 ​ 本文中的案例会有四台机器,他们的Host和IP地址如下 c1 -> 10.0.0.31 c2 -> 10.0.0.32 c3 -> 10.0.0.33 c4 -&g ...

  7. Matplotlib外观和基本配置笔记

    title: matplotlib 外观和基本配置笔记 notebook: Python tags:matplotlib --- 参考资料,如何使用matplotlib绘制出数据图形,参考另一篇mat ...

  8. Python3 迭代器和生成器

    想要搞明白什么是迭代器,首先要了解几个名词:容器(container).迭代(iteration).可迭代对象(iterable).迭代器(iterator).生成器(generator). 看图是不 ...

  9. 谈谈javascript中的变量提升还有函数提升

    在很多面试题中,经常会看到关于变量提升,还有函数提升的题目,所以我就写一篇自己理解之后的随笔,方便之后的查阅和复习. 首先举个例子 foo();//undefined function foo(){ ...

  10. 20181023-4 Beta阶段第1周/共2周 Scrum立会报告+燃尽图 01

    作业要求:[https://edu.cnblogs.com/campus/nenu/2018fall/homework/2383] 版本控制:[https://git.coding.net/lglr2 ...