计算机系统

大作业

题 目 程序人生-Hello’s P2P
专 业 计算机科学与技术
学   号 120L022012
班   级 2003007
学 生 石瑞琳
指 导 教 师 吴锐

计算机科学与技术学院
2021年5月
摘 要
本文介绍了hello程序的一生,通过调试工具对hello的每个部分进行剖析,我们加深了对于计算机系统的理解,在文章中能够感受到hello的魅力所在。

关键词:P2P;020;编译;计算机系统;

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

目 录

第1章 概述 - 4 -
1.1 Hello简介 - 4 -
1.2 环境与工具 - 4 -
1.3 中间结果 - 4 -
1.4 本章小结 - 5 -
第2章 预处理 - 6 -
2.1 预处理的概念与作用 - 6 -
2.2在Ubuntu下预处理的命令 - 6 -
2.3 Hello的预处理结果解析 - 7 -
2.4 本章小结 - 7 -
第3章 编译 - 8 -
3.1 编译的概念与作用 - 8 -
3.2 在Ubuntu下编译的命令 - 8 -
3.3 Hello的编译结果解析 - 8 -
3.3.1文件指令 - 9 -
3.3.2 常量 - 10 -
3.3.3 变量 - 10 -
3.3.4 赋值 - 11 -
3.3.5 类型转换 - 11 -
3.3.6 算术操作 - 11 -
3.3.7 数组/指针/结构操作 - 12 -
3.3.8 函数操作 - 12 -
3.4 本章小结 - 14 -
第4章 汇编 - 15 -
4.1 汇编的概念与作用 - 15 -
4.2 在Ubuntu下汇编的命令 - 15 -
4.3 可重定位目标elf格式 - 15 -
4.4 Hello.o的结果解析 - 18 -
4.5 本章小结 - 20 -
第5章 链接 - 21 -
5.1 链接的概念与作用 - 21 -
5.2 在Ubuntu下链接的命令 - 21 -
5.3 可执行目标文件hello的格式 - 21 -
5.4 hello的虚拟地址空间 - 25 -
5.5 链接的重定位过程分析 - 26 -
5.6 hello的执行流程 - 27 -
5.7 Hello的动态链接分析 - 27 -
5.8 本章小结 - 28 -
第6章 hello进程管理 - 29 -
6.1 进程的概念与作用 - 29 -
6.2 简述壳Shell-bash的作用与处理流程 - 29 -
6.3 Hello的fork进程创建过程 - 29 -
6.4 Hello的execve过程 - 30 -
6.5 Hello的进程执行 - 30 -
6.6 hello的异常与信号处理 - 31 -
6.6.1异常 - 31 -
6.6.2 信号处理 - 32 -
6.7本章小结 - 35 -
第7章 hello的存储管理 - 36 -
7.1 hello的存储器地址空间 - 36 -
7.2 Intel逻辑地址到线性地址的变换-段式管理 - 36 -
7.3 Hello的线性地址到物理地址的变换-页式管理 - 37 -
7.4 TLB与四级页表支持下的VA到PA的变换 - 37 -
7.5 三级Cache支持下的物理内存访问 - 38 -
7.6 hello进程fork时的内存映射 - 39 -
7.7 hello进程execve时的内存映射 - 39 -
7.8 缺页故障与缺页中断处理 - 40 -
7.9动态存储分配管理 - 40 -
7.10本章小结 - 42 -
第8章 hello的IO管理 - 43 -
8.1 Linux的IO设备管理方法 - 43 -
8.2 简述Unix IO接口及其函数 - 43 -
8.3 printf的实现分析 - 43 -
8.4 getchar的实现分析 - 44 -
8.5本章小结 - 45 -
结论 - 45 -
附件 - 46 -
参考文献 - 47 -

