程序人生-Hello’s P2P

2024-06-04 8892阅读

程序人生-Hello’s P2P 第1张

计算机系统

大作业

题     目  程序人生-Hellos P2P  

专       业    计算机科学与技术      

学     号      2022111101          

班   级       2203101            

学       生       郝永克         

指 导 教 师        史先俊             

计算机科学与技术学院

2023年4月

摘  要

本论文以简单的hello程序贯穿全文,详细论述程序从program到process最后被回收的过程,包括预处理,编译,汇编,链接等过程,从而展示程序的完整周期。并且展示进程等计算机重要概念,深入理解计算机运行程序时对异常的处理,提高对计算机底层思路的理解水平

关键词:hello;预处理;汇编;编译;链接;运行                            

目  录

第1章 概述

1.1 Hello简介

1.2 环境与工具

1.3 中间结果

1.4 本章小结

第2章 预处理

2.1 预处理的概念与作用

2.2在Ubuntu下预处理的命令

2.3 Hello的预处理结果解析

2.4 本章小结

第3章 编译

3.1 编译的概念与作用

3.2 在Ubuntu下编译的命令

3.3 Hello的编译结果解析

3.4 本章小结

第4章 汇编

4.1 汇编的概念与作用

4.2 在Ubuntu下汇编的命令

4.3 可重定位目标elf格式

4.4 Hello.o的结果解析

4.5 本章小结

第5章 链接

5.1 链接的概念与作用

5.2 在Ubuntu下链接的命令

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

5.4 hello的虚拟地址空间

5.5 链接的重定位过程分析

5.6 hello的执行流程

5.7 Hello的动态链接分析

5.8 本章小结

第6章 hello进程管理

6.1 进程的概念与作用

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

6.3 Hello的fork进程创建过程

6.4 Hello的execve过程

6.5 Hello的进程执行

6.6 hello的异常与信号处理

6.7本章小结

第7章 hello的存储管理

7.1 hello的存储器地址空间

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

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

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

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

7.6 hello进程fork时的内存映射

7.7 hello进程execve时的内存映射

7.8 缺页故障与缺页中断处理

7.9动态存储分配管理

7.10本章小结

第8章 hello的IO管理

8.1 Linux的IO设备管理方法

8.2 简述Unix IO接口及其函数

8.3 printf的实现分析

8.4 getchar的实现分析

8.5本章小结

结论

附件

参考文献


第1章 概述

1.1 Hello简介

Hello程序是简单的输出学号等信息的program,从程序到运行进过几个过程,首先是预处理器对hello.c进行预处理,然后经过编译器编译以及汇编过程后,再由链接器进行链接操作生成可执行文件hello,存放在磁盘中。当运行时,可执行文件从磁盘读取到内存中,shell为hello创建进程并调用加载器加载hello的可执行文件,为其提供虚拟地址空间等,然后在CPU等硬件设备处理指令以及数据的操作下,hello程序开始运行,运行时会出现许多异常,这些会通过异常处理机制逐一处理,最后到运行结束,操作系统结束hello进程,释放其占用的一切志愿,返回shell,整个hello生命周期结束。

1.2 环境与工具

硬件环境: CPU:AMD Ryzen7 5800H,16GB内存。
系统环境: 虚拟机:Ubuntu 20.04.4 LTS,VMware Workstation 16
工具: 文本编辑器gedit,反汇编工具objdump,编译环境gcc等。

1.3 中间结果

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

  1. hello.i 预处理生成的文件
  2. hello.s 编译后生成的文件
  3. hello.o 汇编之后生成的可重定位目标文件
  4. hello 链接后生成的可执行目标文件
  5. hello_o_disassembler.txt hello.o的反汇编代码
  6. hello_disassembler.txt hello.o的反汇编代码
  7. hello_o_elf.txt hello.o的ELF文件

1.4 本章小结

本章介绍了hello程序的运行周期,列举出实验的环境以及工具,并且展示出本次实验所产生的中间文件及其作用


第2章 预处理

2.1 预处理的概念与作用

概念:预处理指的是程序在编译之前进行的处理,是计算机在处理一个程序时所进行的第一步处理,可以进行代码文本的替换工作,但是不做语法检查。

作用:预处理是为编译做的准备工作,能够对源程序. c文件中出现的以字符“#”开头的命令进行处理,包括宏定义、文件包含、条件编译等,最后将修改之后的文本进行保存,生成. i文件

2.2在Ubuntu下预处理的命令

