计算机系统

大作业

题 目 程序人生-Hello’s P2P

专 业 航天学院

学   号 7203610117

班   级 2036015

学 生 李青峰   

指 导 教 师 史先俊  

计算机科学与技术学院

2022年5月

摘 要

本文简要分析了hello这一程序从开始执行到结束的过程,并基于Linux平台,通过gcc、objdump、gdb、edb等工具对hello程序代码预处理、编译、汇编、链接与反汇编的过程进行分析与比较,并且通过shell及其他Linux内置程序对hello进程运行过程进行了分析。

关键词:预处理;编译;汇编;链接;虚拟内存;I/O管理

(摘要0分,缺失-1分,根据内容精彩称都酌情加分0-1分

目 录

第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. 在linux中,对源程序进行预处理、编译、汇编、链接生成可执行目标文件。

O2O是指from zero to zero. 程序开始执行后,OS为其映射到虚拟内存,管理hello进程,分配物理内存,然后将其结果输出到显示器,最后回收内存空间。

1.2 环境与工具

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

软件环境:Windows10 64位;Vmware 11;Ubuntu 16.04 LTS 64位

开发和调试工具:gcc, gdb, as, ld, readelf

1.3 中间结果

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

hello.c: 源文件

hello.i: 预处理输出文件

hello.s: 编译输出文件(汇编语言)

hello.o:汇编输出文件(二进制文件)

hello:可执行文件

helloobj.s:hello.o的反汇编

helloobj1.s:hello的反汇编

hello.elf:hello的elf格式

1.4 本章小结

本章主要描述了hello程序的P2P020过程,介绍了本次实验所采用的软硬环境与调试工具,并列出了中间文件与其作用。

(第1章0.5分)

第2章 预处理

2.1 预处理的概念与作用

概念:在编译之前进行的处理

作用:这个过程不解析程序的源代码,常用于宏定义、文件包含、条件编译。

2.2在Ubuntu下预处理的命令

gcc –E hello.c –o hello.i

2.3 Hello的预处理结果解析

hello.c文件

hello.i文件

分析:由图可知,原来仅三十行左右的代码扩展到了三千多行。其中main函数部分没有发生变化,而头文件部分展开,而宏定义也由其相应的文件取代。

2.4 本章小结

本章主要介绍了预处理的概念和作用,并分析hello.c预处理的过程——头文件展开和宏定义处理,以及得到的结果。

(第2章0.5分)

第3章 编译

3.1 编译的概念与作用

概念:将高级语言翻译成汇编语言的过程,即将预处理后得到的文件(.i)生成汇编文本文件(.s)的过程。

作用:通过词法分析、语法分析、语义检查和中间代码生成、代码优化目、标代码生成,将程序员所用的高级语言转化为机器可识别的语言(二进制代码)。

注意:这儿的编译是指从 .i 到 .s 即预处理后的文件到生成汇编语言程序

3.2 在Ubuntu下编译的命令

3.3 Hello的编译结果解析

hello.s文件

3.3.1文件声明

.file 源文件名

.text代码段(codesegment/textsegment)通常是指用来存放程序执行代码的一块内存区域。

.section 指示把代码划分成若干个段

.rodata 用于维护只读数据

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

.string 字符串的存储位置

.global用来让一个符号对链接器可见,可以供其他链接对象模块使用;告诉编译器后续跟的是一个全局可见的名字

.type 指定是对象类型或是函数类型

3.3.2数据

(1)字符串

源程序中有2个字符串常量,均在printf函数中出现,这两个字符串前都被编译器声明了.rodata,即这两个字符串都将存放在只读数据区。

(2)整型数

全局变量:未赋初值的在.bss节中,赋初值的在.data中

局部变量:会在汇编语言里用寄存器表示,或存放在堆栈里

hello.s中申请了整型变量i,该变量是一个局部变量.编译器将局部变量存储在寄存器或栈中,在hello.s中编译器将i存储在-4(%rbp)中可以看出i占4个字节

argc 储存在寄存器%edi中,作为参数传入到-20(%rbp)的内存位置

3.3.3赋值操作

hello.s中的赋值操作:i= 0

该语句用movl指令来完成;0以立即数的形式存储,将0送给寄存器eax。赋值完成。

3.3.4算数操作

Hello.s中的算数操作:i++;

使用addl指令来完成,addl $1, -4(%rbp)

3.3.5关系操作

(1) argc!=4:用cmpl指令对4和存放在-20(%rbp)中的argc进行比较,相等则跳转,否者继续执行。Cmpl指令的功能相当于减法指令,不过不保存结果,只是对标志寄存器产生影响,只需要对标志寄存器进行判断。

(2) i<8:用cmpl指令对7和存放在-4(%rbp)中的i进行比较,小于等于则执行循环体

3.3.6控制转移

(1)if(avgc!=4) 使用cmp指令比较avgc与4,如果相等则使用je语句直接跳转到L2,如果不相等,则顺序执行。

(2) For(i = 0;i<8;i++) 先给在L2i赋值,然后跳转到L3L3中进行比较如果满足i<=7则进入循环,否则循环结束,调到循环外的下一条语句。

3.3.7函数操作

(1) main函数

功能:主函数

参数:调用了argc 和argv两个参数,%edi存储着argc的值

返回:返回值为0

(2)exit函数

参数:将立即数1传给%edi

(3)atoi函数

参数:将%rdi设置为1

返回:将要返回的值存储在%eax中,并用ret返回

(4)sleep函数

参数:将%edi设置为atoi(argv[3])(即调用atoi函数返回的数据)

(5)printf函数

在hello.s中printf被替换成了puts

参数:第一个printf将字符串的首地址传给了%rdi,然后调用了puts函数。第二个printf将“Hello %s %s\n”的首地址传给了%rdi,设置%rsi为argv[1],%rdx为argv[2]

(6)getchar函数

.4 本章小结

本章主要讲解了编译器将hello.i处理为hello.s的过程。着重描述编译时编译器如何处理数据并进行赋值操作、运算操作、关系操作、控制操作及函数操作等

(第32分)

第4章 汇编

4.1 汇编的概念与作用

概念:是指将汇编程序翻译成机器语言,把这些机器语言指令打包成可重定位目标程序的过程。

汇编的作用:把汇编语言翻译成机器语言,方便计算机识别和执行

4.2 在Ubuntu下汇编的命令

gcc -c hello.s -o hello.o

4.3 可重定位目标elf格式

获得hello.o文件的elf格式的指令:readelf -a hello.o > hello.elf

(1)ELF头

ELF头以一个十六字节的序列开始,描述了数据字节顺序数据表示方法、目标文件类型、系统架构、入口点地址、程序头起点、节头部的起始位置、ELF头的大小以及节头部表中条目的大小与数量等信息。

(2)节头部表

节头部表描述了各个节的类型、位置和大小等信息。

(3)重定位节

重定位节包含了.text 节需要重定位的信息,在生成可执行文件的时候会修改。图中包括putsexitprintfatoisleepgetchar这几个函数位置的描述。

4.4 Hello.o的结果解析

指令:objdump -d -r hello.o>hello.txt

hello.s文件进行比较:

(1)hello.o文件中每条语句都有了一个偏移量,便于跳转寻址。

(2)hello.txt采用十六进制,而hello.s中采用十进制。

(3)Hello.s中函数调用的方式是call后直接跟着函数名,而hello.txt中函数的调用方式是call后跟随着一个相对地址(函数与下一条指令的相对位置加上下一条指令的地址)来调用。

(4)分支转移:在.s文件中使用段名称如.LC0,反汇编代码中确定的地址。

4.5 本章小结

本章简单介绍了汇编的过程,分析了elf的格式和内容,之后通过查看反汇编代码,比较与.o文件的差别。

(第41分)

第5章 链接

5.1 链接的概念与作用

概念:将各种代码和数据片段收集并组合成一个单一文件的过程,这个文件可以被加载到内存中执行。

作用:链接操作将各个.o里面的函数引用,全局变量引用进行重定位,最终得到一个可执行目标文件,这个文件可以被加载到内存并运行。

5.2 在Ubuntu下链接的命令

ld -o hello -dynamic-linker /lib64/ld-linux-x86-64.so.2 /usr/lib/x86_64-linux-gnu/crt1.o /usr/lib/x86_64-linux-gnu/crti.o hello.o /usr/lib/x86_64-linux-gnu/libc.so /usr/lib/x86_64-linux-gnu/crtn.o

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

指令:readelf -a hello > hello1.elf

(1)ELF头

(2)节头部表

(3)程序头

(4)段节

(5)动态偏移表

(6)重定位节

(7)符号表

(8)版本符号节

(9)版本需求节

5.4 hello的虚拟地址空间

使用edb打开hello的可执行文件后,可以在Data

Dump中找到hello的虚拟地址空间。程序的虚拟地址空间为 0x00000000004001000-0x0000000000402000。

PHDR:程序头表

5.5 链接的重定位过程分析

指令:objdump -d -r hello>hello1.txt

(1)链接将程序中调用过得函数的汇编代码也加入到了程序里,hello1.txt中出现了puts getchar,atio,exit,sleep的汇编代码

(2)hello1.txt文件中增加了_init和.plt节

(3)函数调用,链接后每个函数都有了确定的运行地址

(4)相对偏移地址变为了虚拟内存的地址。链接时,链接器通过符号表和节头了解到.data和.text在每个文件中的偏移和大小,进行合并,然后为新的合并出来的数据和代码节分配内存,并映射虚拟内存地址。最后修改对各种符号的引用,完成重定位。

5.6 hello的执行流程

使用edb执行hello,列出从加载hello到_start,到call main,以及程序终止的所有过程程序名或程序地址。

函数名称 地址

ld-2.29.so!_dl_start 0x7f3325c6b030

ld-2.29.so!_dl_init 0x7f3325c799e0

hello!_start 0x401090

libc-2.29.so!__libc_start_main 0x7f0ca921ba80

libc-2.29.so!__cxa_atexit 0x7ff630a2a740

libc-2.29.so!__libc_csu_init 0x401150

hello!_init 0x401000

libc-2.29.so!_setjmp 0x7efd31390b90

libc-2.29.so!_sigsetjmp 0x7efd31390af0

hello!main 0x4010c1

hello!printf@plt 0x401040

hello!atoi@plt 0x401060

hello!sleep@plt 0x401080

hello!getchar@plt 0x401050

libc-2.27.so!exit 0x7f2c0fd763c0

5.7 Hello的动态链接分析

通过查找直到_dl_init在0x00007fb81f4d3630位置

在执行_dl_int函数前:

从而找到该处地址,在执行_dl_init函数后:

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

5.8 本章小结

本章简要介绍了链接的概念和作用,以及Ubuntu下的链接命令。并以hello文件为例,查看了链接后的文件格式,并对虚拟地址分配,重定位,动态链接等过程进行了分析。(第51分)

第6章 hello进程管理

6.1 进程的概念与作用

概念:操作系统对一个正在运行的程序的一种抽象。

作用:一个程序在系统上运行时,操作系统会提供一种,程序在独占这个系统,包括处理器,主存,I/O设备的假象。处理器看上去在不间断地一条一条执行程序中的指令…这些假象都是通过进程的概念实现的。

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

Shell 是指一种应用程序,Shell应用程序提供了一个界面,用户通过这个界面访问操作系统内核的服务。

处理流程:

从终端读入输入的命令。

将输入字符串切分获得所有的参数放入argv[]

如果是内置命令则立即执行

否则调用相应的程序为其分配子进程并运行

shell应该接受键盘输入信号,并对这些信号进行相应处理

6.3 Hello的fork进程创建过程

(1)在shell中输入相应命令

(2)shell分析命令,发现这不是内置命令,此时shell作为父进程通过fork函数创建一个新的进程给hello。

(3)新进程具有与原进程完全相同的状态(除PID)。创建过程如下:

为新进程复制父进程的堆栈等数据空间。

创建新进程。

6.4 Hello的execve过程

Execve函数在当前进程的上下文中加载并运行一个新程序。当读取文件出现错误时,返回原程序,否则不返回。具体步骤如下:

  1. 根据第一个参数加载文件,通过启动代码对栈进行设置,并完成控制传递。
  2. 顺序执行,用第二,三个参数调用main函数

6.5 Hello的进程执行

操作系统内核使用一种称为上下文切换的较高层形式的异常控制流来实现多任务。上下文切换机制建立在较低层异常机制之上的。

内核为每个进程维持一个上下文。上下文就是内核重新启动一个被抢占的进程所需的状态。它由一些对象的值组成,这些对象包括通用目的寄存器、浮点寄存器、程序计数器、用户栈、状态寄存器、内核栈和各种内核数据结构,比如描述地址空间的页表、包含有关当前进程信息的进程表,以及包含进程已打开文件的信息的文件表。

Hello进程执行:hello一开始运行在用户模式中;直到执行到sleep函数,该函数让hello进行休眠,内核处理器执行上下文切换,进入到内核模式,当定时器到达规定时间(atoi(argv[3])时,发生定时器中断,内核切换会用户模式

6.6 hello的异常与信号处理

hello执行过程中可能出现四类异常:中断、陷阱、故障和终止。

中断是来自I/O设备的信号,异步发生,中断处理程序对其进行处理,返回后继续执行调用前待执行的下一条代码,就像没有发生过中断。

陷阱是有意的异常,是执行一条指令的结果,调用后也会返回到下一条指令,用来调用内核的服务进行操作。帮助程序从用户模式切换到内核模式。

故障是由错误情况引起的,它可能能够被故障处理程序修正。如果修正成功,则将控制返回到引起故障的指令,否则将终止程序。

终止是不可恢复的致命错误造成的结果,通常是一些硬件的错误,处理程序会将控制返回给一个abort例程,该例程会终止这个应用程序。

按Ctrl-C:当按下ctrl-c之后,shell父进程收到SIGINT信号,信号处理函数的逻辑是结束hello,并回收hello进程。

Ctrl + Z

输入ps:

输入jobs:发现被停止的hello进程

输入pstree:

输入fg指令,使hello程序重新运行

输入kill -9 5441,杀死pid为16532的进程

6.7本章小结

本章简要介绍了进程的概念和作用,以及shell的处理流程。同时以hello文件为例分析了fork,execve,进程执行,以及异常和信号处理的过程。(第61分)

第7章 hello的存储管理

7.1 hello的存储器地址空间

1.逻辑地址:源代码经过预处理,编译,汇编后生成的地址,出现在汇编文件中,是由一个段加上一个偏移量组成,偏移量是实际地址与段开始时的地址之间的距离 。

2线性地址:逻辑地址经过段机制后转化为线性地址,为描述符:偏移量的组合形式。分页机制中线性地址作为输入;

3虚拟地址:在采用虚拟内存的系统中,CPU从一个有2n个地址的地址空间中生成虚拟地址。实际上就是线性地址。

4物理地址:计算机的主存被组织为M个字节大小的连续内存组成的数组,每个字节有唯一的地址,计算机利用地址总线来访问这些地址。

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

1·观察段选择符,0则转换的是GDT(全局)中的段,否则就是LDT(局部)中的段。

2·根据相应寄存器,找到其起始地址。

3·通过段标识符找到对应的基地址。

4·用基地址加上偏移,得到线性地址。

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

1·根据线性地址前十位找到对应页表的地址。

2·根据线性地址中间十位找到对应页的起始地址。

3·页的起始地址加上线性地址最后十二位,得到物理地址。

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

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

每次CPU产生一个虚拟地址,MMU就必须查阅相应的PTE,这显然造成了巨大的时间开销,为了消除这样的开销,MMU中存在一个关于PTE的小的缓存,称为翻译后备缓冲器(TLB)。

TLB通过虚拟地址VPN部分进行索引,如下图,分为索引(TLBI)与标记(TLBT)两个部分。

这样,MMU在读取PTE时会直接通过TLB,如果不命中再从内存中将PTE复制到TLB。Intel Core i7环境下虚拟地址空间48位,物理地址空间52位,页表大小4KB4级页表。TLB 416组相联。
解析前提条件:由一个页表大小4KB,一个PTE条目8B,共512个条目,使用9位二进制索引,一共4个页表共使用36位二进制索引,所以VPN36位,因为VA 48位,所以VPO 12位;因为TLB16组,所以TLBI4位,因为VPN 36位,所以TLBT 32位。
如图 CPU产生虚拟地址VAVA传送给MMUMMU使用前36VPN作为TLBT(前32位)+TLBI(后4位)向TLB中匹配,如果命中,则得到PPN40bit)与VPO12bit)组合成PA52bit)。
如果TLB中没有命中,MMU向页表中查询,CR3确定第一级页表的起始地址,VPN19bit)确定在第一级页表中的偏移量,查询出PTE,如果在物理内存中且权限符合,确定第二级页表的起始地址,以此类推,最终在第四级页表中查询到PPN,与VPO组合成PA,并且向TLB中添加条目。
如果查询PTE的时候发现不在物理内存中,则引发缺页故障。

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

