美丽的神话 发表于 2024-10-16 13:26:19

步伐人生-Hello’s P2P



计算机体系

大作业


题     目  步伐人生-Hello’s P2P 
专       业  计算机科学技能                     
学     号  2021111751                     
班     级  2103103                     
学       生  牛春阳                   
指 导 教 师   刘雄伟                    






计算机科学与技能学院
2022年5月
摘  要
该篇大作业为对于本学期学习计算机体系这门课程的总结。通过对hello步伐从开始到竣事在计算机中执行的过程的扼要概述,高度总结了一台计算机执行步伐的一个基本原理。本作业从概述、预处置惩罚、编译、汇编、链接以及HELLO进程管理六个角度举行分析(由于课时限制,没有对内存管理和I/O管理做出要求)通过分析hello在一台计算机中的“人生”让我们对计算机体系有了很好的相识。
在概述中扼要阐明了hello步伐的P2P,020,并且按照hello.c,hello.i,hello.s,hello.o以及可执行文件的次序对hello这个步伐举行分析和先容,每章从天生相应文件的下令行开始先容,逐层深入。结公道论知识和实际hello步伐代码,形象生动的将计算机体系展示出来。Hello的步伐先履历编译器体系得到可执行目的步伐,接着通过在shell中的运行,在存储布局中的存储,以及输入输出,让我们看到了hello的人生履历。



关键词:关键词1:预处置惩罚;关键词2:编译;关键词3:汇编;关键词4:链接;关键词5:进程                       











目  录

第1章 概述................................................................................... - 4 -
1.1 Hello简介............................................................................ - 4 -
1.2 环境与工具........................................................................... - 4 -
1.3 中间结果............................................................................... - 4 -
1.4 本章小结............................................................................... - 4 -
第2章 预处置惩罚............................................................................... - 5 -
2.1 预处置惩罚的概念与作用........................................................... - 5 -
2.2在Ubuntu下预处置惩罚的下令................................................ - 5 -
2.3 Hello的预处置惩罚结果分析.................................................... - 5 -
2.4 本章小结............................................................................... - 5 -
第3章 编译................................................................................... - 6 -
3.1 编译的概念与作用............................................................... - 6 -
3.2 在Ubuntu下编译的下令.................................................... - 6 -
3.3 Hello的编译结果分析........................................................ - 6 -
3.4 本章小结............................................................................... - 6 -
第4章 汇编................................................................................... - 7 -
4.1 汇编的概念与作用............................................................... - 7 -
4.2 在Ubuntu下汇编的下令.................................................... - 7 -
4.3 可重定位目的elf格式........................................................ - 7 -
4.4 Hello.o的结果分析............................................................. - 7 -
4.5 本章小结............................................................................... - 7 -
第5章 链接................................................................................... - 8 -
5.1 链接的概念与作用............................................................... - 8 -
5.2 在Ubuntu下链接的下令.................................................... - 8 -
5.3 可执行目的文件hello的格式........................................... - 8 -
5.4 hello的虚拟地址空间......................................................... - 8 -
5.5 链接的重定位过程分析....................................................... - 8 -
5.6 hello的执行流程................................................................. - 8 -
5.7 Hello的动态链接分析........................................................ - 8 -
5.8 本章小结............................................................................... - 9 -
第6章 hello进程管理.......................................................... - 10 -
6.1 进程的概念与作用............................................................. - 10 -
6.2 简述壳Shell-bash的作用与处置惩罚流程........................... - 10 -
6.3 Hello的fork进程创建过程............................................ - 10 -
6.4 Hello的execve过程........................................................ - 10 -
6.5 Hello的进程执行.............................................................. - 10 -
6.6 hello的非常与信号处置惩罚................................................... - 10 -
6.7本章小结.............................................................................. - 10 -
结论............................................................................................... - 14 -
附件............................................................................................... - 15 -
参考文献....................................................................................... - 16 -



第1章 概述

1.1 Hello简介

1.P2P: from program to process 从步伐到进程  
program指的就是编写出来的hello.c文件,进程就是通过编译体系(compilation system)图1得到的可执行目的步伐hello,在内核shell中通过fork函数创建的子进程,该进程中使用execve执行该步伐。
编译体系中,.c文件颠末预处置惩罚器预处置惩罚成为.i文件,.i文件颠末编译器编译得到.s文件,颠末汇编器汇编得到.o文件,最后颠末链接器链接得到hello可执行目的文件。
https://i-blog.csdnimg.cn/blog_migrate/057b94ce4a61c9f4e8d4a326807e1fe2.png
 


图1.1编译体系   
      2.020:from zero to zero 从无到有再到无

        Hello步伐从步伐员写出得到.c文件之后便诞生,jin过CS编译体系,在OS操作体系中,shell中的execve加载执行hello,为其分配虚拟内存映射到物理内存(并终极存储到磁盘中)。接着开始运行hello文件,首先在shell中输入字符串./hello,shell举行下令行分析(颠末USB,I/O桥,总线接口,寄存器文件),然后CPU通过发送信号,将hello的代码和数据从磁盘加载到主存,CPU此时执行main中的呆板语言指令,“hello world\n”履历主存,寄存器文件最后输出到屏幕上。从步伐执行完成之后,shell会对该进程执行回收操作,回收完成之后,hello的生命就可以视为竣事。
