计算机系统
大作业
题 目 程序人生-Hello’s P2P
专 业 计算学部
学 号 7203610224
班 级 2036011
学 生 关壹铭
指 导 教 师 刘宏伟
计算机科学与技术学院
2021年5月
本文通过介绍hello程序的一生,对每一个经历的过程进行分析,表面上看是hello过程在表演,背后却是预处理,编译,汇编,链接,进程,虚拟存储共同作用的结果。通过对计算机系统的漫游,从最外面的文本文件,一步一步,到了最底层的硬件实现,和操作系统的配合,使得对计算机系统的理解,更加深入。
关键词:预处理,编译,汇编,链接,进程,虚拟存储
(摘要0分,缺失-1分,根据内容精彩称都酌情加分0-1分)
目 录
2.2在Ubuntu下预处理的命令.......................................................................... - 5 -
3.2 在Ubuntu下编译的命令............................................................................. - 6 -
4.2 在Ubuntu下汇编的命令............................................................................. - 7 -
5.2 在Ubuntu下链接的命令............................................................................. - 8 -
5.3 可执行目标文件hello的格式.................................................................... - 8 -
6.2 简述壳Shell-bash的作用与处理流程..................................................... - 10 -
6.3 Hello的fork进程创建过程..................................................................... - 10 -
6.6 hello的异常与信号处理............................................................................ - 10 -
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 -
8.1 Linux的IO设备管理方法.......................................................................... - 13 -
8.2 简述Unix IO接口及其函数....................................................................... - 13 -
第1章 概述
1.1 Hello简介
- P2P:
程序员用高级语言编写代码hello.c文件,经过预处理(预处理器cpp)得到hello.i文件,再经过编译器(cc1)编译得到hello.s汇编文件,再由汇编器(as)加工得到hello.o可重定位目标程序,最后由链接器将各部分链接在一起形成可执行程序。在shell中创建hello进程。
- 020:
原本并没有hello程序,可以看做0,是程序员输入的,将hello装载到进程,执行结束后父进程将其回收,又变成了0.
1.2 环境与工具
硬件环境:X64 CPU;2GHz;2G RAM;256GHD Disk 以上
软件环境:Windows10 64位以上;VirtualBox/Vmware 11以上;Ubuntu 16.04 LTS 64位/优麒麟 64位
开发与调试工具:gcc,vim,edb,readelf,HexEdit
1.3 中间结果
hello.c: 源文件
hello.i:预处理后的文件
hello.s:编译后的文件
hello.o:汇编器作用后的可重定位目标程序
hello.out:链接完的可执行程序
1.4 本章小结
本章介绍了hello程序的一生,p2p,020的过程。列举了中间产物,开发环境和工具,对hello程序有了初步的认识。
(第1章0.5分)
第2章 预处理
2.1 预处理的概念与作用
1.概念:
程序源代码被编译之前,由预处理器对程序源代码进行的处理。这个过程并不对程序的源代码语法进行解析,但它会把源代码分割或处理成为特定的符号为下一步的编译做准备工作。例如#include<stdio.h>,预处理器会将系统头文件的代码插入代码段中。
2.作用:
宏定义,文件包含,条件编译,便于程序的修改、阅读、移植和调试,也便于实现模块化程序设计。
2.2在Ubuntu下预处理的命令
如图在命令行窗口输入gcc -E hello.c -o hello.i命令后即完成预处理。
2.3 Hello的预处理结果解析
如图所示是hello.i文件与hello.c文件的对照。
可以看到,hello.i文件中加入了一些定义的变量,结构体以及外部定义的函数:
2.4 本章小结
本章介绍了预处理的概念和作用,并在Linux系统下对hello.c进行了预处理,并对hello.i进行了解析,观察到两者的不同之处。掌握了预处理的机制,看到了预处理的执行情况。
(第2章0.5分)
第3章 编译
3.1 编译的概念与作用
1.概念:
编译是指将源程序转换为计算机可以识别的低级机器语言。
2.作用:
编译是为了提高程序执行的效率,将对用户友好的语言转化为对机器友好的语言,不用解释器一条一条地翻译语句解析执行。
3.2 在Ubuntu下编译的命令
命令: gcc -S hello.i -o hello.s
hello.s文件截图
3.3.1常量:
if语句中参与比较的“4”,会保存在test段中。当做立即数,直接和指令一起保存。
3.3.2 全局变量:
图中的变量i是全局变量,
- 初始化了的全局变量:存放在data段
- 未初始化的全局变量:存放在bss段
3.3.3 字符串常量:
存放在rodata段
3.3.4 局部变量:
局部变量存储在栈帧中或寄存器中
3.3.5 算数运算操作:
图中i++是算术运算,对应add操作
如图可知i保存在-4(%rbp)中,对他进行加一操作
3.3.6 数组:
argv保存在%esi中,argc保存在%edi中
3.4 本章小结
本章介绍了编译的概念和作用,并给出了ubantu下生成汇编代码的指令,
并对常量,字符串,全局变量,局部变量,算术运算,数组等基本操作进行了解析,经过编译之后,hello.i变成了hello.s文件,变成了更低级的程序语言。
第4章 汇编
4.1 汇编的概念与作用
1.概念:
汇编是汇编器将汇编文件hello.s转换成机器语言指令,并把这些指令打包成可重定位目标程序的文件hello.o的过程。
2.作用:
将高级语言转化为可执行的机器指令,此时只是可重定位目标文件hello.o(二进制EFL文件),进行了符号解析和重定位,产生的EFL结构包含.text, .data, .bss, .reltext, .reldata, symtab, .rodata等节。
4.2 在Ubuntu下汇编的命令
gcc -c hello.s -o hello.o
4.3 可重定位目标elf格式
先看ELF文件的格式,分为很多节(.text,.data,.rodata等)
分别介绍如下
(1).text:存放已编译程序的机器代码。
(2).rodata:只读数据,比如printf语句中出现的格式串和开关语句的跳转表。
(3).data:已初始化的全局和静态C变量。
(4).bss:未初始化的全局和静态C变量,以及所有被初始化为0的全局和静态变量。
(5).symtab:一个符号表,存放在程序中定义和引用的函数和全局变量的信息。
(6).rel.text:一个.text节中位置的列表,当链接器把这个目标文件和其他文件组合时,需要修改这些位置。
(7).rel.data:被模块引用或定义的所有全局变量的重定位信息。
(8).debug:一个调试符号表,其条目是程序中定义的局部变量和类型定义,程序中定义和引用的全局变量,以及原始的C源文件。
这是ELF头部分:有一个16字节的串表示生成该文件的系统的字的大小和字节顺序。下面的部分表示机器类型、节头表的位置、条目大小、数量等。
4.4 Hello.o的结果解析
输入反汇编命令得到如下结果:
分析hello.o的反汇编,并请与第3章的 hello.s进行对照分析。
通过与hello.s的分析可知:
- 跳转时hello.s文件中写的是跳转表的名称,反汇编的到的是跳转地址的偏移量。
- 调用函数时,hello.s的call指令后面接的是具体的函数名,而反汇编文件接的是地址。
- 操作数大小不一致。
4.5 本章小结
本章介绍了汇编器将hello.s转变成hello.o的过程,介绍了ELF文件的格式,并对其进行反汇编与hello.s进行对比,有助于加深对汇编这一过程的理解。
(第4章1分)
第5章 链接
5.1 链接的概念与作用
1.概念:链接是将各种代码和数据片段收集并组合成单一文件的过程,这个文件可被加载到内存中并执行。
2.作用:使程序变得模块化,可以单独进行编写,分离编译,提高效率。
注意:这儿的链接是指从 hello.o 到hello生成过程。
5.2 在Ubuntu下链接的命令
5.3 可执行目标文件hello的格式
分析hello的ELF格式,用readelf等列出其各段的基本信息,包括各段的起始地址,大小等信息。1.readelf -h hello
ELF Header:
2.readelf -S hello
Section Headers:
3.readelf -s hello
symbol table:
1.不同:
hello中新增加了hello.c中用到的函数,比如printf,sleep等
新加入了_init ,.plt等节
hello中无hello.o中的重定位条目,并且跳转和函数调用的地址在hello中都变成了虚拟内存地址。
对于hello.o的反汇编代码,函数只有在链接之后才能确定运行执行的地址,因此在.rela.text节中为其添加了重定位条目。
2.hello利用不同可重定位目标程序中不同代码部分的相对地址,在hello中重新对其进行排序,得到重定位的文件。举例如下图所示:
请列出其调用与跳转的各个子程序名或程序地址:
0xcbea7014
0xcbea7088
0xcbea7122 <.plt>
0xcbea7127 < deregister_tm_clones>
0xcbea715d <.plt_got>
0xcbea719c <_init>
0xcbea71b9
5.7 Hello的动态链接分析
当程序被转载的时候,系统的动态链接器会将程序所需要的所有动态链接库装载到进程的地址空间,并将程序中所有未决议的符号绑定到相应的动态链接库中,并进行重定位工作。减少了内存、磁盘空间的浪费,还减少了物理页面的换入换出,也可以增加CPU缓存的命中率,因为不同进程的数据和指令偶读集中在了一个共享模块上。
5.8 本章小结
本章介绍了链接的概念和作用,了解了可执行目标文件的存储,重定位的过程,执行过程,以及动态链接的分析,深入理解了链接的原理。
(第5章1分)
第6章 hello进程管理
6.1 进程的概念与作用
概念:进程是执行的程序,这是一种非正式的说法。进程不只是程序代码(文本段或代码段),通常还包含以下内容:
- 当前活动,如程序计数器的值和处理器寄存器的内容等。
- 进程堆栈(包括临时数据,如函数参数、返回地址和局部变量)和数据段(包括全局变量)。
- 堆,这是在进程运行时动态分配的内存。
作用:进程给计算机提供了一种抽象,让计算机认为当前进程占用了全部的内存,独占处理器。进程有利于计算机同时加载多个程序到内存,进行并发执行。
6.2 简述壳Shell-bash的作用与处理流程
(一)shell :shell本身是一个用C语言编写的命令行解释器,它作为用户使和Linux内核之间的桥梁,可以解释和执行用户输入的命令。
(二)bash处理流程:
1. 将命令行分成由 元字符(meta character) 分隔的 记号(token):
元字符包括 SPACE, TAB, NEWLINE, ; , (, ), <, >, |, &
记号 的类型包括 单词,关键字,I/O重定向符和分号。
2. 检测每个命令的第一个记号,看是否为不带引号或反斜线的关键字。如果是一个 开放的关键字,如if和其他控制结构起始字符串,function,{或(,则命令实际上为一复合命令。shell在内部对复合命令进行处理,读取下一个命 令,并重复这一过程。如果关键字不是复合命令起始字符串,而是如then等一个控制结构中间出现的关键字,则给出语法错误信号。
3. 依据别名列表检查每个命令的第一个关键字。如果找到相应匹配,则替换其别名定义,并退回第一步;否则进入第4步。
4. 执行大括号扩展,例如a{b,c}变成ab ac
5. 如果~位于单词开头,用$HOME替换~。使用usr的主目录替换~user。
6. 对任何以符号$开头的表达式执行参数(变量)替换
7. 对形如$(string)或者`string` 的表达式进行命令替换
这里是嵌套的命令行处理。
8. 计算形式为$((string))的算术表达式
9. 把行的参数替换,命令替换和算术替换 的结果部分再次分成单词,这次它使用$IFS中的字符做分割符而不是步骤1的元字符集。
10. 对出现*, ?, [ ]对执行路径名扩展,也称为通配符扩展
11. 按命令优先级表(跳过别名),进行命令查寻。
先作为一个特殊的内建命令,接着是作为函数,然后作为一般的内建命令,最后作为查找$PATH找到的第一个文件。
12. 设置完I/O重定向和其他操作后执行该命令。6.3 Hello的fork进程创建过程
6.3 Hello的fork过程
fork函数会创建新的进程。Fork函数有两个返回值,如果返回值为-1,则表示创建失败,创建子进程返回0,父进程调用fork返回子进程的pid。Fork的子进程与父进程共享代码数据,子进程与父进程虚拟地址空间相同。
6.4 Hello的execve过程
execve的作用是在当前上下文进程中加载一个新的程序。
1. 陷入内核
2. 加载新的可执行文件并进行可执行性检查
3. 将新的可执行文件映射到当前运行进程的进程空间中,并覆盖原来的进程数据
4. 将EIP的值设置为新的可执行程序的入口地址。如果可执行程序是静态链接的程序,或不需要其他的动态链接库,则新的入口地址就是新的可执行文件的main函数地址;如果可执行程序还需要其他的动态链接库,则入口地址是加载器ld的入口地址
5. 返回用户态,程序从新的EIP出开始继续往下执行。至此,老进程的上下文已经被新的进程完全替代了,但是进程的PID还是原来的。从这个角度来看,新的运行进程中已经找不到原来的对execve调用的代码了,所以execve函数的一个特别之处是他从来不会成功返回,而总是实现了一次完全的变身。
在执行fork得到子进程后随即使用解析后的命令行参数调用execve,execve调用启动加载器来执行hello程序。加载器执行的操作是,加删除子进程现有的虚拟内存段,并创建新的代码、数据、堆和栈段。代码和数据段被初始化为hello的代码和数据。堆和栈被置空。然后加载器将PC指向hello程序的起始位置,即从下条指令开始执行hello程序。
6.5 Hello的进程执行
1.上下文切换:
即从一个可执行进程切换到另一个可执行进程。由 context_switch()函数负责处理。调用 switch_mm(),把虚拟内存从上一个进程映射切换到新进程中。调用 switch_to(),从上一个进程的处理器状态切换到新进程的处理器状态。包括保存、恢复栈信息和寄存器信息,以及其他任何与体系结构相关的状态信息
2.进程时间片:
处理器按照控制流逐条执行指令,因为进程需要轮流使用处理器,则同一处理器执行完一个进程的一部分后又要执行其他进程的一部分。
- 进程调度:
进程从一个切换到另一个的过程叫做进程调度。
2.用户态与核心态:
用户可以修改内核,需要一定的指令。
Hello进程一开始处于用户态,再接受相关信号后进入内核态,进行信号处理,然后返回用户模式。不断地切换进程实现并行。
6.6 hello的异常与信号处理
1.Hello进程可能遇到的异常:
- 中断:由处理器外部设备I/O引起的,例如时钟中断,从键盘输入Ctrl+c等。
- 陷阱:系统调用system call 时,用户和内核的接口。
- 故障:缺页故障,保护故障, 浮点异常。
- 中止:非故意,不可恢复的致命错误造成,Examples: 非法指令,奇偶校验错误,机器检查到致命的硬件错误。
系统中预先设定了一个异常表,里面包含了可能出现的各种异常状况,当出现异常时,系统会从当前进程跳到异常处理程序,异常情况会返回给程序一个索引来找到相应的解决办法。
2.接收到的信号:
Ctrl-C:会发送SIGINT 信号。当前进程收到这个信号之后,结束hello进程。
Ctrl-Z:会发送SIGSTP 信号。当前进程收到这个信号之后,会将hello进程挂起,就相当于停住了。
6.7本章小结
本章介绍了进程的相关概念,包括shell的处理流程,fork过程,execve过程是如何执行的。还介绍了进程会出现的异常情况和相应的处理办法,还有一些相关信号的处理。通过上手执行hello进程,使用命令ps,jobs,pstree,fg,kill熟悉工作原理。
(第6章1分)
第7章 hello的存储管理
7.1 hello的存储器地址空间
1)虚拟地址:
是由程序产生的由段选择符和段内偏移地址组成的地址。这2部分组成的地址并不能直接访问物理内存,而是要通过分段地址的变化处理后才会对应到相应的物理内存地址。
2)逻辑地址:
指由程序产生的段内偏移地址。逻辑地址与虚拟地址二者之间没有明确的界限。
3)线性地址:
指虚拟地址到物理地址变换的中间层,是处理器可寻址的内存空间(称为线性地址空间)中的地址。程序代码会产生逻辑地址,或者说段中的偏移地址,加上相应段基址就成了一个线性地址。如果启用了分页机制,那么线性地址可以再经过变换产生物理地址。若是没有采用分页机制,那么线性地址就是物理地址。
4)物理地址:
指内存中物理单元的集合,他是地址转换的最终地址,进程在运行时执行指令和访问数据最后都要通过物理地址来存取主存。
7.2 Intel逻辑地址到线性地址的变换-段式管理
机器语言指令中出现的内存地址,都是逻辑地址,需要转换成线性地址,再经过MMU(CPU中的内存管理单元)转换成物理地址才能够被访问到
在x86保护模式下,段的信息(段基线性地址、长度、权限等)即段描述符占8个字节,段信息无法直接存放在段寄存器中(段寄存器只有2字节)。Intel的设计是段描述符集中存放在GDT或LDT中,而段寄存器存放的是段描述符在GDT或LDT内的索引值(index)。
7.3 Hello的线性地址到物理地址的变换-页式管理
CPU通过地址来访问内存中的单元,地址有虚拟地址和物理地址之分,如果CPU没有MMU,或者有MMU但没有启用,CPU核在取指令或访问内存时发出的地址将直接传到CPU芯片的外部地址引脚上,直接被内存芯片(以下称为物理内存,以便与虚拟内存区分)接收,这称为物理地址。
如果CPU启用了MMU,CPU核发出的地址将被MMU截获,从CPU到MMU的地址称为虚拟地址(Virtual Address,以下简称VA),而MMU将这个地址翻译成另一个地址发到CPU芯片的外部地址引脚上,也就是将虚拟地址映射成物理地址。
依据以下步骤进行转换:
(1) 从cr3中取出进程的页目录地址(操作系统负责在调度进程的时候,把这个地址装入对应寄存器);
(2) 根据线性地址前十位,在数组中,找到对应的索引项,因为引入了二级管理模式,页目录中的项,不再是页的地址,而是一个页表的地址。(又引入了一个数组),页的地址被放到页表中去了。
(3)根据线性地址的中间十位,在页表(也是数组)中找到页的起始地址;
(4) 将页的起始地址与线性地址中最后12位相加,得到最终我们想要的地址。
7.4 TLB与四级页表支持下的VA到PA的变换
- 首先查看Virtual Address 的高16位VA[63:48]是否为全0,如果全0,使用TTBR0_EL1寄存内放的Level 0 Page Table的基地址; 否则,使用TTBR1_EL
- 由于是4K的页表,4K页表的大小是这样的计算的: 4KB = 1024 × 8 × 4 = 512 × 64 bit. 就是说4K 的页表要分为512个Entry, 每个Entry的大小为64bit。每个Entry存放的数据,实际是下一个level 的转换表的地址。对于某个VA[47:0], 我们怎么知道下一级页表的地址存放在这512个 Entry 中的那个Entry呢?答案是使用VA[47:39]来索引。这样就可以找到第二级转换表(level 1 page table)的首地址.
- Level 1 page table 也是4K 共512 个Entry,每个Entry 存放下一个页表的首地址,这个首地址的存放的位置要用VA[38:30]去索引Level 1 page table的Entry 得到. 样就可以找到第三级转换表(level 2 page table)的首地址.
- Level 2 page table 也是4K 共512 个Entry,每个Entry 存放下一个页表的首地址,这个首地址的存放的位置要用VA[29:21]去索引Level 1 page table的Entry 得到. 样就可以找到第四级转换表(level 3 page table)的首地址.
- .Level 3 page table 内存放的就是VA 向 PA转换的Descriptor了, 也是512个entry,每个Entry 64bit的数据。 通过VA[20:12]来索引使用那个Entry的descriptor。在这个descriptor中就可以得到我们想要的物理地址的 PA[47:12].
- 最终的地址转换完成,VA[47:0] 转换为 PA[47:0] = {来自level 3 转换表的PA[47:12], VA[11:0]}. 就是Descriptor 中给出物理地址的[47:12], 而虚拟地址给出物理的值的[11:0].
7.5 三级Cache支持下的物理内存访问
根据物理地址的中间三位(index字段)来定位当前数据应该在cache的哪一行,把物理地址的tag字段和该地址对应的内容放入对应的cache line的tag字段和data字段,并把相应的valid位置1 7.6 hello进程fork时的内存映射
物理内存的索引字段(Index)选择cache 的行,通过对比物理内存和cache line的Tag来判断是否命中。块偏移字段(Block Offset)可以从cache line的数据块中选择期望数据。在这个过程中cache的index是不占空间的,它就类似于物理内存的地址,对于物理内存来说是通过地址去寻找数据,对于cache来说,是通过index来找到对应的cache line。
7.6 hello进程fork时的内存映射
1.为新进程创建虚拟内存
2.在新进程中返回时,新进程拥有与调用fork的父进程相同的虚拟内存
3.随后的写操作通过写时复制机制创建新页面
7.7 hello进程execve时的内存映射
在执行fork得到子进程后随即使用解析后的命令行参数调用execve,execve调用启动加载器来执行hello程序。加载器执行的操作是,加删除子进程现有的虚拟内存段,并创建新的代码、数据、堆和栈段。代码和数据段被初始化为hello的代码和数据。堆和栈被置空。然后加载器将PC指向hello程序的起始位置,即从下条指令开始执行hello程序。
7.8 缺页故障与缺页中断处理
1) 处理器生成一个虚拟地址,并将其传送给MMU
2) MMU生成PTE地址(PTEA),并从高速缓存/主存请求得到PTE
3) 高速缓存/主存向MMU返回PTE
4) PTE的有效位为零, 因此 MMU 触发缺页异常
5) 缺页处理程序确定物理内存中的牺牲页 (若页面被修改,则换出到磁盘——写回策略)
6) 缺页处理程序调入新的页面,并更新内存中的PTE
7) 缺页处理程序返回到原来进程,再次执行导致缺页的指令
7.9动态存储分配管理
1.可利用空间表及分配方法:
只讨论链表,可利用空间表可称为存储池,三种情况:
- 系统运行期间所有用户请求分配的存储量大小相同,通常在系统开始运行时将内存区分割为大小相同的块,然后用指针链接成一个可利用空间表,请求内存时将第一个结点分配给程序,回收内存时在表头插入结点即可。
- 系统运行期间用户请求分配的存储量有若干种大小的规格,通常建立若干个可利用空间表,表内结点大小相同。此时分配与回收与第一种类似,只是在各自的可利用空间表中进行。两种额外情况:
如果结点大小与请求分配的内存大小相同的链表空了,查询结点较大的链表,取出一个结点分配一部分内存,再将剩下的部分插入相应的链表中
如果对应结点大小和大结点的链表都为空,不一定是内存满了,而是有可能经过多次分配之后,空闲区变成了多个小结点在其他链表中,此时应当重整内存,即"内存紧缩"
(3)系统运行期间用户请求分配的存储量大小不固定,就将整个内存空闲区作为结点,分配时割出一个结点,这种情况下结点应当指明自身的大小,即有一个结点大小域
2.边界标识法:
是操作系统中用以动态分区分配的一种存储管理方法,系统将所有空闲块连接在一个双重循环链表结构的可利用空间表中。
特点在于:每个内存区头部和底部设标识,标识该区域是占用块还是空闲块,使得在回收用户释放的空闲块时易于判别在物理位置上与其相邻的内存内存区域是否为空闲块,以便合并空闲存储区
3.
malloc 函数分配指定字节数的存储区。此存储区的初始值不确定。
calloc 函数为指定数量指定长度的对象分配存储空间。该空间中的每一位(bit)都初始化为 0。
7.10本章小结
本章介绍了hello进程的内存管理,介绍了逻辑地址,虚拟地址,线性地址和物理地址的相关概念,以及他们之间的转化方法。又讨论了fork,execve过程的内存映射,缺页中断的处理方案和动态内存分配管理的实现。
(第7章 2分)
结论
用计算机系统的语言,逐条总结hello所经历的过程。
你对计算机系统的设计与实现的深切感悟,你的创新理念,如新的设计与实现方法。
- 过程
1.程序员用高级程序语言编写程序,以ASCII码进行呈现,Hello便以文本形式出现。
2. 通过预处理器(cpp)的预处理,hello完成了扩展,包含,仍然是C语言格式的。
3. 被编译器(cc1)编译后,成了汇编语言(.s),语言已经成为汇编语言。
4.汇编器处理成为了二进制文件,hello.o,这个文件的格式是ELF文件格式,有待于进一步被链接。
5.链接器收到.o格式的hello,对hello进行符号解析与重定位。形成可执行文件。
6.我们在bash的shell里面,对hello进行加载,fork一个子进程,对子进程通过调用exceve函数,对虚拟内存进行了映射,hello就开始在子进程里面进行运行。
7. 在hello的main函数结束后,子进程进入终止状态,由父进程进行对子进程回收。
(二)感悟
从第一章到第八章的分析,我们深入了解了计算机底层的原理,熟悉了预处理,编译,汇编,链接,进程,存储等方面的原理和知识,以后在编写程序的时候可以更多地考虑底层方面的问题,不必一直局限在高级程序中,可以将程序进行进一步的优化。通过这次学习,感受到了计算机系统的博大精深,我还有很多地方的不足,还需要进一步的研究学习。
(结论0分,缺失 -1分,根据内容酌情加分)
附件
列出所有的中间产物的文件名,并予以说明起作用。
hello.c: 源文件
hello.i:预处理后的文件
hello.s:编译后的文件
hello.o:汇编器作用后的可重定位目标程序
hello.out:链接完的可执行程序
(附件0分,缺失 -1分)
参考文献
为完成本次大作业你翻阅的书籍与网站等
[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分)