获得了物理地址VA之后,使用CI(倒数7-12位)进行组索引,每组8路,对8路的块分别匹配CT(前40位)如果匹配成功且块的valid标志位为1,则命中。根据数据偏移量CO(后6位)取出数据返回。

如果没有匹配成功或者匹配成功但是标志位是1,则不命中,向下一级缓存中查询数据(L2 Cache->L3 Cache->主存),查询到数据之后,一种简单的放置策略如下:如果映射到的组内有空闲块,则直接放置,否则组内都是有效块,产生冲突(evict),则采用最近最少使用策略LFU(Leastfrequently used)进行替换。也就是替换掉最不经常访问的一次数据。

7.6 hello进程fork时的内存映射

fork会为新进程(子进程)复制一个与父进程完全相同只读数据空间,并为其分配另一片内存和虚拟地址。分配时会将其标记为私有,防止过程中被父进程影响。7.7 hello进程execve时的内存映射

execve函数调用驻留在内核区域的启动加载器代码,在当前进程中加载并运行包含在可执行目标文件hello中的程序,用hello程序有效地替代了当前程序。加载并运行hello需要以下几个步骤:

1.删除已存在的用户区域,删除当前进程虚拟地址的用户部分中的已存在的区域结构。

2.映射私有区域,为新程序的代码、数据、bss和栈区域创建新的区域结构,所有这些新的区域都是私有的、写时复制的.代码和数据区域被映射为hello文件中的.text和.data区,bss区域是请求二进制零的,映射到匿名文件,其大小包含在hello中,栈和堆地址也是请求二进制零的,初始长度为零。