1.2 环境与工具

硬件环境X64 CPU;2GHz;2G RAM;256GHD Disk 以上

软件环境Windows7/10 64位以上;VirtualBox/Vmware 11以上;Ubuntu 16.04 LTS 64位/优麒麟 64位 以上;

开发工具Visual Studio 2010 64位以上;CodeBlocks 64位;vi/vim/gedit+gcc

1.3 中间结果

hello.c :hello步伐代码(文本文件)
hello.i :预处置惩罚产生的修改了的源步伐(文本文件)
hello.s :编译产生的汇编文件(二进制文件)
hello.o :可重定位的目的文件(二进制文件)
hello :可执行文件(二进制文件)
asm.txt :hello.o反汇编文件
1.4 本章小结

   本章先容了P2P以及020的过程,以及本实验的实验环境和中间结果。



第2章 预处置惩罚

2.1 预处置惩罚的概念与作用

预处置惩罚的概念:预处置惩罚器针对#开头的下令,对步伐员编写的原始C步伐举行添加(添加相应的代码),得到被修改了的源步伐,即后缀为.i的文件。
预处置惩罚的作用:#开头下令常用的一样寻常包括#include,这条下令告诉cpp读取include后的头文件内容并放到源步伐中;#define,这条下令告诉cpp举行相应的define后的宏常量的替换。

2.2在Ubuntu下预处置惩罚的下令

gcc -E hello.c hello.i
https://i-blog.csdnimg.cn/blog_migrate/d7a991363cb02c5963695a71fb8d0085.png
 
图2.2.1预处置惩罚下令行
https://i-blog.csdnimg.cn/blog_migrate/bfe07a258c49f0a0218bbaea646e17f1.png
 

图2.2.2执行结果
2.3 Hello的预处置惩罚结果分析

https://i-blog.csdnimg.cn/blog_migrate/7bccda673a7c0f7bde6450045ae35594.png
 图2.3.1 hello.i中printf函数
https://i-blog.csdnimg.cn/blog_migrate/026384c483691be3d2f469b3de342933.png
 
图2.3.2 hello.i中hello.c
使用gcc举行预处置惩罚得到hello.i步伐,此时已经把stdio.h头中的内容完全插入hello.c中,在头文件中我们可以看到我们在hello中用到的printf函数(在尺度库中),以及在文件末尾我们可以看到之前编写的hello代码。
2.4 本章小结

本章先容了预处置惩罚的概念和作用,并且以hello.c为例,使用gcc将hello.c转化成hello.i文件,此时hello.i文件中gcc已经对hello.c中的#后的下令举行了相应的操作,以include和define为例。

第3章 编译

3.1 编译的概念与作用

编译的概念compilation:编译器ccl将文本文件hello.i翻译成文本文件hello.s(由源步伐转化成汇编步伐),汇编步伐是用汇编语言组成的的步伐。
注意:这儿的编译是指从 .i 到 .s 即预处置惩罚后的文件到天生汇编语言步伐
编译的作用:编译而成的汇编语言步伐中,每一条汇编语言都对应一条低级语言指令,汇编语言可以为不同高级语言的不同编译器提供通用的输出语言,一样寻常环境下编译器ccl都是将C语言步伐转化成x86-64的汇编指令(CISC)

3.2 在Ubuntu下编译的下令
https://i-blog.csdnimg.cn/blog_migrate/c9872d2148f0a45b34697916feebaf5b.png
 图3.2.1 编译指令
https://i-blog.csdnimg.cn/blog_migrate/09639f4b19852bf4655e568198647b87.png
 
图3.2.3 执行结果
3.3 Hello的编译结果分析

下图中给出了数据,赋值以及类型转换的操作。
https://i-blog.csdnimg.cn/blog_migrate/7ebe8e142075846de90a0be12d8455c0.png
 
图3.3
3.3.1数据:常量、变量(全局/局部/静态)、表达式、类型、宏 
3.3.2赋值 =   ,逗号操作符,赋初值/不赋初值
  数据包括立刻数,和存储在寄存器和内存中的数据,我们使用对应的三种方式举行数据的读取。
  如图3.3所示,我们可以发现常量,全局变量以及宏是不会在函数内部完成赋值操作的 。而局部变量和局部静态变量是在函数内部赋值的。值得阐明的是,const 定义的常量在超出其作用域之后其空间会被开释,而 static 定义的静态常量在函数执行后不会开释其存储空间。同时,define定义的类型不限。另一点是const,static以及define他们三个定义的范围仅局限在该文件中,如果在其他文件中使用,必要用到关键字extern。
3.3.3类型转换(隐式或显式) unsigned/char/int/long/float/double
本文只给出了一个类型操作,在图3.3中,通过movxx操作完成类型转换。在类型转换的过程中,呆板执行的操作可以明白位先举行大小的转换,举行移位操作(分别对应有符号和无符号),再举行符号的在转换(有符号和无符号的转换)。
3.3.4sizeof
https://i-blog.csdnimg.cn/blog_migrate/113e35f56f4467cf501965e6a8526667.png
 https://i-blog.csdnimg.cn/blog_migrate/d36e1e36a1a852d88ca5ecd7909d0227.png
 