预处理命令:gcc hello.c -E -o hello.i(将预处理得到结果放入hello.i中)

程序人生-Hello’s P2P 第2张

2.3 Hello的预处理结果解析

首先是hello.c文件的一些基本信息如图:

程序人生-Hello’s P2P 第3张

然后是hello.c涉及到的所有头文件的信息如图:

程序人生-Hello’s P2P 第4张

其次是头文件中所定义的数据类型如图:

程序人生-Hello’s P2P 第5张

然后是头文件中的函数声明部分以及struct结构声明部分如图:

程序人生-Hello’s P2P 第6张

最后是我们的hello.c程序部分:

程序人生-Hello’s P2P 第7张

2.4 本章小结

本章对预处理过程进行展示,包括预处理的命令行指令,以及预处理后产生的hello.i文件解析,我们能发现预处理扩展了很多头文件内容,但hello程序仅仅使用了其中一小部分。


第3章 编译

3.1 编译的概念与作用

编译概念:编译是指将一种高级语言代码(如Java、C++等)翻译成另一种形式(如机器语言)的过程。

编译作用:将高级语言代码转化为计算机可以理解的机器语言代码,便于计算机执行        

3.2 在Ubuntu下编译的命令

编译命令行:gcc -S hello.i -o hello.s如图:

程序人生-Hello’s P2P 第8张

3.3 Hello的编译结果解析

3.3.1常量

常数用立即数表示,例如原程序中的argc与4比较,其汇编代码如图,$4表示立即数4

程序人生-Hello’s P2P 第9张

3.3.2局部变量

局部变量存放在寄存器或栈中,例如程序中的局部变量i,其存放在%rbp-4的位置

程序人生-Hello’s P2P 第10张

3.3.3赋值

赋值语句用mov操作表示,例如源代码中i=0,汇编代码如图

程序人生-Hello’s P2P 第11张

3.3.4算术操作

算数操作用add,sub等操作表示,例如源代码中的i++语句,其汇编代码如图:

程序人生-Hello’s P2P 第12张

3.3.5关系操作

关系操作例如==,!=等判断语句,在cmp操作实现,并产生条件码,之后jmp根据条件码进行跳转,例如源代码中判断argc!=4语句,其汇编代码如图:

程序人生-Hello’s P2P 第13张

3.3.6控制转移

控制转移包括if,while等使用jmp操作符实现,例如源代码中if(argc!=4){

printf("用法: Hello 学号 姓名 秒数!\n");

exit(1);

}语句,其汇编代码如图:

程序人生-Hello’s P2P 第14张

其中cmpl判断argc与常数4的大小,并产生条件码,je跳转指令根据条件码执行跳转操作