3.映射共享区域,hello程序与共享对象libc.so链接,libc.so是动态链接到这个程序中的,然后再映射到用户虚拟地址空间中的共享区域内。

4.设置程序计数器(PC),execve做的最后一件事情就是设置当前进程上下文的程序计数器,使之指向代码区域的入口点。

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

DRAM 缓存不命中称为缺页,即在MMU中查找页表时发现与该地址相对应的物理地址不在内存中。缺页导致页面出错,产生缺页异常,内核调用缺页处理程序。

缺页中断处理:

1判断虚拟地址是否合法,缺页处理程序会搜索区域结构的链表,把该地址和每个区域结构中的vm_startvm_end做比较。如果指令不合法则触发段错误,从而终止该进程。

2然后检查进程是否有读、写或执行该区域页面的权限,如果不具有则触发保护异常,程序终止。

3以上两步检查都没有错误的话,内存会确定一个牺牲页,若页面被修改,则换出到磁盘,再将新的目标页替换牺牲页写入,缺页处理程序返回到原来的进程,重启导致缺页的指令。

7.9动态存储分配管理

分配器有两种风格,显示分配器(要求应用显式地释放任何已分配的块),隐式分配器(要求分配器检测一个已分配块是否仍然需要,不需要则释放)。

分配策略:

1·空闲链表:

(1) 隐式:在每块的头,尾部增加32位存储块大小,以及是否空闲。

(2) 显式:在隐式的基础上在头部增加对前后空闲块的指针。

(3) 分离:同时维护多个空闲链表。

2·带边界标记的合并:

利用每块头尾的大小和空闲状态信息合并空闲块。

3·无合适空闲块时,申请额外的堆空间。

7.10本章小结

本章简要介绍了文件的存储管理,包括各种地址的转换,错误的处理,以及动态存储的分配模式。(第7 2分)

第8章 hello的IO管理

8.1 Linux的IO设备管理方法

设备的模型化:所有的IO设备都被模型化为文件,而所有的输入输出都被当作对相应文件的读和写来执行。

设备管理:这种设备映射为文件的方式,允许Linux内核引出一个简单、低级的应用接口,称为Unix I/O,这使得输入和输出都能以一种统一且一致的方式的来执行。8.2 简述Unix IO接口及其函数

Unix IO接口:

打开文件:内核返回一个非负整数的文件描述符,通过对此文件描述符对文件进行所有操作。

Linux

shell创建的每个进程开始时都有三个打开的文件:标准输入(文件描述符0)、标准输出(描述符为1),标准出错(描述符为2)。头文件定义了常量STDIN_FILENO、STDOUT_FILENO、STDERR_FILENO,他们可用来代替显式的描述符值。