图3.3.4.1
图3.3.4.1中实现了sizeof的操作,实际上sizeof不是一个函数,并且值得注意的是,他的“返回值“是一个无符号数,一次在判定的过程中要稍加注意。
3.3.5算术操作:+ - * / %  ++  --     取正/负+-   复合“+=”等
https://i-blog.csdnimg.cn/blog_migrate/61d427a32ef549b38ddfc84a282f38f2.png
 
图3.3.5.1
正如图3.3.5.1展示了addl的加法操作,但还有很多环境下,算术运算是通过lea取地址运算来实现的。
3.3.6逻辑/位操作:逻辑&& ||  !    位 & | ~ ^    移位>>   <<    复合操作如 “|=” 或“<<=”等
https://i-blog.csdnimg.cn/blog_migrate/0171e19cc4794941fd78e540cd0cb24d.png
 https://i-blog.csdnimg.cn/blog_migrate/8b6d7edb054d95a877a26dcc10696786.png
 图3.3.6.1
https://i-blog.csdnimg.cn/blog_migrate/78a96ca8700731dac816b5e532840347.png
图3.3.6.2
图3.3.6.1中展示的移位操作并没有通过SHL等指令来完成,而是通过lea算数运算完成操作的。逻辑运算操作如图3.3.6.2部分所示。

3.3.7关系操作:==    !=      >    <      >=     <=
关系操作是重要时通过cmp指令以及对EFALG的操作完成的。
https://i-blog.csdnimg.cn/blog_migrate/feee17a5b01a7c2ecc70fbbbd493d566.png
 图 3.3.7.1
图3.3.7.1中展示了cmpl的操作,该操作将改变寄存器中的符号寄存器中的数值。
https://i-blog.csdnimg.cn/blog_migrate/2ec9bd7f1a657a8ea095fc6ccb56a272.pnghttps://i-blog.csdnimg.cn/blog_migrate/a3d37ee69122ef2ec4d58136a7510a05.png
 
图3.3.7.2显现了cmp相关指令   图3.3.7.3显现了jmpxx相关指令
关系操作重要是与jmpxx(或者setxx)操作相结合完成的,同时值得阐明的是,cmov指令是一种对cmpl和jmpxx一部分操作的简化形式,
3.3.8数组/指针/布局操作:A    &v   *p    s.id    p->id
 https://i-blog.csdnimg.cn/blog_migrate/0d2265b3d90b3333d7945e57190d2ec1.png
 https://i-blog.csdnimg.cn/blog_migrate/5b675ed2fa2db15197c25ea0ac0cc546.png
 
图3.3.8.1图3.3.8.2
数组赋初值操作,可以发现对于局部变量的数组操作是在栈中完成的。通过不断更改间隔rbp(栈基指针的间隔)来实现数组在栈中的赋初值的操作。
https://i-blog.csdnimg.cn/blog_migrate/b338f97631af9ead3713d50e86d707cc.png
 https://i-blog.csdnimg.cn/blog_migrate/a070dd72fedfe697ea64efb8d03d9694.png
 
图3.3.8.3图3.3.8.4
这里是将指针变量赋初值。首先是在内存中取相应的地址,然后将立刻数4赋给该地址。
3.3.9控制转移:if/else switch for while  do/while  ?:       continue  break
https://i-blog.csdnimg.cn/blog_migrate/a87fc685ffb48882d44f6af363cbfcad.png
 https://i-blog.csdnimg.cn/blog_migrate/fc297c9a39ef3c83eaeba3510203511b.png
 
图3.3.9.1循环以及判定的汇编语言
图3.3.9.2循环以及判定的c语言代码
我们可以看到while中首先判定了i和3的大小,但在汇编步伐中,往往会有这样的规定,将while函数转化成jumptomiddle或者guarded-do的形式,图3.3.9.3展示了这两种状态。
https://i-blog.csdnimg.cn/blog_migrate/ff1d39982fc9c45fd35530dbfdfdc32d.png
 https://i-blog.csdnimg.cn/blog_migrate/fcebd54f1a36c1c224bc0eb9440ec0c4.png
 
图3.3.9.3两种循环形式
我们发现本汇编步伐采用了jumptomiddle的形式。我们可以在汇编语言中看到,步伐先跳转到i和2比较的环境,如果i<=2那么在跳转到while内部开始的操作。否则不执行循环。在while循环中我们有采用了if的条件判定语句,如果if中是continue,则直接跳转到循环开始,如果是break,则跳转到循环竣事。
https://i-blog.csdnimg.cn/blog_migrate/298062abd6c32e1c25bd9518f666ad1c.png
 https://i-blog.csdnimg.cn/blog_migrate/aa4c6e36bdaf0bbc93ffb13dcdda6927.png
 