例如源代码中for(i=0;i上下文切换->执行进程B->上下文切换->执行进程A->… 如此循环往复。 在进程执行的某些时刻,内核可以决定抢占当前进程,并重新开始一个先前被抢占了的进程,这种决策就叫做调度,是由内核中称为调度器的代码处理的。当内核选择一个新的进程运行,我们说内核调度了这个进程。在内核调度了一个新的进程运行了之后,它就抢占了当前进程,并使用上下文切换机制来将控制转移到新的进程。在一个程序被调运行开始到被另一个进程打断,中间的时间就是运行的时间片。

6.5.3 调度的过程:

在对进程进行调度的过程,操作系统主要做了两件事:加载保存的寄存器,切换虚拟地址空间。

6.5.4 用户态与核心态转换:

为了能让处理器安全运行,需要限制应用程序可执行指令所能访问的地址范围。因此划分了用户态与核心态。

核心态可以说是拥有最高的访问权限,处理器以一个寄存器当做模式位来描述当前进程的特权。进程只有故障、中断或陷入系统调用时才会得到内核访问权限,其他情况下始终处于用户权限之中,保证了系统的安全性。

6.6 hello的异常与信号处理

hello可能出现的异常及处理方式:

  1. 中断:来自处理器外部的I/O设备信号的结果,由中断处理程序处理,处理后总是返回到下一条指令
  2. 陷阱:有意的异常,利用syscall指令请求系统服务,异常处理程序处理,这个处理程序解析参数,并调用适当的内核程序,最后总是返回到下一条指令
  3. 故障:潜在可恢复的错误,可能被故障处理程序修正,可能返回到当前指令
  4. 终止:不可恢复的错误,不会返回.

 产生信号种类:

程序人生-Hello’s P2P 第15张

处理方式:接收信号后,进程可以忽略这个信号,终止或者通过一个称为信号处理程序的用户层函数捕获这个信号

以下为例子:

1.正常运行:

程序人生-Hello’s P2P 第16张

2.按回车:不影响程序正

常运行

程序人生-Hello’s P2P 第17张

  1. 按ctrl+z:发送SIGTSTP信号,进程暂停被挂起

程序人生-Hello’s P2P 第18张

  1. 按ctrl+c:发送SIGINT信号,进程终止

程序人生-Hello’s P2P 第19张

Ctrl+z后运行命令

5.1.ps命令:

程序人生-Hello’s P2P 第20张

5.2.jobs命令:

程序人生-Hello’s P2P 第21张

5.3pstree命令:

程序人生-Hello’s P2P 第22张

5.4.fg命令:

程序人生-Hello’s P2P 第23张

5.5.kill命令:

程序人生-Hello’s P2P 第24张

6.7本章小结

本章主要介绍了进程及进程的创建,进程的运行,以及执行过程,此外介绍了运行过程中可能出现的异常以及信号及其对应的处理方式。

第7章 hello的存储管理

7.1 hello的存储器地址空间

1.逻辑地址(Logical Address)是指由程序产生的与段相关的偏移地址部分。在这里指的是hello.o中的内容。

2.线性地址(Linear Address)是逻辑地址到物理地址变换之间的中间层。程序hello的代码会产生段中的偏移地址,加上相应段的基地址就生成了一个线性地址。

3.虚拟地址:CPU启动保护模式后,程序hello运行在虚拟地址空间中。注意,并不是所有的“程序”都是运行在虚拟地址中。CPU在启动的时候是运行在实模式的,Bootloader以及内核在初始化页表之前并不使用虚拟地址,而是直接使用物理地址的。

4.物理地址:放在寻址总线上的地址。放在寻址总线上,如果是读,电路根据这个地址每位的值就将相应地址的物理内存中的数据放到数据总线中传输。如果是写,电路根据这个地址每位的值就在相应地址的物理内存中放入数据总线上的内容。物理内存是以字节(8位)为单位编址的。

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

逻辑内存地址由两个部分组成:段选择符和偏移量。逻辑地址通过这两个部分经过一系列的变换得到线性地址如图所示。以段选择符为索引,在GDT或LDT中找到对应的段描述符。将段描述符中的基地址与偏移量相加,得到线性地址

程序人生-Hello’s P2P 第25张

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

页式管理是一种内存空间存储管理的技术,页式管理分为静态页式管理和动态页式管理。将各进程的虚拟空间划分成若干个长度相等的页(page),页式管理把内存空间按页的大小划分成片或者页面(page frame),然后把页式虚拟地址与内存地址建立一一对应页表,并用相应的硬件地址变换机构,来解决离散地址变换问题。页式管理采用请求调页或预调页技术实现了内外存存储器的统一管理。

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

程序人生-Hello’s P2P 第26张

如图所示,CPU产生虚拟地址VA,并将其传送至MMU,MMU使用前36位***作为TLBT(前32位)+TLBI(后4位)在TLB中进行匹配,若命中,则得到PPN(40位)与VPO(12位)组合成物理地址PA(52位)。若TLB没有命中,则MMU向页表中查询,由CR3确定第一级页表的起始地址,***1(9位)确定在第一级页表中的偏移量,查询出PTE,如果在物理内存中且权限符合,则执行下一步确定第二级页表的起始地址,以此类推,最终在第四级页表中查询到PPN,与VPO组合成PA,并向TLB中添加条目。

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

CPU将一条虚拟地址VA传送到MMU按照7.4所述的操作获得了物理地址PA。如上图71右半部分所示,根据cache大小组数的要求,将PA分为CT(标记位)、CI(组索引)、CO(块偏移)。根据CI寻找到正确的组,依次与每一行的数据比较,有效位有效且标记位一致则命中。如果命中,直接返回想要的数据。如果不命中,就依次去L2、L3、主存判断是否命中,命中时将数据传给CPU同时更新各级cache的储存。

7.6 hello进程fork时的内存映射

当fork函数被当前进程调用时,内核为新进程创建各种数据结构,并分配给它一个唯一的PID。为了给这个新进程创建虚拟内存,它创建了当前进程的mm_struct、区域结构和页表的原样副本。当fork在新进程中返回时,新进程现在的虚拟内存刚好和调用fork时存在的虚拟内存相同。当这两个进程中的任何一个后来进行写操作时,写时复制机制就会创建新页面,因此,也就为每个进程保持了私有地址空间的抽象概念。

7.7 hello进程execve时的内存映射

1)在bash中的进程中执行了如下的execve调用:execve("hello",NULL,NULL);

