预处理、编译、链接和目标文件的格式

可执行程序是怎么得来的

以C语言为例,c代码经过编译器的预处理,编译成汇编代码,由汇编器编译成目标代码,再链接成可执行文件,由操作系统加载到cpu里来执行。
(截图)

.c----.asm(.s)-----.o(二进制文件)-----A.out(可执行文件)

预处理负责把include的文件包含进来及宏替换等工作
可执行文件是使用共享库的。

静态编译
-static

把库里的东西都放在里面了所以比较大
可执行文件的内部是怎样的?

目标文件的格式ELF

(截图)
文件格式:

  • PE是windows下
  • ELF是linux下(executable linkable format)

目标文件格式和ABI应用程序二进制接口适应到某一种cpu格式

ELF标准下三种可执行文件:

    • 一个可重定位文件(代码和数据)
    • 一个可执行文件(用来执行的程序)
    • 一个共享文件(代码和数据,连接编译器和动态连接器)

      Obeject文件参与程序联接(创建一个程序)和程序执行(运行一个程序)

      (截图)

      查看ELF文件的头部

      gccs readelf -h main

      可执行程序加载的主要工作:

      映射代码中各种数据对应到进程空间的地址。例如:在文件中的代码段,拷贝到进程的空间时;数据段拷贝到进程空间。

      静态链接的ELF可执行文件和进程的地址空间

      文件映射进程地址空间
      0xc000000开始是用户态可以使用的
      0x8048000默认的加载地址
      0x8048X00程序的真实入口,可执行文件加载到内存中开始执行的第一行代码

    • 一般静态链接会将所有代码放在一个代码段

    • 动态链接的进程会有多个代码段

      可执行程序、共享库和动态链接

      装载可执行程序之前的工作

      可执行程序的的执行环境

    • 命令行参数和shell环境

      • ls -l/usr/bin列出/usr/bin下的目录信息//ls是一个可执行程序
      • shell本身不限制命令行参数的个数,命令行参数的个数受限于命令自身//也就是main函数
      • 例如,int main(int argc,char argv[]);//愿意接受命令行参数,用户输入的
        -又例如,int main(int argc,char
        argv[],charenvp[])//envp:shell的环境变量
      • shell会调用execve将命令行参数传递给可执行程序的main()函数
      • int execve(int char filename,char argv[],char *const envp[]);//函数原型,先函数调用参数传递,再系统调用参数传递

        execve的封装教程

        (截图不能用)

        命令行参数和环境变量时如何保存和传递的?

        (截图不能用)命令行参数和环境变量,fork一个子进程时完全复制父进程的,然后调用execv时,把当前的可执行程序把原来的环境(子进程)给覆盖掉,子进程的用户态堆栈也被清空了,因为新的进程要执行。

        那么命令行参数和环境变量时如何进入新程序的堆栈的?
    • 命令行参数(char argv[])、环境变量(char const envp[])压栈
    • 创建一个新的用户态堆栈,通过指针将命令行参数,环境变量传递给系统调用execve的内核处理函数
    • 内核处理函数创建一个新的可执行程序用户态堆栈的同时,将命令行参数和环境变量拷贝进去
      shell程序--execve--对应的系统调用sys_execv--然后在初始化时拷贝

      装载时动态链接和运行时动态链接的应用举例

    • 可执行程序装载时动态链接
    • 可执行程序运行时动态链接
      #### 可执行装载时、运行动态链接
      1. 准备.so文件
        共享库文件shlibexample.h和shlibexample.c编译成.so文件
        (共享库的代码展示图)

      gcc -shared shlibexample.c -o libshlibexample.so -m32

      1. 分别以共享库和动态加载共享库的方式使用libshlibexample.so文件和libdllibexample.so文件
        (展示main函数)
        编译main注意这里只提供shlibexample的-L(库对应接口文件所在目录)和-l(库名)并没有提供dllibexample的信息
    • gcc mian.c -o main -l/path/to/your/dir -lshlibexample -ldl -m32
      //分别指定头文件的路径和库文件的路径,动态加载

    • export LD_LIBRARY_PATH=$PWD

      //将当前目录加入默认路径

    • ./main