图3.3.9.4 switch汇编语言
图3.3.9.5 switchC语言代码
在汇编语言步伐中,switch采用了跳转表的形式,举行相应的跳转操作。
?:语句在汇编语言中为条件转移指令,它相比于条件控制指令有一定的上风,由于现代CPU都采用了流水和分支猜测的操作形式,如果分支猜测错误就会导致严重的错误处罚,但是使用条件转移指令就会克制错误penalt。但是在实际环境中不是所用的if语句都能够转换成条件转移指令的。

3.3.10函数操作:参数传递(地址/值)、函数调用()、局部变量、函数返回
https://i-blog.csdnimg.cn/blog_migrate/402427c2bbaf130123993656f8f38fc8.png
 https://i-blog.csdnimg.cn/blog_migrate/92caed4c3cb85ac2fe8d9a44127bb62c.png
 https://i-blog.csdnimg.cn/blog_migrate/46507ca1dd5ca40446b11378c7e34d81.png
 
图3.3.10.1函数中的参数传递(包括指针参数)
图3.3.10.2函数调用操作以及返回值rax的使用
图3.3.10.3步伐函数调用代码
调用函数操作中传入的是数组c和x2的地址,使用了指针布局,可以发现在汇编语言中通过将地址作为参数传递给函数来完成相应操作的。注意第一个参数和第二个参数规定是存储在rdi和ris寄存器中的,这两个寄存器和其他4个寄存器规定用来举行函数调用中的参数传递。
而rax则用来存储函数返回值,由于只有一个寄存器rax,这也解释了c语言函数中为什么只有一个返回值的环境。
局部变量只在该函数中存在,观察调用者和被调用者寄存器我们可以发现,被调用者寄存器在进入函数调用的开始就先举行存储赋值,在函数调用的末尾举行寄存器的回复,阐明局部变量的生命周期只存在于该函数之中。


3.4 本章小结

在本章中先容了编译有关内容包括定义和作用,并且偏重先容了汇编语言和c语言之间的对应关系,我们从数据到最后的函数调用,大致分析了编译器是怎样对C语言代码举行操作的。

第4章 汇编

4.1 汇编的概念与作用

  汇编的概念:汇编器as将汇编步伐.s文件转化为可重定位目的文件.o文件。
  汇编的作用:汇编器将汇编语言转化为呆板语言即将文本文件转化成二进制文件,二进制文件中的每一个01字符串都代表着一段汇编语言指令。可重定位目的文件为下一步链接做准备。
注意:这儿的汇编是指从 .s 到 .o 即编译后的文件到天生呆板语言二进制步伐的过程。
4.2 在Ubuntu下汇编的下令

https://i-blog.csdnimg.cn/blog_migrate/72225b6f6c66f7f78ffbee5bab6362fb.png
 图4.2.1 汇编下令
https://i-blog.csdnimg.cn/blog_migrate/91fe2f4975388790ab365ee779269676.png
 
图4.2.2 执行结果
4.3 可重定位目的elf格式

下图为可重定位目的文件的一样寻常格式:
https://i-blog.csdnimg.cn/blog_migrate/0bf0c266a25d30025c1648cf07637faf.png
 
图4.3
可重定位目的文件一样寻常包含一下几个节:
.text:已编译步伐的呆板代码
.rodata: 只读数据
.data: 已初始化的全局和静态C变量
.bss: 未初始化的全局和静态C变量,以及所有被初始化为0的全局或静态变量
.symtab:一个符号表,其存放在步伐中定义和引用的函数和全局变量信息
.rel.text: 一个.text节中位置的列表
.rel.data: 被模块引用或定义的所有全局变量的重定位信息
.debug:调试符号表
.line: 原始C源步伐中的行号和.text节中呆板指令之间的映射
.strlab: 一个字符串表,其中包括.symtab和.debug节中的符号表
https://i-blog.csdnimg.cn/blog_migrate/381707537c89347ff9a4739425c3f52b.png
 
图4.3.1 ELF头
ELF头:
以hello.o文件为例,开头十六字节的起始序列包括成该文件的体系的字的大小和字节次序,ELF头剩下的部分包含资助链接器语法分析息争释目的文件的信息,其中包括 ELF 头的大小、目的文件的类型、呆板类型、 字节头部表(section header table)的文件偏移,及节头部表中条目的大小和数目等。
https://i-blog.csdnimg.cn/blog_migrate/3ea7768f5592aedd9bd7fbb0482b21af.png
 图4.3.2步伐头信息
https://i-blog.csdnimg.cn/blog_migrate/dc9e05116e50fd3603dc0934f59671a1.png
图4.3.3节头部表
节头部表:不同节的位置和大小是由节头部表决定的。
https://i-blog.csdnimg.cn/blog_migrate/73186e5a8b1f68afbf607a333733507f.png
 