第1章 概述
1.1 Hello简介
根据Hello的自白,利用计算机系统的术语,简述Hello的P2P,020的整个过程。
P2P: From Program to Process,编辑hello.c经cpp预处理器的预处理得到hello.i文件ccl编译器编译为hello.s文件,再经as汇编器变成hello.o文件,最后经过ld链接器链接得到可执行文件hello,在shell中输入启动命令后,fork产生一个子进程,hello便从程序变为了进程。
020:From Zero to Zero,shell为此进程execve,mmap操作映射到虚拟内存中,为运行的hello分配时间片来执行逻辑控制流,在程序执行结束后,父进程回收子进程,内核删除相关数据。
1.2 环境与工具
列出你为编写本论文,折腾Hello的整个过程中,使用的软硬件环境,以及开发与调试工具。
1)硬件环境:cpu:i7-11800H ram:32.0GB
2)软件环境:Windows10家庭版,虚拟机VMware14,Ubuntu 16.04 LTS 64位,百度网盘
3)调试工具:edb,gcc,bojump
1.3 中间结果
列出你为编写本论文,生成的中间结果文件的名字,文件的作用等。
中间结果文件 作用
hello.i 预处理后的文本文件
hello.s 编译后的汇编文本
hello.o 汇编后可重定位目标文件
hello,elf hello.o的elf
hello.asm hello.o的反汇编文件
hello 链接可执行
hello1.elf hello的elf
hello1.asm hello的反汇编文件

1.4 本章小结
本章介绍了hello的P2P和020的整个过程,列出了本文所用的软硬件及调试工具,以及在实验过程中生成的中间文件及其功能。
(第1章0.5分)

第2章 预处理
2.1 预处理的概念与作用
概念:程序开始运行时,预处理器cpp根据以字符#开头的命令,修改原始的c程序的过程。c语言有#define(宏定义),#include(源文件嵌入),#if,#else,#elif,#endif等预处理指令

作用:预处理根据源代码中的预处理指令修改源代码,将头文件的源码插入到目标文本中,预处理过程是对源程序代码进程行处理和替换,最终生成一个hello.i文件。预处理将不能识别的指令进行替换,方便后续的编译过程。
2.2在Ubuntu下预处理的命令
Ubuntu下预处理命令为cpp hello.c > hello.i

2.3 Hello的预处理结果解析

预处理得到hello.i文本文件,hello.i被宏展开拓展为3060行,其中main函数之前的代码为头文件#include<stdio.h> ,#include<unistd.h>,#include<stdlib.h>的展开,main中的代码没有任何变化。

2.4 本章小结
本章先介绍了预处理的概念和作用,之后在ubuntu上对作业要求的hello.c文件进行预处理操作生成hello.i文件,最后对hello.i进行解析。
(第2章0.5分)

第3章 编译
3.1 编译的概念与作用
概念:编译器ccl将指令翻译成汇编语言的过程。本文中指hello.i预处理文本翻译成hello.s汇编语言文本的过程。
作用:编译把高级语言变成计算机可识别的二进制语言。编译程序把一个源程序翻译成目标程序的工作过程分为五个阶段:词法分析;语法分析;语义检查和中间代码生成;代码优化;目标代码生成。,其中最主要的是词法分析和语法分析过程。
3.2 在Ubuntu下编译的命令
Ubuntu下编译命令为gcc -S hello.i -o hello.s

生成了汇编语言文件hello.s
3.3 Hello的编译结果解析
编译结果:

3.3.1文件指令

  指令        含义
.file       声明源文件
.text       代码段
.rodata    只读变量
.data      数据段
.align     声明对齐方式
.type      声明对象类型
.size      声明文件大小
.global    全局变量

3.3.2 常量
1)if(argv!=4)
4为常量,在hello.s中对应如下:

4以立即数形式存储在.text中。
2)for中

0,8,1,2,3以立即数存储在.text中

3.3.3 变量
Hello.c中 int i,i为变量
在hello.s中

i初始值为0,放置在%rbp-4的栈处
3.3.4 赋值
Hello.c中

i被赋初值为0
体现在汇编当中

同时每次循环i+1

3.3.5 类型转换

Atoi将argv[3]强制转化为整数型

3.3.6 算术操作

i++

3.3.7 数组/指针/结构操作

这里用到了指针操作,argv数组为传入的参数

argv存储在%rsi中
3.3.8 函数操作
调用了printf函数

Printf函数出现了两次
第一次:

第一次出现仅有一个参数,rdi传递
第二次:

调用了exit函数

传递1
调用了sleep和atoi函数

调用了getchar函数

汇编语言:

3.4 本章小结
本章首先介绍了编译的概念与作用,然后在ubuntu上应用指令编译hello.i生成hello.s汇编文件,接下来将hello.c与hello.s相对照,具体分析了每个语句在汇编语言中的表现和实现方法。
(第3章2分)