Linux内核第七节 20135332武西垚的更多相关文章

  1. Linux内核第四节 20135332武西垚

    实验目的: 使用库函数API和C代码中嵌入汇编代码两种方式使用同一个系统调用 实验过程: 查看系统调用列表 get pid 函数 #include <stdio.h> #include & ...

  2. Linux内核第五节 20135332武西垚

    20135332武西垚 在MenuOS中通过添加代码增加自定义的系统调用命令 使用gdb跟踪调试内核 简单分析system_call代码了解系统调用在内核代码中的处理过程 由于本周实验是在Kali虚拟 ...

  3. Linux内核第六节 20135332武西垚

    如何描述一个进程:进程描述符的数据结构: 如何创建一个进程:内核是如何执行的,以及新创建的进程从哪里开始执行: 使用gdb跟踪新进程的创建过程. 进程的描述 操作系统三大功能: 进程管理(最核心最基础 ...

  4. Linux内核总结博客 20135332武西垚

    http://www.cnblogs.com/wuxiyao/p/5220677.htmlhttp://www.cnblogs.com/wuxiyao/p/5247571.htmlhttp://www ...

  5. Linux内核第三节 20135332武西垚

    总结部分: Linux内核源代码: Arch 支持不同cpu的源代码:主要关注x86 Init   内核启动的相关代码:主要关注main.c,整个Linux内核启动代码start_kernel函数 K ...

  6. Linux内核第八节 20135332武西垚

    第一种分类: I/O-bound:频繁进行I/O,并且需要花费很多时间等待I/O完成 CPU-bound:计算密集,需要大量的CPU时间进行运算 第二种分类: 批处理进程:不必与用户交互,常在后台进行 ...

  7. (笔记)Linux内核学习(七)之内核同步机制和实现方式

    一 原子操作 指令以原子的方式执行——执行过程不被打断. 1 原子整数操作 原子操作函数接收的操作数类型——atomic_t //定义 atomic_t v;//初始化 atomic_t u = AT ...

  8. Linux内核第二节

    作者:武西垚 深入理解函数调用堆栈 堆栈是C语言程序运行时必须的一个记录调用路径和参数的空间 堆栈的作用 函数调用框架 传递参数 保存返回地址 提供局部变量空间 堆栈相关的寄存器 esp,堆栈指针,指 ...

  9. Linux内核分析(一)---linux体系简介|内核源码简介|内核配置编译安装

    原文:Linux内核分析(一)---linux体系简介|内核源码简介|内核配置编译安装 Linux内核分析(一) 从本篇博文开始我将对linux内核进行学习和分析,整个过程必将十分艰辛,但我会坚持到底 ...

随机推荐

  1. javascript闭包—围观大神如何解释闭包

    闭包的概念已经出来很长时间了,网上资源一大把,本着拿来主意的方法来看看. 这一篇文章 学习Javascript闭包(Closure) 是大神阮一峰的博文,作者循序渐进,讲的很透彻.下面一一剖析. 1. ...

  2. Reveal安装

    一.安装 第一步:将Reveal.framework拖入工程中(下载地址:http://pan.baidu.com/s/1mgMJVDI,解压后产生的Reveal.framework,拖入工程即可). ...

  3. .whl文件打开方式 Python

    wheel文件本质上就是zip或者rar,只不过他更加方便python的安装以及使用.在之前的图片中我们只要使用pip install wheel 就可以安装wheel. 在安装了wheel之后我们可 ...

  4. Java 堆内存 新生代 (转)

    Java 中的堆是 JVM 所管理的最大的一块内存空间,主要用于存放各种类的实例对象.在 Java 中,堆被划分成两个不同的区域:新生代 ( Young ).老年代 ( Old ).新生代 ( You ...

  5. Looper loop

    public static void loop() { final Looper me = myLooper(); if (me == null) { throw new RuntimeExcepti ...

  6. 【洛谷】【模拟+栈】P4711 「化学」相对分子质量

    [题目传送门:] [戳] (https://www.luogu.org/problemnew/show/P4711) [算法分析:] 关于一个分子拆分后的产物,一共有三种情况: 原子 原子团 水合物 ...

  7. python3 day03 大纲

    一. 上次课内容回顾 1. 格式化输出 %d 占位数字 %s 占位字符串 %f 占位小数 "jfklasjkfj%s %d %f" % (值1, 值2, 值3) "{}爱 ...

  8. kubectl常用命令

    command kubectl kubectl 输出格式 显示Pod的更多信息 kubectl get pod <pod-name> -o wide 以yaml格式显示Pod的详细信息 k ...

  9. <数据结构与算法分析>读书笔记--运行时间中的对数及其分析结果的准确性

    分析算法最混乱的方面大概集中在对数上面.我们已经看到,某些分治算法将以O(N log N)时间运行.此外,对数最常出现的规律可概括为下列一般法则: 如果一个算法用常数时间(O(1))将问题的大小削减为 ...

  10. 【Codeforces 1105E】Helping Hiasat

    Codeforces 1105 E 题意:给你m个事件,每个事件可能是以下两种之一: \(1\),代表此时可以更改用户名 \(2\) \(s\),代表\(s\)来查看是否用户名与其名字相符 一共有\( ...