改变当前的文件位置,文件开始位置为文件偏移量,应用程序通过seek操作,可设置文件的当前位置为k。

读写文件,读操作:从文件复制n个字节到内存,从当前文件位置k开始,然后将k增加到k+n;写操作:从内存复制n个字节到文件,当前文件位置为k,然后更新k。

关闭文件。当应用完成对文件的访问后,通知内核关闭这个文件。内核会释放文件打开时创建的数据结构,将描述符恢复到描述符池中

函数:

open函数:将filename转换为一个文件描述符,并返回描述符数字。

int open(char *filename ,int flags, mode_t mode)

close函数:关闭一个打开的文件

int close(int fd);

read函数:用来对文件的输入

ssize_t read(int fd , void *buf, size_t n);

write函数:用来对文件的输出

ssize_t write(int fd ,void *buf ,size_t n);

8.3 printf的实现分析

https://www.cnblogs.com/pianist/p/3315801.html

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

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

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

8.4 getchar的实现分析

异步异常-键盘中断的处理:当用户按键时,键盘接口会得到一个代表该按键的键盘扫描码,同时产生一个中断请求,中断请求抢占当前进程运行键盘中断子程序,键盘中断子程序先从键盘接口取得该按键的扫描码,然后将该按键扫描码转换成 ASCII 码,保存到系统的键盘缓冲区之中。