图4.3.4重定位表
重定位节:在汇编过程中,由于大概是多文件举行组合操作,会使用到外部数据和函数,或者该文件的数据和函数被其他文件所调用。当汇编器天生一个目的模块时,它并不知道数据和代码终极将放在内存中的什么位置。它也不知道这个模块引用的任何外部定义的函数或者全局变量的位置。以是,无论何时汇编器遇到终极位置未知的目的引用,它就会天生一个重定位条目,告诉链接器在将目的文件归并到可执行文件时怎样修改新的引用。
在重定位表中,对函数的调用使用间接寻址,对数据的调用使用直接寻址。
https://i-blog.csdnimg.cn/blog_migrate/a700f4b5b578921bfaf1176cc017e6ea.png
 
图4.3.5符号表
符号表:符号表中为步伐定义的函数以及全局变量信息,值得注意的是局部变量是存储在内存的栈中的。

 
4.4 Hello.o的结果分析

https://i-blog.csdnimg.cn/blog_migrate/c729b244ce7b0ebcb779670bc8666713.png
 图4.4.1
https://i-blog.csdnimg.cn/blog_migrate/85ba2bdb62cd7e79ea8db6eef8e91642.png
 
图4.4.2
上图是通过objdump -d -r hello.o 得到hello.o的反汇编,与 hello.s举行对照分析,我们可以发现

[*]汇编文件中操作数为十进制,反汇编为十六进制
[*]汇编文件中call和jump使用.L表示段名称,而反汇编中使用pc相对寻址。地址是有实际的数字出现的。同时我们也可以发现,反汇编中的文件前有呆板代码,每一段呆板指令都对应一条汇编语言指令。可以认为这两种指令为双射关系。
4.5 本章小结

本章先容了汇编的概念和作用。通过查阅ELF文件,观察汇编文件的特点。并比较了汇编文件和反汇编文件的异同点。

第5章 链接

5.1 链接的概念与作用

链接的概念:链接是将各种代码和数据片段网络并组合成一个单一文件的过程。
链接的作用:通过链接,被整合的文件可以加载到内存并执行。通过在编译时,加载时或者运行时的链接,将静态库或者动态库举行链接。由于尺度C有很多库函数,使用静态库可以镌汰编译器的复杂性,有利于添加删除修改某个库函数。同时也可以镌汰磁盘的存储空间,并且相对于显式的链接,使用静态库或者动态库可以镌汰堕落并且镌汰耗时。
注意:这儿的链接是指从 hello.o 到hello天生过程。
5.2 在Ubuntu下链接的下令

https://i-blog.csdnimg.cn/blog_migrate/8a612d9ef69b3d444ec29db3036308a9.png图5.2.1 ld下令
https://i-blog.csdnimg.cn/blog_migrate/8904d6f05f6ae03793120e2b2e2d6894.png
 
图5.2.2执行结果
5.3 可执行目的文件hello的格式


下图是可执行目的文件的elf的一样寻常格式,它由只读内存段,读写内存段以及其他信息构成。
https://i-blog.csdnimg.cn/blog_migrate/5a5d40d4d2ef23312e0e5d6844fd4bd0.png
 图5.3
https://i-blog.csdnimg.cn/blog_migrate/e7ee6c67d0fcb2fb41f0d0959e80ac7e.png
 
图5.3.1 ELF头
ELF头:
可执行目的文件的ELF头与可重定位目的文件的ELF的头大致雷同,不同点为可执行目的文件的ELF头还包括步伐的入口点,即步伐运行的第一条至零点地址,同时还多了一个.init节,用于初始化代码。另一不同点为文件的type发生了变化,由REL (Relocatable file)变化为EXEC (Executable file),同时由于完成了连接操作,Number of section headers的数目也变多了。
https://i-blog.csdnimg.cn/blog_migrate/8e93a7eaaf7e49a481902b072ce343d7.png
 
图5.3.2 节头部表
同可重定位目的文件节头部表一样,包含size大小,offset偏移量,address起始地址align数据对齐方式,flag等信息。节头部表可用于定位各个节所在区间,注意地址为虚拟地址的起始地址。
https://i-blog.csdnimg.cn/blog_migrate/1eafa0ef89615af68166677a0b9fd82a.png
 
图5.3.3 可重定位段信息
可执行目的文件和可重定位目的文件这里布局大致雷同。
https://i-blog.csdnimg.cn/blog_migrate/f37144c4f3fd6dff78b215c647912731.png
 
图5.3.4符号表
在链接之后,符号表添加了很多由别的函数或者库中的函数信息。
5.4 hello的虚拟地址空间

https://i-blog.csdnimg.cn/blog_migrate/454edd02035d45c3627e793c5927e5d5.png
 
图5.4.1 edb结果
正常环境下,edb调试hello得出的虚拟地址空间为上述范围,与5.3中节头部表中对照,可以找到对应关系。
  
5.5 链接的重定位过程分析

图5.4.1 edb结果
正常环境下,edb调试hello得出的虚拟地址空间为上述范围,与5.3中节头部表中对照,可以找到对应关系。
  
5.5 链接的重定位过程分析

https://i-blog.csdnimg.cn/blog_migrate/b38a70afb695c01bc2596c01362ae406.png
 
https://i-blog.csdnimg.cn/blog_migrate/5800cf8148c7fdde37de500f468cf0b7.png
 
