2023spr HIT计统大作业——程序人生-Hello’s P2P

题     目  程序人生-Hello’s P2P 

专       业         计算学部              

学     号  7203610817           

班     级     2036013                  

学       生          修亚鹏           

指 导 教 师             刘宏伟          

计算机科学与技术学院

2023年5月

摘  要

本文讲述了hellow程序的“人生”,展示了它经历的P2P(是from program to process的缩写),经过编辑操作得到了hello程序,之后再经过预处理汇编等等生成可执行文件hello,以linux操作系统为例,在linux终端中使用./hello指令执行此文件,然后shell会解析这段命令,再使用fork创建子进程,并且通过一些其他等函数进行操作这个进程,最终完成program to process的“一生”。

目  录

第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 -

第7章 hello的存储管理................................................................................... - 11 -

7.1 hello的存储器地址空间................................................................................ - 11 -

7.2 Intel逻辑地址到线性地址的变换-段式管理............................................... - 11 -

7.3 Hello的线性地址到物理地址的变换-页式管理.......................................... - 11 -

7.4 TLB与四级页表支持下的VA到PA的变换................................................ - 11 -

7.5 三级Cache支持下的物理内存访问............................................................. - 11 -

7.6 hello进程fork时的内存映射..................................................................... - 11 -

7.7 hello进程execve时的内存映射................................................................. - 11 -

7.8 缺页故障与缺页中断处理.............................................................................. - 11 -

7.9动态存储分配管理........................................................................................... - 11 -

7.10本章小结........................................................................................................ - 12 -

第8章 hello的IO管理.................................................................................... - 13 -

8.1 Linux的IO设备管理方法............................................................................. - 13 -

8.2 简述Unix IO接口及其函数.......................................................................... - 13 -

8.3 printf的实现分析........................................................................................... - 13 -

8.4 getchar的实现分析....................................................................................... - 13 -

8.5本章小结.......................................................................................................... - 13 -

结论............................................................................................................................ - 14 -

附件............................................................................................................................ - 15 -

参考文献.................................................................................................................... - 16 -

第1章 概述

1.1 Hello简介

①:P2P是from program to process的缩写,经过编辑操作得到了hello程序,之后再经过预处理汇编等等生成可执行文件hello,以linux操作系统为例,在linux终端中使用./hello指令执行此文件,然后shell会解析这段命令,再使用fork创建子进程,并且通过一些其他等函数进行操作这个进程,最终完成program to process的“一生”。