2)execve函数在当前进程中加载并运行包含在可执行文件hello中的程序,用hello替代了当前bash中的程序。

3)删除已存在的用户区域。

4)映射私有区域:代码和数据区域被映射为.text区和.data区,bss区域是请求二进制零的,映射到匿名文件,栈和堆区域也是请求二进制零的,初始长度为零。

5)映射共享区域

6)设置程序计数器(PC):设置当前进程的上下文中的程序计数器到代码区域的入口点。

7.8 缺页故障与缺页中断处理

缺页异常的处理:

(1)缺页异常的产生:当程序尝试访问一个虚拟地址,而对应的页面不在物理内存中时,就会发生缺页故障。地址翻译硬件从内存中读取CPU引用信息对应的PTE,从有效位推断出对应的页未被缓存,触发缺页异常。 在进入异常处理程序之前,硬件会自动保存一些寄存器的值,以便在中断处理结束后能够正确地恢复执行。

(2)缺页异常处理程序:缺页异常调用缺页异常处理程序,该程序会选择一个牺牲页,若此页已被修改,内核会将其复制会磁盘。无论哪种情况,内核都会修改相应页表条目,反映牺牲页不再缓存在主存中。异常处理程序将缺页对应的页面从磁盘加载到主存中,更新页表,随后返回。

(3)正常继续运行:恢复之前保存的寄存器值,以便继续执行用户程序。此时,用户程序能够重新访问之前导致缺页故障的虚拟地址。由于页面已经加载到物理内存,重新执行引起缺页故障的指令。这次访问将成功完成。

7.9动态存储分配管理

动态储存分配管理使用动态内存分配器(如malloc)来进行。动态内存分配器维护着一个进程的虚拟内存区域,称为堆。分配器将堆视为一组不同大小的块的集合。每个块就是一个连续的虚拟内存页,要么是已分配的,要么是空闲的。已分配的块显式地保留为供应用程序使用。空闲块保持空闲,直到它显式地被应用所分配。一个已分配的块保持已分配的状态,直到它被释放,这种释放要么是应用程序显式执行的,要么是内存分配器自身隐式执行的。动态内存分配主要有两种基本方法与策略:

7.9.1 带边界标签的隐式空闲链表分配器管理

带边界标记的隐式空闲链表的每个块是由一个字的头部、有效载荷、(可能的)额外填充以及一个字的尾部组成。

隐式空闲链表:空闲块通过头部的大小字段隐含地连接着。分配器遍历堆中所有的块,间接地遍历整个空闲块的集合。

当一个应用请求一个k字节的块时,分配器搜索空闲链表,查找一个足够大的可以放置所请求块的空闲块。分配器有三种放置策略:首次适配、下一次适配和最佳适配。分配器在面对释放一个已分配块时,可以合并相邻的空闲块,其中一种简单的方式,是利用隐式空闲链表的边界标记来进行合并。

7.9.2 显式空间链表管理

显式空闲链表是将堆的空闲块组织成一个双向链表,在每个空闲块中,都包含一个前驱与一个后继指针。进行内存管理。在显式空闲链表中。可以采用后进先出的顺序维护链表,将最新释放的块放置在链表的开始处,也可以采用按照地址顺序来维护链表,其中链表中每个块的地址都小于它的后继地址,在这种情况下,释放一个块需要线性时间的搜索来定位合适的前驱。

7.10本章小结

本章主要介绍了hello 的存储器地址空间、段式管理、页式管理, VA 到PA 的变换、物理内存访问,fork、execve 时的内存映射、缺页故障与缺页中断处理、动态存储分配管理的相关内容。

第8章 hello的IO管理

8.1 Linux的IO设备管理方法

Linux中所有的IO设备都被模型化为文件,而所有的输入和输出都被当做对相应文件的读和写来执行。这种将设备映射为文件的方式,允许Linux内核引出一个简单、低级的应用接口,称为Unix I/O。这使得所有的输入和输出都能以一种统一且一致的方式来执行:打开文件、改变当前的文件位置、读写文件、关闭文件。

设备的模型化:文件

设备管理:unix io接口

8.2 简述Unix IO接口及其函数

Unix IO接口:Linux内核引出一个简单、低级的应用接口,称为Unix I/O。这使得所有的输入和输出都能以一种统一且一致的方式来执行