图5.5.1 反汇编
使用指令objdump -d -r hello举行反汇编,通过对比,hello的反汇编代码比hello.o多,反汇编代码中,我们可以找到init节,这是可执行文件中特有的部分。同时在使用call指令的过程中,call的内容是一个具体的地址值。
在上述反汇编代码中我们可以看到,相比于可重定位目的文件,它已经完成了重定位的工作。
重定位:

[*]重定位节和符号定义:在这一步中,连接器将所有雷同类型的节归并成为同一类型的新的聚合节。例如,来自所有输入模块的.data节全部被归并成一个节,这个节成为输出的可执行目的文件的.data节。
[*]重定位节中的符号引用:在这一步中,连接器修改代码节和数据节中对每个符号的引用,使得他们指向精确的运行时地址。


5.6 hello的执行流程

此时使用edb执行hello步伐,下面列出了从加载hello到_start,到call main,以及步伐终止的所有过程,包括其调用与跳转的各个子步伐名或步伐地址。
<_init>:0x4e8
<.plt>:0x500
<puts@plt>:0x510
<__cxa_finalize@plt>:0x520
<_start>:0x 00530
<deregister_tm_clones>:0x560
<register_tm_clones>:0x5a0
<__do_global_dtors_aux>:0x5f0
<frame_dummy>:0x630
<main>:0x63a
<__libc_csu_init>:0x660
<__libc_csu_fini>:0x6d0
    <_fini>:0x6d4

5.7 Hello的动态链接分析

 静态库中存在更新的环境,对步伐员来时使用并不方便,同时静态库仍然会占用大量的磁盘空间,浪费内存。而动态共享库是致力于办理静态库缺陷的一个现代创新产物。共享库是一个目的模块,在运行或加载时,可以加载到恣意的内存地址,并和一个步伐链接起来,这个过程就是动态链接。
动态链接器使用过程链接表PLT和全局偏移量表GOT实现函数动态链接。GOT中存放函数目标地址,PLT使用GOT中地址跳转到目的函数。
过程链接表PLT是一个数组,其中每个条目是16字节代码。PLT 是一个特别条目,它跳转到动态链接器中。每个被可执行步伐调用的库函数都有它自己的PLT条目。每个条目都负责调用一个具体的函数。
同样,全局偏移量表GOT也是一个数组,其中每个条目是8字节地址。和PLT联合使用时,GOT 和GOT 包含动态链接器在分析函数地址时会使用的信息。GOT 是动态链接器在1d-linux.so模块中的入口点。其余的每个条目对应于一个被调用的函数,其地址必要在运行时被分析。每个条目都有一个相匹配的PLT条目。
https://i-blog.csdnimg.cn/blog_migrate/53f2b2c243ede6afc03b9d9292763191.png
 图5.7.1 -dl_init前的.got.plt内容https://i-blog.csdnimg.cn/blog_migrate/dd370ef8ba96874ddae765e79e1a3729.png
 
图5.7.2 -dl_init后的.got.plt内容
从两个图中我们可以发现,-dl前后有两个字节的内容发生改变。PLT内存储的代码跳转到GOT表明的位置,然后再调用链接器。GOT中的PLT相应指令会被链接器修改,链接之后重新调用PLT时就能跳转到精确的地方。
5.8 本章小结

本章先容了链接的概念作用和过程。使用edb展示文件的虚拟地址,并与ELF文件举行对比。同时对比汇编和反汇编的文件得到异同点,来反映重定位的作用。在edb中观察hello逐个调用的函数,包括库函数。并以hello为例,分析动态库的连接过程。


第6章 hello进程管理

6.1 进程的概念与作用

进程的概念:进程是操作体系对一个正在运行的步伐的抽象。进程的经典定义就是一个执行中步伐的实例。
进程(Process)是计算机中的步伐关于某数据聚集上的一次运行活动,是体系举行资源分配和调度的基本单位,是操作体系布局的底子。在早期面向进程设计的计算机布局中,进程是步伐的基本执行实体;在当代面向线程设计的计算机布局中,进程是线程的容器。步伐是指令、数据及其构造形式的描述,进程是步伐的实体。
进程的作用:进程的作用可以明白为进程提供给应用步伐的关键抽象
(1)一个独立的逻辑控制流,它提供一种假象,似乎我们的步伐独占地使用处置惩罚器。
(2)一个私有地址空间,它提供一种假象,似乎我们的步伐独占地使用内存体系。
6.2 简述壳Shell-bash的作用与处置惩罚流程

1.shell是体系的用户界面,提供了用户与内核举行交互操作的一种接口。它接收用户输入的下令并把它送入内核去执行
2.功能:Shell是一个下令解释器,输出提示符等待下令行然后执行此下令。它解释由用户输入的下令并且把它们送到内核。
3.处置惩罚流程:
1.读取由键盘输入的下令;
2.对下令举行分析,以下令名为文件名,并将其他参数改造为体系调用execve()参数处置惩罚所要求的格式;
3.调用fork()或者vfork()建立一个子进程;
4.子进程根据文件名(下令名)到目录中查找有关文件,将他调入内存,并创建新的文本段,并根据写时拷贝的方式创建相应的数据段、堆栈段;
5.当子进程完成处置惩罚或者出现非常后,通过exit()或_exit()函数向父进程陈诉;
6.终端进程调用wait函数来等待子进程完成,并对子进程举行回收;