②:020是From Zero-0 to Zero-0的简写shell通过erxcve在子进程中加载hellow,为hellow船舰新的区域结构,产出自己的内存地址,时间周期等。在进程结束后释放内存,删除上下文,这样hellow的进程在机器中就像不曾出现过一般,也就是从没有到没有(020

1.2 环境与工具

列出你为编写本论文,折腾Hello的整个过程中,使用的软硬件环境,以及开发与调试工具。

硬件环境:x86 cpu ,2.5Ghz,8G ram

软件环境:Windows 10 64位 ,Vmware 14 ,Ubuntu 16.04 LTS 64 

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

1.3 中间结果

列出你为编写本论文,生成的中间结果文件的名字,文件的作用等。

Hello.c   源代码

Hellow.i   hellow.c 的预处理得到的一个ASCII汇编语言文件

hello.s   hellow.i 编译生成的汇编文件

hello.o   汇编器生成的二进制文件

Hello       Hello.s与标准c库链接产生的可执行目标文件

Hello-o-objdump.txt      Hello.o的反汇编文件

Hello-o-elf.txt         Hello.o的ELF文件

Hello-objdump.txt         Hello的反汇编文件

Hello-elf.txt         Hello的ELF文件

1.4 本章小结

本章分析了hellow的psp以及020的特点,比那个且介绍了本次实验使用的环境与工具,同时列出了中间文件以及其作用

第2章 预处理

2.1 预处理的概念与作用

①预处理的概念:预处理器根据以字符#开头的命令,修改原始的C程序,比如hello.c中的第一行的#include <stdio.h>命令就会告诉预处理器读取系统头文件stdio.h的内容,并将其插入到程序文本中,最后将.c的文件进行初步处理成一个.i文件

②作用:

<1>删除所有注释

<2>对某段代码进行限制与加条件

>3<添加信息文件名信息,方便调试

>4<预处理#include。预处理器会读取头文件中用到的库的C程序段,将这段代码直接插入到程序文件中。
 

2.2在Ubuntu下预处理的命令

gcc -E -o hello.i hello.c
预处理过程及结果:

2.3 Hello的预处理结果解析

编译后的hello.c文件生成了hello.i文件,而该文件的大小却变成了近100倍。打开hello.i,hello.c中的主函数没有变化,而宏定义#没有了,取而代之的是其对应的文件,占据了hello.i中的大部分空间。同时说明,预处理只是资源的等效替换,在这种情况下是替换头文件,而没有对函数的主体进行修改。

2.4 本章小结

本章解释了程序的预处理过程,介绍了ubuntu中预处理c的方法,并查看了预处理后的.i文件,加深了对预处理的理解,了解了预处理的内涵。

第3章 编译

3.1 编译的概念与作用

编译器是一个程序,在通过词法分析和语法分析确认所有指令符合语法规则后,将它翻译成等效的中间代码表示或汇编代码。编译器将文本文件hello.i翻译成hello.s。

功能:通过语法分析,检查是否符合语法标准,如果不符合,将会报错。将hello.i翻译成hello.s,可以在编译时优化程序性能,在提高编译器程序性能和运行效率的前提下,很好地实现其原始机器语言功能。从高级语言转换为汇编语言,从而使语言更容易被机器理解。

       

3.2 在Ubuntu下编译的命令

gcc -S hello.i -o hello.s

3.3 Hello的编译结果解析

3.3.1整体指令

其中  .file为源文件名

.text 存放程序执行代码的指定内存区域

.section指示将代码分成若干段

.rodata用于维护只读数据,如常数字符串、const-modified全局变量等等。

.align 8个地址对齐的伪指令,用于指定符号的对齐方式

.string 字符串的存储位置

.type 指定它是一个对象类型还是一个函数类型

3.3.2 常量以及赋值

3.3.3局部变量与其赋值

局部变量会存储在编辑器或一个栈中

例如 int的汇编语言是

这就说明局部变量被存储在内存中

3.3.4  数组,指针,结构的操作

例如指针数组

由main的知道其对应的汇编代码为

我们可以看到,数组的第一个地址argv[0]存在于-32(%rbp),这也是%rsi的内容。同时我们也可以知道argc存在于-20(%rbp)处

3.3.5算数操作

Add操作为 addl $1,-4(%rbp)

3.3.6控制转移

if和for均使用了控制转移指令

设为cmp比较,加上jmp条件跳转

例如,这段代码用来判断条件。

if(argc!=4) 

在汇编语言中

cmpl 4, -20(%rbp) 

    je .L2 

也就是说,它判断一个数字是否等于4,如果是,它就跳到.L2,否则就不跳。类似地,循环中的最后条件判断类似于

cmpl $7, -4(%rbp) 

    jle .L4

判断一个数字是否小于或等于7,如果是,则跳转,否则不跳转。

3.3.7函数的操作

函数操作是在调用前按rdi、rsi、rdx、rcx、r8、r9的顺序向各寄存器传递参数,其余的参数放在堆栈中,然后用调用方式访问函数,之后将返回值存放在rax中,最后返回返回位置。

下面一main函数举例:

.c中

汇编语言却变成了

从这里可以看出输入的参数被放置在了rdi以及rsi中

第五行可以看出返回值o被放在了eax中,就相当于return o

3.3.8数据类型的转换

这里的atoi函数将参数str所指向的字符串转换为一个整数(int类型),这是一个典型的显式转换。其中再汇编语言中表示为atoi函数:

例如上码第四行,将参数输进rdi进而进行转化

3.4 本章小结

本章主要介绍编译的概念以及作用,如何在Ubuntu系统上进行编译操作,以及对hello的编译结果进行解析。通过词法和句法分析,让我们深入了解编译器如何将文本文件hello.i翻译成文本文件hello.s,并在确认语法规则的确认指令是否符合后,再把它翻译成等价的中间代码或汇编代码来进行表示,即深入了解编译器如何将文本文件hello.i翻译成文本文件hello.s。

第4章 汇编

4.1 汇编的概念与作用

概念:将hello.s转换为hello.o的过程,也就是将汇编代码转换为机器代码的过程,称为汇编过程。

作用:汇编代码是人类比较容易理解的代码,但是机器仍难以理解汇编代码。计算机仅仅能理解{0,1}*的语言。汇编的作用是将.s文件翻译成机器能容易读取的二进制代码,这样就可以执行我们输入的程序。

4.2 在Ubuntu下汇编的命令

Linux中输入gcc -c hello.s -o hello.o

得到了二进制o文件如下

4.3 可重定位目标elf格式

输入指令readelf -a hello.o > ./elf.txt

‘产生elf.txt文件

>1<ELF头

生成的elf头如下代码所示

Elf头包括了数据.操作系统的类别等等

>2<节头部表

如下图

上图便是了.o文件中的各个节的类型和所占据的空间的大小等信息

>3<重定位节

偏移量:通常对应于.text或.data部分的偏移量,其中一些程序代码需要被重定向。

信息:要重定位的目标在符号表中的偏移量

类型:代表重定位的类型,与信息相对应。

名称:被重定向的目标的名称

加数:作为辅助操作,用于计算重复或位置文件的位置信息,共约8个字节。

>4<例表

Symbol table被使用在存放程序中定义以及引用函数全局变量的全部信息。

4.4 Hello.o的结果解析

用指令objdump -d -r hello.o > hello.objdump生成反汇编的文本文件hello.objdump。

将其与hello.s文本进行比较,可以注意到一些差异。

①在.s文件中有很多伪代码,但在反汇编代码中没有。

②反汇编代码对常量使用十六进制,而hello.s文件使用十进制操作数。

③对于跳转,反汇编代码使用相对偏移位置,而hello.s文件使用L1等跳转表式地址或者是直接是call + 函数名称

4.5 本章小结

本章解释了汇编的概念和作用,说明了在ubuntu操作系统下如何使用汇编操作将hello.s转换为hello.o,之后我们通过查看反汇编代码来比较与.o文件的差异,使得我们的程序就更容易被机器读懂。

第5章 链接

5.1 链接的概念与作用

概念。正确地衔接模块中相互引用的部分。其工作是纠正一些指令对其他符号地址的引用。衔接过程主要包含地址和空间分配、符号解析和重定向

作用:是所有需要的组件都集成在一个可执行文件中

5.2 在Ubuntu下链接的命令

生成hello文件如下图

5.3 可执行目标文件hello的格式

输入指令:readelf -a hello > hello1.elf

生成的hello1.efl文件

>1<elf头如下

Elf头包含了机器,数据,操作系统的类别,以及系统架构等信息

>2<节头

该表描述了.文件中各个节的位置所占空间大小等消息

5.4 hello的虚拟地址空间

  使用edb加载hello,查看进程中的虚拟地址空间的各个信息,再对照5.3

如上图所示,在edb中加载hello虚拟地址信息

看看ELF格式文件中的程序头文件,它告诉链接器在运行时要加载什么,并提供有关动态链接的信息。每个表项都提供了虚拟地址空间和物理地址空间中各段的各方面信息。

比较5.4.3中的elf文件结构:elf表头+段头,等等。数据转储也可以被查看,包含的部分有PHDR, INTERP, LOAD , DYNAMIC, NOTE , GNU_STACK, GNU_RELRO等。 

5.5 链接的重定位过程分析

5.5.1hello与hello.0反汇编代码的比较

在hello.0的反汇编比较中可以发现一下事情

①在可执行文件中,有许多额外的函数是程序执行所必需的,例如sleep、getchar等等。

②地址编码的方法是不同的。可执行文件使用虚拟地址,而.o使用相对地址。

③与hello.o相比,可执行文件有更多的部分,如.init和.fini。

5.5.2链接重定位的过程分析

主要分为以下两步

①重新定位节和符号定义

链接器将所有相同类型的部分合并成一个新的部分。然后,链接器将内存地址分配给新的部分,以及每个符号。

②重定位章节中的符号引用

链接器依靠.o中的重定位条目来修改代码部分和数据部分对每个

符号,以便它们只需要正确的内存地址。

5.6 hello的执行流程

下面列出各个子程序名:

_dl_start

_dl_init

_start

__licbc_start_main

__cxa_atexit

__libc_csu_init

_init

_setjmp

_sisgsetjmp

__sigjmp_save

main

puts@plt

exxit@plt

printf@plt

atoi@plt

sleep@plt

getcahar@plt

_dl_runtime_resolve_xsave

_dl_fixup

_dl_lookup_symbol_x

exit

5.7 Hello的动态链接分析

  首先 找到got函数的位置,通过edb工具中到相应位置,

在dl-int函数之前:从而找到该处地址

在执行dl-int函数之后:dl-int函数执行之后global_offset表由全0地状态被赋值上相应地值.

5.8 本章小结

本章介绍了链接的作用以及概念,并且通过hello和.0程序的必先分析中解释了链接的作用效果,带我们更好的了解链接的功效

第6章 hello进程管理

6.1 进程的概念与作用

概念:进程是计算机中一个程序在一定数据集上的单一运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础。

作用:进程可以给我们一种错觉,即程序在处理一条指令时没有中断,而且程序对处理器和内存有独占的访问权。

6.2 简述壳Shell-bash的作用与处理流程

作用:提供一个系统内核与操作系统的用户交互的界面

处理流程:首先在shell中输入命令,然后shell程序使用praseline内置函数来分割字符串并获得命令。如果得到的命令是一个内置的命令,那么它将被立即执行,如果它不是一个内置的命令,那么它将调用可执行文件来分叉一个子进程。

6.3 Hello的fork进程创建过程

shell的fork函数进程创建过程如上图所示,其中子进程可以读写父进程中打开的任何文件及文本

6.4 Hello的execve过程

Execve在当前进程中加载和运行程序,函数形式为int execve(char *filename, char *argv[], char *envp[])。覆盖当前进程的代码、数据和堆栈,但会保留具有相同的PID,继承打开的文件描述符和信号上下文。调用一次,永不返回,除非有错误,例如,指定的文本或者文件并不存在。

6.5 Hello的进程执行

①逻辑控制流。每个程序都会有一个程序计数器数值的序列,这个序列中数值的转换顺序被称为控制流。

②时间片:一个进程执行其控制流的一部分的每个时间段被称为一个时间片。

③用户模式和内核模式:用户模式是执行应用程序级别的代码和访问用户空间;内核模式是执行内核代码和访问内核空间(当然要有访问用户空间的权限)。

④上下文信息:执行进程所需信息的状态。

Hello的进程调的过程:

首先Hello程序被执行,该进程会处于用户模式。当输入参数不为3时,将调用exit函数,终止并回收Hello进程;当输入参数为3时,将使用sleep函数,进程将处于睡眠状态,此时内核将保存Hello的进程的上下文。之后,进程的上下文被恢复,进程再次启动。经过固定时间的休眠后,sleep函数传递一个信号,使控制权传递给内核,恢复Hello进程的上下文,并执行Hello进程。

6.6 hello的异常与信号处理

①运行时无输入进程被收回按回车结束

②随即输入无意义指令

运行过程中输入CTRL+c, 父进程收到SIGINT信号, 终止hello并回收

运行过程中输入CTRL+z后执行ps命令, 父进程收到SIGTSTP信号, 将hello挂起

运行过程中输入CTRL+z后执行jobs命令

运行过程中输入CTRL+z后执行pstree命令

部分截图

使用fg命令将进程调到前台

kill发送信号给一个或多个进程, 使用命令kill -9 18916杀死hello进程

6.7本章小结

进程的概念和作用,shell-bash的作用以及处理过程,fork,execve以及进程执行等过程,又通过实际操作让我们了解了各种信号的作用和产生结果,加深了我们对进程管理的认知

结论

一开始hello是以代码的形式存在,然后在预处理器中,.c被预处理并与外部库结合成为.i文件。然后在编译器中,它被编译成.s文件。之后,程序开始运行。Bash创建了一个新的进程,清除了当前进程的数据并加载了hello,从函数的入口点进入并开始执行。我们也可以输入一个命令来暂停正在执行的进程。hello输出信息时,这需要调用Unix。进程结束后,bash一直等到退出,因为hello的父进程召回了hello,内核也删除了所有关于hello的信息。这就是hello的旅程的结束。对hello的学习让我们对程序在计算机深层的表现有了更深的了解,基于这种了解,我们可以写出更好的、对系统友好的程序。
附件

hello.c: 源程序文件
hello.i: 预处理后的文件
hello.s: 编译后的汇编文件
hello.o: 汇编后的可重定位文件
hello: 链接后的可执行文件

参考文献

  1.     《深入理解计算机系统》Bryant and O’hallaron.

[2]           Global Descriptor Table - Wikipedia.
[3]  
        Translation lookaside buffer - Wikipedia

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值