函数:

open和close - 打开和关闭文件

read 和 write – 最简单的读写函数;

readn 和 writen – 原子性读写操作;

iseek函数:修改文件偏移量

8.3 printf的实现分析

printf主函数:

程序人生-Hello’s P2P 第27张

调用的vsprintf函数:vsprintf的作用就是格式化。它接受确定输出格式的格式字符串fmt。用格式字符串对个数变化的参数进行格式化,产生格式化输出。返回的是要打印出来的字符串的长度

程序人生-Hello’s P2P 第28张

最后的write函数即为写操作,把buf中的i个元素的值写到终端。

write:

mov eax, _NR_write

mov ebx, [esp + 4]

mov ecx, [esp + 8]

int INT_VECTOR_SYS_CALL

从vsprintf生成显示信息,到write系统函数,到陷阱-系统调用 int 0x80或syscall等.

字符显示驱动子程序:从ASCII到字模库到显示vram(存储每一个点的RGB颜色信息)。

显示芯片按照刷新频率逐行读取vram,并通过信号线向液晶显示器传输每一个点(RGB分量)。

8.4 getchar的实现分析

getchar函数:

程序人生-Hello’s P2P 第29张

在getchar函数中,首先声明了几个静态变量:buf表示缓冲区,BUFSIZ为缓冲区的最大长度,而bb指针指向缓冲区的首地址。

getchar调用read函数,将缓冲区读入到buf中,并将长度送给n,再重新令bb指针指向buf。最后返回buf中的第一个字符(如果长度n

异步异常-键盘中断的处理:键盘中断处理子程序。接受按键扫描码转成ascii码,保存到系统的键盘缓冲区。

getchar等调用read系统函数,通过系统调用读取按键ascii码,直到接受到回车键才返回。

8.5本章小结

本章通过介绍hello中包含的函数所对应的unix I/O,以及printf和getchar函数的实现

结论

用计算机系统的语言,逐条总结hello所经历的过程。

  1. hello.c程序被创建后存储在内存中
  2. 然后预处理器将hello.c预处理成为hello.i,
  3. 接着编译器将hello.i翻译成汇编语言文件hello.s
  4. 汇编器将hello.s汇编成可重定位二进制代码hello.o
  5. 链接器将外部文件和hello.o连接起来形成可执行二进制文件hello
  6. shell通过fork和execve创建进程,然后把hello加载到其中,shell创建新的内存区域,并加载代码、数据和堆栈
  7. hello在执行的过程中遇到异常,会接受shell的信号完成处理
  8. hello在执行的过程中需要使用内存,那么就通过CPU和虚拟空间进行地址访问
  9. hello执行结束后,shell回收其僵***进程,从系统中消失

你对计算机系统的设计与实现的深切感悟,你的创新理念,如新的设计与实现方法。

计算机系统设计是一个复杂但是完备的过程,它确保程序运行的稳定性及准确性,它不仅仅是硬件和软件的结合,更是对计算机科学原理、算法、数据结构、操作系统、编程语言等多个领域深入理解的体现。


附件

列出所有的中间产物的文件名,并予以说明起作用。

程序人生-Hello’s P2P 第30张

参考文献

为完成本次大作业你翻阅的书籍与网站等

[1]  林来兴. 空间控制技术[M]. 北京:中国宇航出版社,1992:25-42.

[2]  辛希孟. 信息技术与信息服务国际研讨会论文集:A集[C]. 北京:中国科学出版社,1999.

[3]  赵耀东. 新时代的工业工程师[M/OL]. 台北:天下文化出版社,1998 [1998-09-26]. http://www.ie.nthu.edu.tw/info/ie.newie.htm(Big5).

[4]  谌颖. 空间交会控制理论与方法研究[D]. 哈尔滨:哈尔滨工业大学,1992:8-13.

[5]  KANAMORI H. Shaking Without Quaking[J]. Science,1998,279(5359):2063-2064.

[6]  CHRISTINE M. Plant Physiology: Plant Biology in the Genome Era[J/OL]. Science,1998,281:331-332[1998-09-23]. http://www.sciencemag.org/cgi/ collection/anatmorp.

(参考文献0分,缺失 -1分)


    免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理! 图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们,邮箱:ciyunidc@ciyunshuju.com。本站只作为美观性配图使用,无任何非法侵犯第三方意图,一切解释权归图片著作权方,本站不承担任何责任。如有恶意碰瓷者,必当奉陪到底严惩不贷!

    目录[+]