第4章 汇编
4.1 汇编的概念与作用
概念:汇编是把汇编语言翻译成机器语言的过程,汇编器将.s结尾的汇编文件翻译成机器语言指令,生成可重定位目标程序的.o文件
作用:hello.o是一个二进制文件,这种二进制代码能够被计算机处理并执行,汇编将汇编语言转换成底层的、低级的语言,以便被计算机理解处理。
4.2 在Ubuntu下汇编的命令
Ubuntu下汇编命令为:gcc -c hello.s -o hello.o

4.3 可重定位目标elf格式
Ubuntu下命令为:readelf -a hello.o > hello.elf

分析:
1)ELF头

ELF头以magic开始,描述生成此文件的系统信息,我们可以看到系统是64位的,ELF大小为64字节,节头部表偏移为1240bytes等信息
2)节头

描述了各个节的名称,类型,地址,偏移量等具体信息
3)重定位

.rela.text为节中位置的列表,包含需要重定位的信息,调用外部函数和引入全局变量的指令均需要重定位
.rela.eh_frame节是.eh_frame节重定位信息。
.symtab用于存放定义和引用的函数和全局变量的信息,name对应重定位目标模块,value为起始偏移量
4.4 Hello.o的结果解析
命令:objdump -d -r hello.o
反汇编代码:

hello.s代码:

1.机器语言:两文件相比较,hello.o中多出能被机器直接识别的机器语言,机器语言有0和1的代码构成
2.映射:机器语言由二进制代码构成,汇编指令映射到二进制功能码,汇编中的操作数被映射到二进制中的操作数,同时汇编中立即数用10进制表示,机器语言中立即数用16进制表示
3.分支转移:hello.s中分支转移用LC0,LC1这样的助记符来表示,而在反汇编指令中用确定的地址来表示。
4.函数调用:汇编语言中直接在call指令后面加上相应的函数名,而在反汇编语言中call+main+x,call后加的是相对地址
4.5 本章小结
本章首先介绍了汇编的概念与作用,然后在ubuntu下汇编生成hello.o,通过指令生成elf文件,对elf文件进行分析,了解了elf头,节头,重定位节等概念,最后比较了汇编程序hello.i和反汇编程序hello.o的不同。

(第4章1分)

第5章 链接
5.1 链接的概念与作用
概念:链接是将多个可重定位目标文件中的代码和数据合并到单一可执行文件的过程。链接可执行于编译时,链接时,加载和运行时
作用:在链接过程中进行了符号解析,和地址的重定位。链接过程将可重定位目标文件集合成一个可执行文件,我们可以把一个程序分成多个源程序文件,进行模块化的编译。
5.2 在Ubuntu下链接的命令
链接命令为:

5.3 可执行目标文件hello的格式
生成elf文件的指令:readelf -a hello >hello1.elf

分析elf文件:
1)ELF头:

Elf头中包含了关于系统等等的相关信息,我们可以看到节头的数量从14变成了29
2)节头:


我们可以看到恰好有29个节与elf头中信息相符合,节头中含有节的名称,偏移量,地址,类型等信息
3)重定位节

4)符号表

5.4 hello的虚拟地址空间
1.查看edb,hello起始地址为0x400000

与magic地址相同
2.由节头部表可以找到每个节的地址,如.hash地址偏移量为0x0340

到edb中找到相应地址

5.5 链接的重定位过程分析
命令:objdump -d -r hello

不同:
1)反汇编代码中地址为确定的虚拟地址,而hello中地址为地址偏移量
2)Hello中含有许多除main外的函数,链接的过程中发生重定位,使得被用到其他库的函数加入,hello比hello.o多出了一些节和代码

重定位的分析:在符号解析完成后,可进行重定位工作,分为3步
1)合并相同的节:将集合E的所有目标模块中相同的节合并成新节
2)对定义符号进行重定位;确定新节中所有定义符号在虚拟地址空间中的地址
3)对引用符号进行重定位:修改.text和.data节中对每个符号的引用
5.6 hello的执行流程
使用edb执行hello,说明从加载hello到_start,到call main,以及程序终止的所有过程。请列出其调用与跳转的各个子程序名或程序地址。

在edb中查看相应内容
子程序名 程序地址
hello!_start 0x00000000004010f0
hello!_init 0x0000000000401000
hello!puts@plt 0x0000000000401030
hello!printf@plt 0x0000000000401040
hello!getchar@plt 0x0000000000401050
hello!atoi@plt 0x0000000000401060
hello!exit@plt 0x0000000000401070
hello!sleep@plt 0x0000000000401080
hello!main 0x00000000004011d6