getchar函数通过调用read函数返回字符。其中read函数的第一个参数是描述符,0代表标准输入。第二个参数输入内容的指针,也就是字符的地址,最后一个参数是1,代表读入一个字符,符号getchar函数读一个字符的设定。read函数的返回值是读入的字符数,如果为1说明读入成功,那么直接返回字符,否则说明读到了buf的最后。

8.5本章小结

Hello从原程序.c文件经过预处理,编译,汇编,链接得到了可执行文件。执行时,通过os对命令的处理结果,hello被分配到了自己的存储空间,虚拟内存地址和时间片。过程中,I/O不断接受信号并对其进行处理。运行结束后,内核清除已分配的数据空间,还原系统状态。(第81分)

结论

通过上文的学习与实践,可以大体概括hello程序所经历的过程:

生成阶段:预处理→编译→汇编→链接;

加载阶段:shell fork子进程→execve;

执行阶段:磁盘读取、虚拟内存映射、CPU执行指令、内核调度、缓存加载数据、信号处理、Unix I/O输入与输出;

终止阶段:进程终止、shell与内核对其进行回收。

感悟:通过分析各种文件,我对编译汇编链接等过程的理解更加深刻了。计算机上任何一个简单的程序,都需要软硬件协作经过一系列复查的过程才能完成,深入理解计算机系统,有助于我们了解这一过程,对我们编写面向计算机友好的系统有很大帮助。

(结论0分,缺失 -1分,根据内容酌情加分)

附件

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

(附件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分)