6.3 Hello的fork进程创建过程

父进程通过调用fork函数创建一个新的运行的子进程。子进程得到与父进程用户级虚拟地址空间雷同的副本,包括代码和数据段,堆,共享库以及用户栈。同时子进程也可以得到父进程打开的任何文件。但值得注意到时,子进程和父进程的副本是独立的,子进程和父进程参数改变时互相不影响的。他们之间的差别是PID不同。
 
6.4 Hello的execve过程

Execve函数为  int execve(const char *filename,const char * argv[],const char * envp[])
Execve函数执行文件filename,并且带有参数列表argv以及环境列表envp。Execve函数调用一次从不返回,只用出现错的环境下才会返回。
Argv存储的时字符串数组,且字符串以null结尾,argv是可执行目的文件名字。Envp字符串同样以null结尾。
https://i-blog.csdnimg.cn/blog_migrate/a20c84b9213e4f783e22a3be170eadca.png
 
图6.4 用户占以及env和arg的分布环境。
6.5 Hello的进程执行

  首先,处置惩罚器通过使用某个控制寄存器中的模式位描述进程当前享有的特权,设置为模式位时,进程运行在内核模式中。内核模式可以访问任何指令(停止处置惩罚器,改变模式位,发起I/O操作)以及任何内存空间。
  其次,未设置模式位则处于用户模式中,用户步伐只能通过体系调用接口简介访问内核代码和数据。
  Hello步伐初始时运行在用户模式中的,通过非常(停止,非常,陷入体系调用)转变为内核模式,这是内核就可以举行上下文切换,让hello步伐与其他步伐同时实现。上下文就是内核重新启动一个被抢占了的进程所必要的状态,包括通用目的寄存器、浮点寄存器、步伐计数器、用户栈、状态寄存器、内核栈和各种内核数据布局,比如描述地址空间的页表、包含有关当前进程信息的进程表,以及包含进程已打开文件的信息的文件表。
而上下文切换时由调度器来完成的。当内核选择一个新的进程运行时,我们说内核调度了这个进程。在内核调度了一个新的进程运行后,它就抢占当前进程,并使用一种称为上下文切换的机制来将控制转移到新的进程,上下文切换包括以下几个步骤:1.保存当前进程的上下文,2.恢复某个先前被抢占的进程被保存的上下文,3.将控制传递给这个新恢复的进程。
发生上下文切换大概会由外部硬件引起的或者外部步伐所发送的信号,或者当某个进程时间片将近终止的时候。
https://i-blog.csdnimg.cn/blog_migrate/5f5c94b0ff66615fe21cf8e5360d00e7.png
 图6.5.1 进程的地址空间
https://i-blog.csdnimg.cn/blog_migrate/79f478659dd6cd118241fb6d8a0dd64d.png
 
 
图6.5.2 上下文切换的分析
6.6 hello的非常与信号处置惩罚

如下图所示,在hello步伐中加入休眠指令(sleep)以延长步伐的运行时间。在运行hello步伐中,从键盘输入Ctrl+Z指令,该条指令的寄义为挂其当前的运行的步伐,此时会输出hello的作业号为1。再输入ps,发现进程列表中有被挂起的hello步伐的名字,输入jobs得到作业号信息。最后fg加hello的作业号1让hello继承再前台执行到竣事。
https://i-blog.csdnimg.cn/blog_migrate/108b2a202c101aee061549846ec8e653.png
 
图6.6.1 Ctrl+Z ps jobs fg指令
   如下图所示,在hello运行的过程中,从键盘输入Ctrl+C的下令,该下令的寄义为给所用前台步伐组发信号终止进程,即让hello终止进程。此时输入ps,可以发现进程列表中已经没有hello步伐了。
 https://i-blog.csdnimg.cn/blog_migrate/4cabc360f2fbb73c73bab7cf7d60b1a7.png 
图6.6.2 Ctrl+C
如下图所示,在hello步伐运行时输入Ctrl+Z挂起hello步伐,再通过kill指令发送信号(注意kill指令是发送信号的指令而不是杀死进程的指令)而kill -9 中的9为SIGKILL信号,该信号是杀死步伐的信号,kill -9 5537,5537指hello的进程号,通过这条指令hello步伐也被杀死,ps列表中不会存在hello的步伐。
 https://i-blog.csdnimg.cn/blog_migrate/10beec50fd9439ebaf6f0d6a34f48fa3.png
 
图6.6.3 kill
下面展示的是hello被kill前后pstree指令的运行结果,我们会发现hello会从pstree中消失。
https://i-blog.csdnimg.cn/blog_migrate/5d78e584f3755c9d366201fe74fe0b80.png
 
图6.6.4 pstree
图6.6.5和图6.6.6分别展示了非常的几种类型,以及Linux中的信号聚集。
https://i-blog.csdnimg.cn/blog_migrate/a694e566ef72c387a74f85f2475cf7bd.png
 图6.6.5 非常状态