5.7 Hello的动态链接分析
在hello中动态链接通过延时绑定来实现,延时绑定依赖全局偏移量表GOT和过程连接表PLT实现。
查看与动态链接相关的.got.pit段

未调用init时

调用init后

我们看到00404000和00404010间数据发生变化,变化的原因是GOT加载了共享库的内容。

5.8 本章小结
本章介绍了链接的概念和作用,应用edb分析了hello的动态链接、执行流程等内容,分析了链接生成的hello文件结构,并将其与hello.o对比分析。
(第5章1分)

第6章 hello进程管理
6.1 进程的概念与作用
概念:进程是一个执行中程序的实例。进程是具有独立功能的一个程序关于某个数据集合的一次运行活动,一个程序可能对应多个不同的进程
作用:每个进程拥有一个独立的逻辑控制流和私有的虚拟地址空间,使得程序在执行过程中独占使用处理器和存储器。”进程”的引入简化了编程、编译、链接、共享和加载等整个过程。
6.2 简述壳Shell-bash的作用与处理流程
作用:shell是运行在终端中的文本互动程序,能够为用户提供操作界面和内核服务,它把我们在计算机上的操作翻译成计算机可识别的二进制命令,传递给内核,再由计算机执行命令,shell翻译成自然语言呈现在我们面前。Bash是常见的一种shell。
处理流程:
1)从终端读入输入的命令
2)按步骤读取用户命令行,获取命令行参数
3)内置命令直接执行,如果不是内置命令调用fork创建子进程
4)在子进程中,利用获取的参数调用execve执行程序
5)根据有无&,判断程序在前台还是后台运行
6)执行完成
6.3 Hello的fork进程创建过程
在我们执行hello程序时,由于hello程序不是shell的内置程序,因此shell调用fork函数创建子进程并进行后续操作。
父进程通过调用fork函数创建一个新的运行的子进程,在子进程中fork返回0,父进程中返回子进程的pid,需要注意的是,新创建的子进程几乎但不完全与父进程相同:
1)子进程得到与父进程虚拟地址空间相同但是相互独立的一份副本
2)子进程获得与父进程任何打开文件描述符相同的副本
父进程和子进程的最大区别是二者的pid不同,同时fork函数被调用一次,返回两次,一次返回至父进程,返回子进程的pid,一次返回至子进程,返回0
6.4 Hello的execve过程
子进程被创建后调用execve函数来运行hello程序,其中可执行文件为hello,参数列表argv,环境变量列表envp
其中argv指向一个指针数组,通常argv[0]==filename
envp指向一个指针数组,每个指针指向一个环境变量字符串,环境变量字符串的格式为name=value

Execve过程:execve调用启动加载器,删除掉当前虚拟地址中存在的区域,接下来创建一组新的区域结构,栈、堆等初始长度为0,将可执行目标文件中的代码和数据复制到内存中,之后跳转到程序的第一条指令或入口点来运行程序。
6.5 Hello的进程执行

结合进程上下文信息、进程时间片,阐述进程调度的过程,用户态与核心态转换等等。
上下文信息:进程上下文是表示进程信息的一系列东西,包括各种变量、寄存器以及进程的运行的环境。这样,当进程被切换后,下次再切换回来继续执行,能够知道原来的状态
进程时间片:进程时间片是分时操作系统分配给每个正在运行的进程微观上的一段CPU时间
进程调度:操作系统管理系统的资源,当多个进程要使用这些资源时,由于资源的有限,必须按照一定的原则选择进程来占用资源。当我们在运行程序时,进程会给我们一种假象:仿佛每个进程都在独占使用处理器。在进程执行时,内核可以抢占当前的资源,并重新开始一个被抢占了的进程,这便是进程调度的决策。我们使用上下文切换来控制转移到新的进程中去。
时间片是进程调度的方法之一,在时间片内如果进程完成任务或者阻碍,则该进程让出cpu,当进程耗费完时间片尚未执行完毕,强迫其让出cpu。
用户态和核心态的转换:
用户态就是执行在用户空间中,不能直接执行系统调用,必须先切换到内核态,也就是系统调用的相关数据信息必须存储在内核空间中,然后执行系统调用。
系统执行程序时大部分时间运行在用户态下,在其需要操作系统帮助,完成用户态没有权限无法完成的工作时,转换到用户态,这种转换是一种特殊的上下文切换。
6.6 hello的异常与信号处理
hello执行过程中会出现哪几类异常,会产生哪些信号,又怎么处理的。
程序运行过程中可以按键盘,如不停乱按,包括回车,Ctrl-Z,Ctrl-C等,Ctrl-z后可以运行ps jobs pstree fg kill 等命令,请分别给出各命令及运行结截屏,说明异常与信号的处理。
6.6.1异常
hello执行过程中可能会出现中断,陷阱,故障和终止四类异常
1)中断:由处理器外部I/O设备引起

