20145316 《信息安全系统设计基础》期中总结
一、Linux常用命令
1.本学期要求掌握的命令:
ac,apt-get,bzip2,cat,chgrp,chmod,chown,clear,compress,cp,
dd,df,diff,du,dump,evn,find,finger,free,grep,gzip,head,kill,less,
ln,locate,l,gout,ls,man,mkdir,more,mount,mt,mv,netstat,nslookup,
od,passwd,patch,ps,pstop,pwd,rm,shell,sort,ssh,stty,tail,tar,telnet,
touch,tree,uname,unzip,vi,vim,whereis,which,who,write等
2.本学期重点学习的命令:
cheat/find/locate/grep/man/whereis/which/apt-get
3.重点命令详解:
1、find
-
在指定目录下搜索指定文件名的文件:
$ find /etc/ -name interfaces
注意:find 命令的路径是作为第一个参数的, 基本命令格式为
find-[path]-[option]-[action]
- 与时间相关的命令参数:
参数 | 说明 |
---|---|
-atime |
最后访问时间 |
-ctime |
创建时间 |
-mtime |
最后修改时间 |
-
下面以
-mtime
参数举例:-mtime n
: n 为数字,表示为在n天之前的”一天之内“修改过的文件-mtime +n
: 列出在n天之前(不包含n天本身)被修改过的文件-mtime -n
: 列出在n天之前(包含n天本身)被修改过的文件newer file
: file为一个已存在的文件,列出比file还要新的文件名
-
列出 home 目录中,当天(24 小时之内)有改动的文件:
$ find ~ -mtime 0
- 列出用户家目录下比Code文件夹新的文件:
$ find ~ -newer /home/shiyanlou/Code
2、grep
-
grep
命令是很强大的,也是相当常用的一个命令,它结合正则表达式可以实现很复杂却很高效的匹配和查找,不过在学习正则表达式之前,这里介绍它简单的使用,而关于正则表达式后面将会有单独一小节介绍到时会再继续学习grep
命令和其他一些命令。 -
grep
命令的一般形式为:grep [命令选项]... 用于匹配的表达式 [文件]...
-
-r
参数表示递归搜索子目录中的文件,-n
表示打印匹配项行号,-I
表示忽略二进制文件。
3.man
-
man -k (等价于apropos)在 Linux 环境中,如果你遇到困难,可以使用man 命令,它是Manual page的缩写。
-
Manual pages 是在 UNIX 或类 UNIX 操作系统在线软件文档的一种普遍的形式。 内容包括计算机程序(包括库和系统调用),正式的标准和惯例,甚至是抽象的概念。用户可以通过执行 man 命令调用手册页。
-
$ man <command_name>来获得某个命令的说明和使用方式的详细介绍
-
你想查看 man 命令本身的使用方式,你可以输入:
man man
-
要查看相应区段的内容,就在 man 后面加上相应区段的数字即可,如:
$ man 3 printf
-
man -k 常用来搜索,结合管道使用。
4.cd
- 进入上一级目录:
$ cd ..
- 进入你的“home”目录:
$ cd ~
- 或者 cd /home/<你的用户名> 3、使用 pwd 获取当前路径:
$ pwd
5.新建文件相关命令
-
使用
touch
命令创建空白文件 -
使用
mkdir(make directories)
命令可以创建一个空目录,也可同时指定创建目录的权限属性 -
使用
-p
参数,同时创建父目录 -
使用
cp(copy)
命令复制一个文件或目录到指定目录。将之前创建的"test"文件复制 -
要成功复制目录需要加上
-r
或者-R
参数, -
使用
rm(remove files or directories)
命令,删除一个文件或目录: -
使用
mv(move or rename files)
命令,移动文件(剪切)。将文件"file1"移动到"Documents"目录mv 源目录文件 目的目录
6.cat
命令说明: 查看文件内容,也可以给文件追加内容到结尾
语法:cat [-AbEnTv]
参数:
-A :相当于-vET的整合参数,可以列出一些特殊字符,而不是空白而已 -b :列出行号,仅对非空行号显示,空白行不标记行号
-E :将结尾的断行字符$显示出来
-n :打印出行号,连同空白行也有行号,与-b参数不同
-T :将[tab]按键以^I 显示出来
-v :列出一些看不出的特殊字符
7.cheat
cheat是非常好用的“作弊”搜索工具,能够方便的告诉你你想要的内容。它提供显示Linux命令使用案例,包括该命令所有的选项和简短但尚可理解的功能。
cheat ls
-
查看用户
$ who am i
-
创建用户
要创建用户需要 root 权限,要用到 sudo 这个命令。使用这个命令有两个大前提,一是要知道当前登录用户的密码,二是当前用户必须在 sudo 用户组。
- 用户组 在 Linux 里面每个用户都有一个归属(用户组),用户组简单地理解就是一组用户的集合,它们共享一些资源和权限,同时拥有私有资源。 查看用户属于的用户组:
$ groups 用户名 或 $ cat /etc/``group | sort
$ sudo adduser 用户名
- 将其它用户加入 sudo 用户组:
$ su 当前用户 //获得root权限 $ groups 待添加用户 $ sudo usermod -G sudo 待添加用户 //将用户添加到sudo用户组 $ groups 待添加用户
- 删除用户
$ sudo deluser 待删除用户 --remove-home
二、vi、gcc等的使用
Vim编辑器
{0}. 普通模式(Normal mode):在普通模式中,用的编辑器命令,比如移动光标,删除文本等等。这也是Vim启动后的默认模式。在普通模式中,进入插入模式比较普通的方式是按a
(append
/追加)键或者i
(insert
/插入)键。
{0}. 插入模式(Insert mode):在插入模式中,可以按ESC键回到普通模式。
{0}. 可视模式(Visual mode):命令多与字母v有关,移动命令会扩大高亮的文本区域。高亮区域可以是字符、行或者是一块文本。
{0}. 选择模式(Select mode):这个模式中,可以用鼠标或者光标键高亮选择文本,不过输入任何字符的话,Vim会用这个字符替换选择的高亮文本块,并且自动进入插入模式。
{0}. 命令行模式(Command line mode):在命令行模式中,执行命令(:键),搜索(/和?键)或者过滤命令(!键)。在命令执行之后,Vim返回到命令行模式之前的模式,通常是普通模式。
{0}. Ex模式(Ex mode):这和命令行模式比较相似,在使用:visual命令离开Ex模式前,可以一次执行多条命令。
{0}. Vim常用命令总结:
- 插入:
i
:在当前光标处进行编辑a
:在光标后插入编辑
- 退出:
q!
:强制退出,不保存:q
:退出:wq!
:强制保存并退出:wq
:保存并退出:w <文件路径>
:另存为
- 删除:
x
:删除游标所在的字符dd
:删除整行
- 行间跳转:
nG(n Shift+g)
:光标移动到第n行
- 复制与粘贴:
nyy
:复制光标所在及其后的整行共n行p
:代表粘贴至光标后
- 功能设定:
:set autoindent(ai)
:设置自动缩进:set cindent(cin)
:设置C语言风格缩进:set nu
:以显示行号
gcc编译链接器
-
预处理
:gcc –E hello.c –o hello.i ;gcc –E
调用cpp 产生预处理过的C原始程序 -
编 译:
gcc –S hello.i –o hello.s ;gcc –S
调用ccl 产生汇编语言原始程序 -
汇 编:
gcc –c hello.s –o hello.o ;gcc -c
调用as 产生目标文件 -
链 接:
gcc hello.o –o hello ;gcc -o
调用ld 产生可执行文件 -
运行:
./hello
注意:
gcc的一般格式为:
gcc [选项] 要编译的文件 [选项],
其中,目标文件可默认,gcc默认生成可执行的文件,名为编译文件.out.
静态库
-
静态库是一系列的目标文件(.o文件)的归档文件((lib+name).a文 件);链接阶段,选择静态库,后缀名为“.a”;选择动态库,后缀名为“.so”。
-
静态链接库的生成:
gcc -c 文件名.c ar rcsv libxxx.a xxx.o
-
静态库的使用:
gcc -o 文件名 文件名.c -L. -lxxx //链接到静态库
注意
:-L
:在库文件的搜索路径列表中添加dir目录
-l
: 在头文件的搜索路径列表中添加dir目录
共享库
- 共享库的生成
gcc -fPIC -c xxx.c
gcc -shared -o libxxx.so xxx.o
-
共享库的使用:
gcc -o main main.c -L. -lxxx
-
注册共享库的方法
将库文件直接复制到/lib或者/usr/lib目录下:
cp (lib+name).so /lib
gdb调试器:调试代码
-
使用流程
查看文件:
l
设置断点:在b
后加入相对应的行号。例b 6
查看断点情况:设置完断点后键入info b
,在gdb
中可以设置多个断点。bt
查询调用函数的情况。
运行代码:默认从首行开始运行代码,键入r
;r+行号
:从该行号开始运行 查看变量值:p
变量。例:p n
单步运行:n
或s
,s
会进入函数,n
不会进入函数
恢复程序运行:c
注意:程序的运行状态有“运行”、“暂停”、“停止“三种。 -
断点的设置
函数:b 文件名.c:函数名
行:b 行数
条件:b 行数 if 表达式(b 8 if == 10)
临时:tb [文件名:]行号或函数名 <条件表达式>
make项目管理器
-
功能 :识别文件代码是否更新,减少编译工作量
makefile文件的编写规则
- 格式为:
目标体:依赖文件
[tab键]各目标体运行命令
-
目标体:
由make创建,通常是目标文件或可执行文件
-
依赖文件:
创建目标体所依赖的文件
-
运行命令:
创建每个目标体时需要的运行命令,必须以tab键开头。
-
使用make的格式:
make 目标体
makefile变量的定义
-
递归展开方式:在引用该变量时进行替换(不能用于引用自己的情况),缺点:不能在变量后追加内容。
格式定义:VAR = var
-
非递归展开方式:在定义处展开,并只展开一次。优点:消除变量的嵌套引用。
格式定义:VAR := var
-
make中变量的使用格式: $(变量名)
变量名的命名:不包括“:”、“#”、“=”以及结尾空格的任何字符串;变量名大小写不敏感。
-
变量分类:
用户自定义变量、预定义变量、自动变量及环境变量。
makefile规则
- 隐含规则
-
模式规则
三、教材知识回顾
第一章
-
信息就是位+上下文
-
计算机系统的核心是高速缓存的概念,一层存储器是低一层存储器的高速缓存。
-
操作系统中的抽象是进程、文件、虚拟存储器、虚拟机。
第二章
-
数字的三种表示 :无符号数、有符号数、浮点数
-
进制转化
x=2^n转化为十六进制
将x写成x=2n的形式,令n=i+4j,x的十六进制表示为:开头为2i的值,后面补j个0。
-
字和字节顺序
字长:一个字长指明整数和指针数据的标称大小。字长决定最重要的系统参数就是虚拟地址空间的最大大小。对一个字长为w位的机器而言,虚拟地址的范围是0~2w-1,程序最多访问2w个字节。
对于跨越多字节的程序对象需建立两个规则:
- 小端法:高对高,低对低
- 大端法:从视觉上,是这次阅读的顺序,与小端法相反。
使字节顺序变得可见的三种方式:
- 不同类型的机器之间通过网络传送二进制数据时,网络应用程序的代码编写必须遵守已建立的关于字节顺序的规则;
- 使用反汇编器,处理整数数据的字节序列的存储字节顺序问题;
- 当编写规避正常的类型系统的程序时。
-
布尔代数
- 位向量的运算:按位运算
-
位向量的应用:表示有限集合
掩码表示的是设置为有效信号的集合。
-
位级运算
|:或
&:与
~:取反
^:异或
- 掩码运算:掩码是一个位模式,表示从一个字中选出的位的集合。例如:位级运算x&0xFF生成一个有x的最低有效字节组成的值。
-
逻辑运算
逻辑运算符:||(或)、&&(与)、!(非)
-
移位运算 右移包括:逻辑右移、算数右移
- 逻辑右移:左端补k个0(常用于无符号数)
-
算数右移:左端补k个最高有效位的值(用于有符号数)
-
补码编码
补码形式是最常见的有符号数的计算机表示方式 将字的最高有效位解释为负权 B2T(W)函数为:B2T(x) = -x(w-1)2(w-1)+∑xi2i(求和从i=0到i=w-2)
-
有符号数和无符号数之间的转换
负数和正数相等的情况:u=2147483648 =-2147483648
(当输出分别为无符号形式和有符号形式时) -
扩展数的位表示
零扩展:将无符号数转换为更大的数在表示的开头添加0
符号扩展:将一个补码数字转换为一个更大的数据类型 -
截断数字
截断数字:不用额外的位来扩展一个数值,而是减少表示一个数字的位数。
注:补码经过截断处理后的结果仍是补码,注意结果为负数时转化为十进制数
-
使用无符号数的情况
把字仅仅看做是位的集合,并没有任何数字意义时
当实现模运算和多精度运算的数学包时,数字是由数的数组来表示的,无符号值也会非常有用。
-
整数运算
- 无符号加法
-
补码加法
-
补码的非
-
无符号乘法
两个数x、y相乘且x、y的位数为w,则结果的位数为2w。
-
补码乘法
同无符号乘法。 若为截断后的结果,则取结果的后w位作为计算结果。 注意:无符号运算和补码运算在“+”、“-”、“”在位级上有相同的结果。
-
乘以常数
对于某个常数K的表达式xK生成代码,编译器会将K的二进制表示表达为一组0或1的交替的序列: [(0…0)(1…1)(0…0)…(1…1)] 可以用以下两种形式来计算这些乘积的结果:
A:(x<<n)+(x<<n-1)+……+(x<<m)
B:(x<<n+1)-(x<<m)注意:
- 对于n为最高位的情况,B:-(x<<m)
- (x<<0)的结果是x,而不是0
-
除以2的幂
设x/K,令K=2^n,
当x为正数时,计算 x>>n;
当x为负数时,将x加上偏置量,即加上2^n-1(即K-1),计算** (x+偏置量)>>n** -
浮点数
-
二进制小数
- 将十进制小数转换为二进制小数
- 首先,将十进制小数写成分数的形式,将分数的分子部分,写成二进制的形式;将分数的分母部分写成2^n的形式,将分子的二进制形式,从右往左数,数n位添加小数点。
- 小数点左移:除以2
- 小数点右移:乘以2
-
IEEE浮点数表示
-
表示形式为:V = (-1)^s * M * 2^E
-
符号:s符号位。
-
尾数:M是一个二进制小数,它的范围是1 ~ 2-ε,或者是0 ~ 1-ε。
-
阶码:E的作用是对浮点数据加权,这个权重是2的E次幂(可能是负数)。
-
根据阶码的值,可分为一下三种情况:
-
情况一:规格化的值 (当阶码字段不全为0或全为1时)
E = e-Bias
Bias = 2^(k-1)-1
M = 1+f
-
情况二:非规格化的值 (当阶码字段全为0时)
E = 1-Bias
Bias = 2^(k-1)-1
M = f
-
情况三:特殊值 (当阶码字段全为1时)
当小数域全为0时, 当s=1时,为-∞;当s=0时,为+∞。
当小数域不全为0时,为NaN。
-
-
浮点数的舍入
有四种情况分别是:向偶数舍入(默认)、向零舍入、向下舍入、向上舍入。
-
浮点运算
浮点加法:不满足结合性、满足单调性
浮点乘法:不满足结合性、满足单调性,在加法上不满足分配性
-
第三章
-
反汇编命令
objdump -d xxx.o
-
执行汇编命令:
gcc –s xxx.c –o xxx.s
-
64位处理器得到32代码的命令:
gcc –m32 –s xxx.c
-
三种操作数:
立即数
寄存器
存储器
-
条件码 :
CF:进位标志
ZF:零标志
SF:符号标志
OF:溢出标志
-
jump
指令:直接跳转——后面跟标号作为跳转目标; 间接跳转——*后面跟一个操作数指示符
-
传送指令包括:
数据传送指令和条件传送指令
-
call
指令的效果是将返回地址入栈。并跳转到被调用过程的起始处。 -
ret
指令返回到call
指令后的那条指令 -
leave
指令可以使栈做好返回的准备 等价于:movl %ebp,%esp ; popl %ebp
第四章
-
指令体系结构:
一个处理器支持的指令和指令的字节级编码
-
程序员可见状态:
8个寄存器状态、程序计数器PC。
-
指令集的一个重要性质:
字节编码必须有唯一的解释。
-
Y86异常:
状态码1,AOK,程序正常
状态码2,HLT,处理处执行halt指令
状态码3,ADR,非法地址
状态码4,INS,非法指令
-
创建Y86代码的唯一工具是汇编器 ;YIS:指令集模拟器
-
pushl
指令会把栈指针减4,并且将一个寄存器值写入存储器中。 -
nop
指令:除了将PC加1,不进行任何处理;halt
指令:将处理器状态设置为HLT,导致处理器停止运行。 -
“cond”硬件单元会根据条件码和功能码来确定是否进行条件分支或者条件数据传送。
第六章
-
随机访问存储器分为:
静态的SRAM
动态的DRAM
-
根据携带信号不同,总线可分为数据总线、地址总线、控制总线。
-
计算磁盘容量的公式:
-
访问时间=寻道时间+旋转时间+传送时间
-
最大旋转延迟=1/RPM X 60secs/1min (s) ;平均旋转时间是最大旋转时间的一半
-
平均传送时间= 1/RPM x 1/(平均扇区数/磁道) x 60s/1min
-
逻辑磁盘块三元组(盘面,磁道,扇区):唯一地标示了对应的物理扇区
-
CPU使用一种称为存储器映射I/O的技术来向I/O设备发出命令。
-
局部性包括时间局部性和空间局部性。
-
循环有好的时间和空间局部性
-
高速缓存:上一层做下一层的高速缓存
-
高速缓存参数的性能影响
缓存大小的影响
块大小的影响
相联度的影响
写策略的影响
第七章
-
c语言程序执行的过程涉及的工具:
c预处理器(cpp)
编译器(cc1)
汇编器(as)
链接器程序(ld)
-
链接器的任务:
符号解析、重定位
-
目标文件的三种形式:
可重定位目标文件
可执行目标文件
共享目标文件
-
目标文件的格式:
a.out、COFF、DE、ELF
-
链接器上下文的三种符号:全局符号、外部符号、本地符号
四、相关考题回顾
第一周
填空:在 Linux 里面可以使用使用(chmod)命令修改文件的权限。
填空:Linux中没有C盘,D盘,其文件系统的目录是由(FHS)标准规定好的。
判断:Linux Bash中,使用tar命令把home目录打包成home.tar的命令是( tar -cf home.tar ~)
填空:Linux Bash中,zip命令使用(-e)参数可以创建加密压缩包。
填空:Linux Bash中,把ls命令显示当前目录的结果存入ls.txt的命令输出重定向命令是(ls > ls.txt)
第二周
选择:教材p449中 swap.c中的buffp1 是在(C) A .text段 B.data段 C.bss段 .symtab段
判断:gcc –c hello.c 产生的hello.o是可重定位目标文件。(ok)
填空:CPU中的(PC或程序计数器)寄存器总指向主存中的某条机器语言指令。
填空:(加载器)将可执行文件的内容映射到存储器,并运行这个程序。
写出编译上面代码的makefile,编译出来的目标文件为testhello, 只用显式规则就可以.(3分),一条一分
testhello: main.o hello.o
gcc main.o hello.o -o testhello
main.o: main.c hello.h
gcc -c main.c
hello.o: hello.c hello.h
gcc -c hello.c
第三周
填空:fun1(0xED005380) = ( 0x00000080 ,0x80都行 )
填空:对于四位数补码0xC,其补码的非表示为十进制为( 4 )
判断:“高对高,低对低”的机器是大端机器。(X)
填空:(Shannon 或香农)建立了布尔代数和数字逻辑之间的联系。
填空:练习2.6中整数换成12345,浮点数换成12345.0,最多时共(13)位匹配。
第五周
填空:Ubuntu中新建一个叫 lilei 的用户的命令是(sudo adduser lilei)
填空:(精通细节 )是理解更深和更基本概念的先决条件。
填空:两个寄存器(%ebp和%esp)保存着指向程序栈中重要位置的指针。
填空: 指令leal 8(%ecx,%eax,2), %edx 存储在%edx中的值为( 8+2x+y )
填空: jz/jnz指令中跳转条件是由(ZF)决定的。
第六周
Y86中 rrmovl %eax, %ecx 对应的机器码是( 2001 )
判断:Y86中,状态码INS表示遇到非法地址。( X )
填空:位级与非门的HCL表达式是( bool Y = !(A&&B) )
填空:bool s= r1 || r2 || r=5 等价于(bool s = r in {1,2,5} )
判断:Y86中rrmovl指令没有访存操作。(OK)
第七周
填空:计算磁盘容量( 81.92GB 或8192000000字节 ):2个盘片,100000个柱面,每条磁道400个扇区,每个扇区512个字节。
填空:对磁盘扇区的访问时间包括三个部分中,(传送时间)最小。
判断:P403两个程序功能等价,性能上不同。( ok )
填空:程序员可以编写(有良好空间和时间局部性)的程序来显著改进程序的运行时间。
五、收获与不足
收获:
-
课本学习
《深入了解计算机系统》带来了不一样的阅读体验:
对于整个计算机系统的生动描述
对于计算机系统中每一个部分细致的描述
对于计算机系统运行原理的清楚展示
总而言之《深入了解计算机系统》给人带来的阅读体验是与其他一些计算机相关书籍所不一样的(如:计算机组成与设计:硬件和/软件接口)。确实很切合书本的小标题:A Programmer‘s Perspective ,作为一名学习过汇编语言、C语言、C++、Java的大三学生在学习本书之前也并没真正深入了解到计算机系统的运行原理。阅读本书之前的问题就在于:
会编程序,但却不了解程序是如何在计算机上跑起来的
本书已经学习了一半,引用知乎上一位用户在问题:《深入理解计算机系统》这本书需要什么水平能看懂?下的回答:
读不完,读不懂,没关系,完全可以暂时放一放。这不是一本一下子就能完全读懂读透的书,希望你不断地学习,不断的去读。这样或许是读这本书的最好状态。
说实话,有时我觉得读书这东西充满了悖论,懂的东西你不用去读,不懂的东西才需要去读,但是不懂的话能读的明白吗?特别是有些东西是超越生活实践经验的,在平时你可能根本接触不到CPU、内存等等这些的构造,你编起程序来也根本从不用考虑编译器是怎么工作的,但是现在突然要告诉你这些东西的原理、构造,很难想象,也很难接受,这些都正常。不过说实话,以我的经验来看,越是难以读懂的书,恰恰正是说明你知识的短板,读懂后回报很大,所以加油。
人的提高,把不懂的书读懂就是一个很重要的途径,有时甚至是唯一的途径,这是读书的中心所在,也是你思考的所在,祝好。作者:王群链接:https://www.zhihu.com/question/20354069/answer/17206238来源:知乎著作权归作者所有,转载请联系作者获得授权。
-
博客学习
博客学习一如往常,每周一篇的博客仍然是巩固知识的最好方式。阅读娄老师和同学们的博客还是反思自我和汲取知识的最佳途径。
通过连续不间断地写博客,知识的体系形成的很快也很牢固。
很像在其他课程上也用博客的方式来总结知识,但不知道是自己的方法问题还是其他问题,没能有足够的时间。
不足:
- 在写第七周博客查阅资料的过程中,看到了娄老师曾经提出的“估算学习时间”与”实际学习时间“的对比(参见http://www.cnblogs.com/java-stx/p/4899314.html)了解到了自己在将计划转换为实际的学习成果上还存在一定的问题,在今后的学习中努力做到计划转换为实际的效率能够得到进一步的提升。
- 自己在学习效率上仍然有很大的提升空间,压榨自我应该是后期学习的主旋律。
- 学习过程中太过于注重学习的结果,想着这个东西一定要做出来,但一旦任务完成之后,就会全身心地放松。反思就整个学习过程中并不存在了。
最后,希望自己有一天能够真正踏实地通过阅读本书,透彻地了解整个计算机系统。
路漫漫其修远兮,吾将上下而求索
六、课程建议与意见
- 博客学习依然成为学习中不可或缺的一种方式,但是一周学习的知识量大且杂,希望以后可以将一周博客分为两个部分,最后再在周末完成的博客中进行总结。
七、代码托管
学习进度条
代码行数(新增/累积) | 博客量(新增/累积) | 学习时间(新增/累积) | 重要成长 | |
---|---|---|---|---|
目标 | 5000行 | 30篇 | 400小时 | |
第一周 | 0/0 | 1/2 | 15/30 | |
第二周 | 56/56 | 2/3 | 15/45 | |
第三周 | 89/145 | 1/4 | 20/65 | |
第五周 | 500/645 | 1/6 | 20/85 | |
第六周 | 150/795 | 1/7 | 20/105 | |
第七周 | 124/919 | 1/8 | 15/120 | |
第八周 | 0/919 | 1/9 | 15/135 |
参考资料
1.教材:《深入理解计算机系统》