zoukankan      html  css  js  c++  java
  • 2019-2020-1 20199325《Linux内核原理与分析》第八周作业

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

    1.理解编译链接的过程和ELF可执行文件格式,详细内容参考本周第一节;​
    2.编程使用exec*库函数加载一个可执行文件,动态链接分为可执行程序装载时动态链接和运行时动态链接,编程练习动态链接库的这两种使用方式,详细内容参考本周第二节;
    3.使用gdb跟踪分析一个execve系统调用内核处理函数sys_execve ,验证您对Linux系统加载可执行程序所需处理过程的理解,详细内容参考本周第三节;推荐在实验楼Linux虚拟机环境下完成实验。
    4.特别关注新的可执行程序是从哪里开始执行的?为什么execve系统调用返回后新的可执行程序能顺利执行?对于静态链接的可执行程序和动态链接的可执行程序execve系统调用返回时会有什么不同


    一、理解编译链接的过程和ELF可执行文件格式:

    1.预处理、编译、链接:

    <1>预处理,处理代码中的宏定义和 include 文件,并做语法检查

    gcc -E hello_world.c -o hello_world.i
    

    <2>编译,生成汇编代码

    gcc -S hello_world.i -o hello_world.s
    

    <3>汇编,生成 ELF 格式的目标代码

    gcc -c hello_world.s -o hello_world.o
    

    <4>链接,生成可执行代码

    gcc hello_world.o -o hello_world
    

    <5>执行程序

    ./hello_world hello, world!
    

    2.ELF文件格式:

    ELF 格式:可执行和可链接(Executable and Linkable Format) 是一种用于二进制文件、可执行文件、目标代码、共享库和核心转储的标准文件格式。

    可重定位文件,如:.o 文件,包含代码和数据,可以被链接成可执行文件或共享目标文件,静态链接库属于这类。
    可执行文件,如:/bin/bash 文件,包含可直接执行的程序,没有扩展名。
    共享目标文件,如:.so 文件,包含代码和数据,可以跟其他可重定位文件和共享目标文件链接产生新的目标文件,也可以跟可执行文件结合作为进程映像的一部分。

    ELF 文件由 ELF header 和文件数据组成,文件数据包括:

    Program header table, 程序头:描述段信息
    .text, 代码段:保存编译后得到的指令数据
    .data, 数据段:保存已经初始化的全局静态变量和局部静态变量
    Section header table, 节头表:链接与重定位需要的数据

    二、编程使用exec*库函数加载一个可执行文件,动态链接分为可执行程序装载时动态链接和运行时动态链接,编程练习动态链接库的这两种使用方式:

    链接,是收集和组织程序所需的不同代码和数据的过程,以便程序能被装入内存并被执行。一般分为两步:1.空间与地址分配,2.符号解析与重定位。一般有两种类型,一是静态链接,二是动态链接。
    使用静态链接的好处是,依赖的动态链接库较少(这句话有点绕),对动态链接库的版本更新不会很敏感,具有较好的兼容性;不好地方主要是生成的程序比较大,占用资源多。使用动态链接的好处是生成的程序小,占用资源少。动态链接分为可执行程序装载时动态链接和运行时动态链接。
    当用户启动一个应用程序时,它们就会调用一个可执行和链接格式映像。Linux 中 ELF 支持两种类型的库:静态库包含在编译时静态绑定到一个程序的函数。动态库则是在加载应用程序时被加载的,而且它与应用程序是在运行时绑定的。


    首先更新linux/kernel下的menu,并将test_exec变成test.c

    进入内核,查看exec命令是否添加进入内核

    退出内核,新建terminal进行gdb调试查看

    gdb中与内核建立联系

    file linux-3.18.6/vmlinux
    target remote:1234
    

    内核中对sys_execve,load_elf_binary,start_thread进行断点调试,c执行,list列出代码,并进行单步调试。

    内核运行


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

    1.我们通过跟踪以及查看分析代码,执行的流程是:(代码见上面) sys_execve -> do_execve -> do_execve_common -> exec_binprm -> search_binary_handler -> load_binary ->(对于我们这里的ELF,会跳转到)load_elf_binary(也执行了elf_format)-> start_thread
    2.我们调用execve的可执行程序时,当执行到exceve时,系统调用exceve陷入内核,这时会创建一个新的用户态堆栈,实际是把命令行参数的内容和环境变量的内容通过指 针的方式传递给系统调用内核处理函数的,然后内核处理函数在创建可执行程序新的用户态堆栈的时候,会把这些拷贝到用户态堆栈初始化新的可执行程序的执行上下文环 境(先函数调用参数传递,再系统调用参数传递)。这时就加载了新的可执行程序。系统调用exceve返回用户态的时候,就变成了被exceve加载的可执行程序。

  • 相关阅读:
    bzoj3721
    [BZOJ3555] [Ctsc2014]企鹅QQ(Hash)
    [POJ3233] Matrix Power Series(矩阵快速幂)
    矩阵运算所满足的定律
    [luoguP1962] 斐波那契数列(矩阵快速幂)
    [luoguP3390]【模板】矩阵快速幂
    【转】关于LIS和一类可以用树状数组优化的DP 预备知识
    [BZOJ1264][AHOI2006]基因匹配Match(DP + 树状数组)
    [luoguP1439] 排列LCS问题(DP + 树状数组)
    蛤蛤蛤(树状数组 | 二分)
  • 原文地址:https://www.cnblogs.com/buhery/p/11819225.html
Copyright © 2011-2022 走看看