2)陷阱:通过执行指令将控制返回到下一条指令
3)故障:故障并非有意的,有可能被修复,处理程序可能重新执行已经恢复的引起故障的指令,或是因故障未修复而终止
4)终止:因不可恢复的致命错误导致终止,比如非法指令的出现
6.6.2 信号处理
(1)不断乱按

乱按字符串直接打印在了屏幕上
(2)回车

程序正常运行
(3)Ctrl-Z:

Ctrl-z发送SIGSTP信号,hello程序被挂起,根据提示,输入要求的程序
ps:输出ps发现hello没有被回收进程号为49209
Jobs:job id为1,已停止
Pstree:通过进程树,我们能找到hello进程的位置
Fg:fg命令使进程继续运行
Kill:kill -9 49209可以杀死hello终止进程
(4)Ctrl-c

输入ctrl-c后,hello进程被终止,组合键使内核发送SIGINT信号到进程中,使得进程被终止。
6.7本章小结
(以下格式自行编排,编辑时删除)
本章介绍了hello的进程,shell的作用和处理流程,之后分析了shell运用fork创建子进程和应用execve加载运行程序的过程,再结合进程上下文信息、进程时间片,阐述进程调度的过程,用户态与核心态转换,解释了进程执行的过程,最后分析了异常,并用给定的hello程序进行实例分析。
(第6章1分)

第7章 hello的存储管理
7.1 hello的存储器地址空间
逻辑地址:逻辑地址分为段地址和偏移地址两部分。程序编译后在汇编代码当中的地址均为逻辑地址,在hello反汇编代码当中的地址就是逻辑地址。
线性地址:线性地址是逻辑地址到物理地址变换之间的中间层。程序代码会产生逻辑地址,或者说是段中的偏移地址,加上相应段的基地址就生成了一个线性地址,每个进程拥有独立的地址空间,拥有独立的资源。但对于某个特定时刻,只有一个进程运行于CPU之上。此时,CPU看到的就是这个进程所占用的空间,就是线性地址。
虚拟地址:CPU启动保护模式后,程序运行在虚拟地址空间中。由hello程序产生的由段选择符和段内偏移地址组成的地址。
物理地址:出现在CPU外部地址总线上的寻址物理内存的地址信号,是地址变换的最终结果地址。
7.2 Intel逻辑地址到线性地址的变换-段式管理

逻辑地址有48位,前16位为段选择符,后32位为段内偏移量
段选择符用于找到相应的段描述符,段描述符用于描述一个段的具体信息。
我们通过段选择符的TI字段判断描述符表时GDT还是LDT。TI是0,描述符表是GDT,TI是1,描述符表是LDT。我们通过段选择符得到段基址,再结合段内偏移量获得线性地址。
7.3 Hello的线性地址到物理地址的变换-页式管理

我们将程序的逻辑地址空间划分为固定大小的页,物理内存划分为同样大小的页框。在程序加载时,我们可将任意一页放入内存中任意一个页框,这些页框不必连续,从而实现了离散分配。该方法需要CPU的硬件支持,来实现逻辑地址和物理地址之间的映射。
MMU通过VPN在页表中找到了对应的页表项PTE,高速缓存/主存向MMU返回PTE。
7.4 TLB与四级页表支持下的VA到PA的变换
四级页表:大小4kb,页表条目大小8字节

N = 2 n :虚拟地址空间中的地址数量
 M = 2m : 物理地址空间中的地址数量
 P = 2 p : 页的大小 (bytes)
TLBI: TLB索引
 TLBT: TLB 标记
 VPO: 虚拟页面偏移量(字节)
 VPN: 虚拟页号
 PPO:物理页面偏移量 (same as VPO)
 PPN:物理页号
 CO: 缓冲块内的字节偏移量
 CI: Cache 索引