https://i-blog.csdnimg.cn/blog_migrate/0e3041790d6f6d803eea2b441509bb16.png
 
图6.6.6 非常信号类型
 hello执行过程中会出现哪几类非常,会产生哪些信号,又怎么处置惩罚的。
 步伐运行过程中可以按键盘,如不停乱按,包括回车,Ctrl-Z,Ctrl-C等,Ctrl-z后可以运行ps  jobs  pstree  fg  kill 等下令,请分别给出各下令及运行结截屏,阐明非常与信号的处置惩罚。
6.7本章小结

  本章重要先容了hello的执行过程。通过分析进程的概念让我们对步伐的抽象有更好的明白。接着通过分析shell的执行过程,先容了不同于用户操作的计算机内部的内核处置惩罚流程。基于shell的执行过程,具体先容了shell内部最重要的两个函数fork和execve。通过扼要叙述hello进程的执行,实际上从这个角度让我们明白了shell对于多任务执行的具体操作。在6.6节中,通过对hello步伐的非常信号发送,对内核处置惩罚信号的机制得到一定的熟悉。





结论

Hello的步伐先履历编译器体系得到可执行目的步伐,接着通过在shell中的运行,在存储布局中的存储,以及输入输出,让我们看到了hello的人生履历。
hello.c(文本文件)颠末预处置惩罚器(cpp)得到hello.i
hello.i(被修改了的源步伐,文本文件)颠末编译器(ccl)得到hello.s
hello.s(汇编步伐,文本)颠末汇编器(as)得到hello.o
hello.o(可重定位目的步伐,二进制)与其他.o文件颠末连接器(ld)得到hello,在链接过程中,hello.o的步伐会与其他步伐举行链接,或者与静态库,动态库举行链接。
hello为可执行目的步伐(二进制文件)
hello进入到执行阶段,在内核体系中,shell为该步伐调用fork函数为其分配进程,在子进程中使用execve函数执行对该步伐的操作运行。此时hello步伐往往会与其他进程并行执行在流水线中。
   在编译以及执行阶段中,hello步伐会出现在不同地址中,这让我们初步相识了计算机的存储布局。
同时输出“hello world”到屏幕上与计算机体系的I/O装备相关。
当hello所属进程竣事执行后,父进程会使用waitpid或者wait对该进程举行回收。到这里,内核会回收hello步伐有关所有信息,我们可以认为hello步伐的任务到此竣事了。


计算机体系这门课程是计算机思维导论这门课程的进一步深条理的延申。由于大学之前从未相识过计算机的原理,甚至从未打仗过代码,计算机体系这门课程对与相识计算机有很大的资助。通过CSAPP(Computer System A Programmer’s Perpective)这本教材,对计算机体系有了比较深刻的相识与熟悉。同时对本课程所开设的实验印象尤为深刻。正如计算机一样,这门课程以及这门课程的实验对自己来说都是十分抽象的,老师只对大致方向举行模糊的讲解,很少设计具体操作,更不会有在实验中遇到题目的分析。因此在写实验的过程中,往往会遇到很多的题目,同时,在网上查找资料也往往没有进一步具体的操作,因此本课程学习起来十分吃力。但是学习这门课程,充分锻炼了自己的内心,从对一个什么都不会的实验的一种极度担心和恐惧的态度,转化为一种对于未知能学会大致举行办理的能力,虽然这个题目由于种种缘故原由不能得到最完善的办理,但是至少提供了自己的一份方案或者学到了一份能够办理此题目的一个方案,因此,在内心上得到了端粒,同时对于事务的处置惩罚态度也更加成熟,从一种不成熟的,急于求成,想要放弃的一种想法转化到了轻微成熟一点的,能够有一点蒙受能力的一种心态。

附件

hello.c:源步伐文件
hello.i:hello.c预处置惩罚后的源步伐文件
hello.s:汇编步伐
hello.o:可重定位目的文件
hello:可执行目的文件
asm.txt:hello.o的反汇编代码
asm1.txt:hello的反汇编代码
pro.c:用于展示汇编语言指令的代码
prog:pro.c的可执行文件
asm2.txt:prog的反汇编代码


参考文献

  Randal E. Bryant,David R. O'Hallaron. 深入明白计算机体系. 北京:机械工业出书社,2016.7.

  林来兴. 空间控制技能. 北京:中国宇航出书社,1992:25-42.
  辛希孟. 信息技能与信息服务国际研讨会论文集:A集. 北京:中国科学出书社,1999.
  赵耀东. 新时代的工业工程师. 台北:天下文化出书社,1998 . http://www.ie.nthu.edu.tw/info/ie.newie.htm(Big5).
  谌颖. 空间交会控制理论与方法研究. 哈尔滨:哈尔滨工业大学,1992:8-13.
  KANAMORI H. Shaking Without Quaking. Science,1998,279(5359):2063-2064.
  CHRISTINE M. Plant Physiology: Plant Biology in the Genome Era. Science,1998,281:331-332. http://www.sciencemag.org/cgi/ collection/anatmorp.

 

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: 步伐人生-Hello’s P2P