系统根据CR3得到页表基址。MMU通过虚拟页号到页表中选择适当的页表项,得到相应的PPN。VPO和PPO是相同的,因此将PPN和VPO串联起来就能得到对应的物理地址。四级页表第j级页表的PTE指向第j+1级页表的基址,最后一级页表的PTE包含某个物理页面的PPN。得到PPN后与VPO组合得到最后的PA。
7.5 三级Cache支持下的物理内存访问

MMU得到虚拟地址PA。根据cache大小和组数的要求,将PA分为CT(标记)、CI(组索引)和CO(块偏移),我们首先根据CI进行组索引,每组8路,对8路的块进行标志位匹配,匹配成功且块的标志位为1,则命中,根据CO取出块偏移量并返回,否则不命中,向下一级缓存请求数据,逐级写入cache。
7.6 hello进程fork时的内存映射
当fork被新进程hello调用,内核给hello创建各种数据结构,并分配唯一的pid。Fork为新进程创建虚拟内存,创建当前进程的的mm_struct, vm_area_struct和页表的原样副本,两个进程中的每个页面都标记为只读并且两个进程中的每个区域结构都标记为私有的写时复制(COW)。在新进程中返回时,新进程拥有与调用fork进程相同的虚拟内存,随后的写操作通过写时复制机制创建新页面。
7.7 hello进程execve时的内存映射
execve函数在当前进程中加载并运行新程序的步骤:
1)删除已存在的用户区域
2)创建新的区域结构:这些区域都是私有的、写时复制的。代码和数据,被映射为hello文件中的.text和.data区。
3)映射共享的区域,将hello程序与共享对象链接,对象动态链接到hello程序,然后映射到用户虚拟地址空间。
4)设置PC,设置程序计数器,指向代码区域的入口点

7.8 缺页故障与缺页中断处理
缺页故障:进程线性地址空间里的页面不必常驻内存,在执行一条指令时,如果发现他要访问的页没有在内存中(即存在位为0),那么停止该指令的执行,并产生一个页不存在的异常,对应的故障处理程序可通过从外存加载该页的方法来排除故障,之后,原先引起的异常的指令就可以继续执行,而不再产生异常。
缺页中断处理:处理器生成一个虚拟地址,并将它传送给MMU,MMU生PTE地址,并从高速缓存处请求得到它,高速缓存返回PTE,缺页处理程序确认出物理内存中的牺牲页,如果这个页已经被修改了,则把它换到磁盘,调入新的页面,更新PTE,最后返回原来的进程,重新执行导致缺页的命令,如果处理成功,就会命中。
7.9动态存储分配管理
Printf会调用malloc,请简述动态内存管理的基本方法与策略。
在程序运行时程序员使 用动态内存分配器 (比如malloc) 获得虚拟内存,动态存分配器维护着 一个进程的虚拟内存区域,称为堆。

分配器将堆视为一组不同大小的 块(blocks)的集合来维护,每个块要么是已分配的,要么是空闲的。
分配器有两种类型:
显性分配器:要求应用显式地释放任何已分配的块
隐形分配器:应用检测到已分配块不再被程序所使用,就释放这个块
当应用请求一个块时,分配器搜索空闲链表,查找一个足够大的可以放置所请求块的空闲块。分配器有三种放置策略:首次适配、下一次适配和最佳适配。分配器在面对释放一个已分配块时,合并相邻的空闲块,其中一种简单的方式,是利用隐式空闲链表的边界标记来进行合并。

7.10本章小结
本章介绍了存储器地址空间、段式管理、页式管理,VA 到 PA 的变换,物理内存访问,fork和execve 的内存映射、缺页故障与缺页中断处理以及动态存储分配管理,通过大作业对知识有了更系统地的了解与复习。
(第7章 2分)

第8章 hello的IO管理
8.1 Linux的IO设备管理方法
(以下格式自行编排,编辑时删除)
设备的模型化:文件
设备管理:unix io接口
一个Linux文件就是一个 m 字节的序列,所有的I/O设备都被模型化为文件,
那么I/O操作可看作对相应文件的读或写。
Linux内核给出了一个简单、低级的应用接口,能够以统一且一致的方式执行I/O操作,这包括:打开和关闭文件,读写文件和改变文件的位置
每个Linux文件都有一个类型(type)来表明它在系统中的角色:
普通文件,目录,套接字,命名通道,符号链接,字符和块设备。
8.2 简述Unix IO接口及其函数
Unix IO接口:
1)打开文件:Linux内核创建的每个进程都有三个打开的文件:标准输入,标准输出标准错误
2)读文件:从当前文件位置复制字节到内存位置,然后更新文件位置
3)写文件:从内存复制字节到当前文件位置,然后更新文件位置
4)关闭文件:调用close函数关闭一个打开的文件
Unix IO 函数:
1)int open(char* filename,int flags,mode_t mode)将文件转为操作符
2)int close(fd)关闭文件,并返回操作结果
3)ssize_t read(int fd,void *buf,size_t n)从fd复制n个字节到buf
4)ssize_t wirte(int fd,const void *buf,size_t n)从buf复制n个字节到fd
8.3 printf的实现分析
先从printf函数函数体
int printf(const char *fmt, …)
{
int i;
char buf[256];

 va_list arg = (va_list)((char*)(&fmt) + 4);i = vsprintf(buf, fmt, arg);write(buf, i);return i;
}

Valist说明arg是一个字符指针,指向fmt的第一个参数
Vsprintf返回即将打印的字符串的长度
接下来调用了write函数,write中INT_VECTOR_SYS_CALL表示要通过系统来调用sys_call这个函数
Sys_call作用是打印,显存存储ASCII字符码,字符显示驱动子程序通过ASCII码在字体库中查找点阵信息,将点阵信息存储在vram中。显示芯片按照刷新频率逐行读取vram,并通过信号线向液晶显示器传输每一个点(RGB分量)。
8.4 getchar的实现分析
(以下格式自行编排,编辑时删除)
getchar实现代码:
int getchar(void)
{
static char buf[BUFSIZ];
static char* bb=buf;
static int n=0;
if(n==0)
{
n=read(0,buf,BUFSIZ);
bb=buf;
}
return (–n>=0)?(unsigned char)*bb++:EOF;
}
异步异常-键盘中断的处理:键盘中断处理子程序。接受按键扫描码转成ascii码,保存到系统的键盘缓冲区。
getchar等调用read系统函数,通过系统调用读取按键ascii码,直到接受到回车键才返回,getchar函数的返回值是用户输入的字符的ASCII码,若文件结尾(End-Of-File)则返回-1(EOF),且将用户输入的字符回显到屏幕。如用户在按回车之前输入了不止一个字符,其他字符会保留在键盘缓存区中,等待后续getchar调用读取。

8.5本章小结
本章先介绍了linux下的IO管理方法,然后对第十章的内容unix IO进行了分析总结,最后对熟悉的printf函数和getchar函数进行详细的分析,通过本章,了解到了更深层次的实现原理。
(第8章1分)
结论
用计算机系统的语言,逐条总结hello所经历的过程。
预处理:hello.c经过cpp预处理变为hello.i
编译:hello.i经过编译变为hello.s,高级语言变为了汇编语言
汇编:hello.s经过as汇编变成hello.o可重定位文件,P2P也到此结束
链接:通过把hello和许多库文件连接到一起生成一个可执行的hello
运行:在shell中打开hello,shell为hello,fork一个子进程并用execve函数来运行hello进程
回收:在运行过程中,hello收到了许多信号,它对信号进程处理完成自己的任务,在hello进程结束后由shell回收,完成了自己辉煌的一生。
你对计算机系统的设计与实现的深切感悟,你的创新理念,如新的设计与实现方法。
通过完成大作业,我们把计算机系统的知识点串联到一起,形成了一张完整的网络,计算机改变了现代社会,它是那样的复杂和充满魅力。
(结论0分,缺失 -1分,根据内容酌情加分)

附件
列出所有的中间产物的文件名,并予以说明起作用。
中间结果文件 作用
hello.i 预处理后的文本文件
hello.s 编译后的汇编文本
hello.o 汇编后可重定位目标文件
hello,elf hello.o的elf
hello.asm hello.o的反汇编文件
hello 链接可执行
hello1.elf hello的elf
hello1.asm hello的反汇编文件

(附件0分,缺失 -1分)

参考文献
[1] 兰德尔E.布莱恩特. 深入理解计算机系统[M]. 2021年10月第一版第21次印刷. 北京市:机械工业出版社, 2021.
[2] 沈文枫. 计算机系统结构[M]. 4. 电子工业出版社.

程序人生-hit计统大作业相关推荐

  1. HIT计统大作业:程序人生-hello’s P2P

    .摘 要 本文简要分析了hello这一程序从"出生"到"成人"的过程,并介绍了相应的计算机系统组成成分在其中扮演的角色.主要包括预处理,编译,汇编,链接,进程管 ...

  2. 【无标题】计统大作业-hello

    计算机系统 大作业 题     目 程序人生-Hello's P2P 专       业 计算学部 学   号 120L022124 班   级 2003007 学       生 田茂尧 指 导 教 ...

  3. 计统大作业Hello P2P

    菜狗的大作业( 计算机系统 大作业 题     目 程序人生-Hello's P2P 专       业 计算机科学与技术 学    号 2021113307 班    级 21w0312 学     ...

  4. HIT计算机系统CSAPP大作业

    HIT计算机系统CSAPP大作业 摘 要 一.第1章 概述 1.1 Hello简介 ·P2P过程 ·020过程 1.2 环境与工具 1.2.1 硬件环境 1.2.2 软件环境 1.2.3 开发工具 1 ...

  5. HIT计算机系统CSAPP-ICS2022大作业程序人生

    摘 要 本文主要以hello的一生作为行文线索,介绍了程序从编写到运行的各个阶段以及和计算机系统相关联的结构和原理.主要部分分为预处理,编译,汇编,链接,以及计算机系统的进程管理,存储管理等. 关键词 ...

  6. 【Computer Organization笔记15】清华计组大作业布置:奋战二十天,做台计算机!

    本次笔记内容: P29 计算机组成原理(29):第25分钟起 P30 计算机组成原理(30) 我的计组笔记汇总:计算机组成笔记 视频地址:计算机组成原理 清华大学刘卫东 全58讲 国家精品课程 108 ...

  7. 计网大作业--SMTP邮件代理服务器

    软件设计 2.1 数据结构 变量名: S:本机上的socket链接数据结构 s = socket() host.port :本机IP地址和163邮箱端口号 host = "127.0.0.1 ...

  8. 哈工大计组大作业-RISC处理器设计

    RISC_CPU_HIT RISC处理器设计 地址:https://github.com/944613709/Design-of-RISC-Processor.git 要求 根据计算机组成原理课程所学 ...

  9. 程序设计基础c语言版大作业,程序设计基础(C语言版)

    本书详细介绍了C语言程序设计所涉及的标记.类型.运算符.表达式.基本输入/输出.顺序结构.选择结构.循环结构.数组类型.指针类型.函数.变量的属性.编译预处理.结构体类型.共同体类型.枚举类型以及文件 ...

最新文章

  1. raw格式图片读取与显示C++,opencv
  2. PHP根据IP获取当前所在地地址
  3. 管理软件售前咨询与企业架构
  4. 求一批整数中出现最多的个位数字_C语言经典100例007-求低n-1位的数
  5. Html5必看:教你如何选择移动APP开发框架
  6. 《淘宝店铺 大数据营销+SEO+爆款打造 一册通》一一2.2 实时直播抢占生意先机...
  7. Linux vim中使用计算器
  8. 剑指offer(刷题51-60)--c++,Python版本
  9. django-普通的cookie操作
  10. springboot使用thymeleaf完成数据的页面展示
  11. Eclipse的自动build选项,制造时别忘了选上~
  12. Oracle的权限角色及用户
  13. Linux sed命令之删除文件第一行,第n行
  14. Java中string,map,json之间的常用转换方法(json转map,map转json,json转string等)
  15. snmptrap 中文内容java解析_snmp trap内容中的中文如何解析
  16. Modis数据下载及后处理
  17. 计算机教室的英语单词怎么写,教室的英语单词怎么写
  18. 健脾和胃,养生食疗——山药枸杞鲫鱼汤了解一下
  19. 猿创征文|我的Go成长之路道阻且长
  20. 创维e900什么芯片_创维E900V21C晶晨芯片卡刷包 V1.0 免费版

热门文章

  1. 微信朋友如何找回 android,微信怎么恢复好友?简单几步轻松恢复!
  2. IDEA 在debug 模式下启动tomcat报错:Application Server was not ..reason:Unable to ping server at localhos:1199
  3. 第二阶段:数据库设计与初始化
  4. 数据分析师基本技能——SQL
  5. json对象、json字符串的区别和相互转换
  6. IntelliJ IDEA 简体中文字体
  7. 【光线追踪系列十四】蒙特卡洛积分与重要性采样
  8. B-spline Curves 学习之B样条曲线定义(4)
  9. What is the difference of PO Charge Account,PO Accrual Account and PO Variance Account
  10. 编程初学者入门训练-KiKi和酸奶