第一章 计算机系统漫游
PC :也就是程序计数器,是处理器的核心,这是仅仅具有一个字长的存储设备。从系统上电开始,直到系统断点,在任何时刻,PC都指向主存中的某条机器语言指令(即指向某个地址),处理器(CPU)一直在不断地执行PC指向的指令,然后更新PC,使其指向下一条指令。
寄存器文件:是一个小的存储设备,由一些 1字长的寄存器组成,每个寄存器有一个唯一的名字。
第二章
2.1 信息的存储
-
位:
在计算机的内部和数字设备中,所有的数据都是以二进制数表示的,即0和1的序列。位(bit )由二进制数字(binary digit)而来。每个二进制位只能表示两种状态:0和1。位是计算机中最小的数据单位,一般用逻辑器件的一种状态来表示,例如“断开”或“闭合”。
-
字节:
是计算机数据处理的基本单位。1个字节由8个二进制位组成,也就是由两个16进制位组成,通常我们写地址都是按照16进制来写,如一个int类型的变量 a 的值为 0x01234567,这个就是用16进制表示的,所以在存储的时候,就需要每两个数字组成一个整体,也就是作为 1 个字节。所以变量 a 的字节有4个,分别是: 01、23、45、67,注意01是最高有效位,67是最低有效位。
-
字 & 字长:
在计算机中,一串数码是作为一个整体来处理或运算的,称为一个计算机字,简称字(word),一个字通常由一个或多个字节构成。计算机的每个字所包含的位数称为字长。接着上面的例子 变量a 来分析,一个 int 类型占了 4 个字节,那么这4个字节如何在计算机中进行存储呢?这里就产生了一种歧义。不同的处理器(CPU)可能会采用不同的方式,可以分为大端法或者小端法。变量 a 需要4个字节来进行存储,假设分配的4个地址分别是 0x100,0x101,0x102,0x103。
对地址来说,前面的,也就是数值比较小的地址属于低位地址,数值比较大的地址属于高位地址。
对于变量 a 来说,前面的,也就是比如 01 这个字节,对应的是最高有效位,后面的,也就是67是最低有效位。
所谓大端法:就是将最高有效字节放在最低位,地址的增长顺序与值的增长顺序相反
所谓小端法:就是将最高有效字节放在最高位,地址的增长顺序与值的增长顺序相同
第三章 程序的机器级表示
gcc 指令指的就是 GCC C 编译器,Linux 系统上默认的编译器就是这个
第7章 链接
链接器 | 把程序的各个部分联合成一个文件 |
处理器CPU | 将这个文件加载到内存,并且执行它 |
目标文件是对程序二进制代码和数据的组织,
- 贝尔实验室第一个Unix系统使用a.out格式
- windows使用可移植可执行的PE格式(如最常见的可执行程序.exe格式)
- Linux中使用的是ELF (executable and linkable format)格式。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-c9jctkum-1624204736922)(C:\Users\lh\AppData\Roaming\Typora\typora-user-images\image-20210619151501627.png)]
1、编译过程
将编译过程分开来查看
[root@linuxprobe link]# gcc -E main.c -o main.i // 预处理(也叫预编译)
[root@linuxprobe link]# cpp main.c > main.i // 预处理(也叫预编译)
[root@linuxprobe link]# gcc -S main.i -o main.s // 编译
[root@linuxprobe link]# gcc -c main.s -o main.o // 汇编
gcc -c main.c 可以直接编译 main.c 程序生成 main.o 可执行文件
[root@linuxprobe link]# objdump -h main.o // 查看生成的main.o文件的结构
[root@linuxprobe link]# readelf -S main.o // 查看段表(主要为了查看每个段的段号)
[root@linuxprobe link]# readelf -s main.o // 查看符号表(我们定义的变量名都是符号,包括函数名)
第8章 异常控制流
8.1 异常
类别
- 中断
- 陷阱
- 故障
- 终止
8.2 进程
概念:一个执行中程序的实例
8.3 系统调用错误处理
8.4 进程控制
第9章 虚拟内存
虚拟·内存·提供了·三个重要的能力:
- 1)他将主存看成是一个存储在磁盘上的地址空间的高速缓存,在主存中只保存活动区域,并根据需要在磁盘和内存之间来回传输数据,通过这种方式,它高效的使用了主存
- 2)他为每个进程提供了一致的地址空间,从而简化了内存管理
- 3)他保护了每个进程的地址空间不被其他进程破坏
第10章 系统级IO
第11章 网络编程
Q1:怎么把本机的文件转到虚拟机下的linux系统中
- 方式一:把待移动文件,直接从本机拖拽到 crt 的命令窗口即可,选择最后一种zmodem方式,注意拖拽所在的目录,即为文件在linux系统中的目录
- 方式二:直接在linux系统下,用 wget 指令进行下载,要有下载的链接
Q2: linux 根目录与家目录的区别:
- ~ 代表是home目录,也就是家目录, / 代表的是根目录
- 用户登录后在 家目录 ,可用pwd命令查看,
- 普通用户为 /home/用户名
- root用户为 /root
- 根目录是在最顶端的目录(因为已经不能cd …到上一级目录了 )
- 根目录是所有用户的都可以操作的,家目录用户才有权限操作(管理员可以分配权限)
Q3:主机名、IP地址、域名
- point
- DNS 域名系统,实现了主机名和IP地址一一对应的映射关系
- 主机名
- 小范围(也就是局域网范围内)的唯一标识,在同一个局域网中不同的主机主机名一定是不同的。
- 查看主机名 [root@linuxprobe ~]# hodtname -i
- 主机名可以是像IP地址的形式,也可以是字母组成的便于记忆的名字
- IP地址
- 互联网络中的的唯一标识。
- 查看 IP 地址 ifconfig
- SecureCRT 连接的是IP地址
- 注意在SecureCRT的命令窗口中查询的IP和在linux系统下查询的IP是相同的
- 同一个虚拟机下运行的不同操作系统查询的IP也是不同的
- 域名
- 一个域名对应唯一的一个IP地址,但是一个IP地址可以对应多个域名,是一对多的关系
- DNS 域名解析器就是根据这种层级关系,将IP地址与主机进行唯一的映射
Q4:SecureCRT
Q5 :下载文件
在 LInux 中如何使用深入理解计算机系统 (CSAPP) 的代码_sinat_36024346的博客-CSDN博客
使用wget下载单个文件:
[root@linuxcool ~]# wget http://www.Linuxcool.com/testfile.zip
Q6:编译执行 csapp 中的某个 .c 文件
对于本书中的 csapp.c 和 csapp.h 两个文件,
因为 csapp.c 中包含线程的一部分,所以编译的时候一定要加上 -lpthread 选项
例: gcc forkprob6.c -lpthread
Q7:环境变量
-
环境变量(environment variables)一般是指在操作系统中用来指定操作系统运行环境的一些参数 。
-
如:我们在编写C/C++代码的时候,在链接的时候,从来不知道我们的所链接的动态静态库在哪里,但是照样可以链接成功,生成可执行程序,原因就是有相关环境变量帮助编译器进行查找。
-
环境变量通常具有某些特殊用途,还有在系统当中通常具有全局特性 。
常见的环境变量
PATH:指定的命令的搜索路径
HOME:指定用户的主工作目录
SHELL:当前的 shell,它的值通常是 /bin/bash
和环境变量相关的命令
echo:显示某个环境变量值
export:设置一个新的环境变量
env:显示所有的环境变量
unset:清除环境变量
set:显示本地定义的shell变量和环境变量
Q8:在Linux下编译执行一个C++工程的两种方式
- 方式一:在windows下的IDE编辑完成整个项目,然后转到Linux系统下编译执行
- 方式二:在Linux系统下,建立一个目录,里面存放相关的 .cpp 以及 .h 文件,除此之外还需要一个 单独的 makefile 文件,用来存放 编辑的指令,这样最后执行make指令就可以生成可执行文件,并看到最终的结果了 Linux下使用make构建一个C++工程项目_哈工大许政的博客-CSDN博客
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jtdmF0E3-1624204736924)(C:\Users\lh\AppData\Roaming\Typora\typora-user-images\image-20210619151250752.png)]
2、Linux系统下 我的第一个.c文件的运行
- 第1步:gcc main.c 执行这个指令,后面的文件名,注意要写明后缀为.c,会生成一个 a.out 可执行文件
- 第2步: ./a.out 执行刚才生成的可执行文件,注意前面有个小数点,表示在当前目录下。
web server
1、目前遇到过的可执行文件可能的情况:
./a.out
app
main.o
2、 ./a.out 文件中有什么?
a.out文件就是扩展名为out的文件,它本身不代表任何信息。
在Linux中判断文件是否是可执行文件,首先要看文件的属性是否是可执行的,它没有一个默认的扩展名表示此文件为可执行文件。
为了方便,Linux中可执行文件一般都是没有扩展名的。
在使用gcc编程时,没有指定输入可执行文件名,默认生成可执行文件a.out文件。执行时必须键入命令 ./a.out,即要带上扩展名,如果键入./a 则不正确,因为它寻找a这个文件,而不是a.out这个文件。
3、加载
在shell中输入 ./a.out 就是运行了一个可执行目标文件
然后就是通过调研某个存储器中称为 加载器的 操作系统代码来运行它
任何 Linux 程序都可以通过调用 execve 函数来调用加载器
加载器将可执行目标文件中的代码和数据从磁盘复制到内存中,然后通过跳转到程序的第一条指令或入口点来运行该
将程序复制到内存并运行的过程叫做加载
4.1 测试程序 adder 的实现
参考csapp 11.5.4(p669)
CGI 通用网关接口
使用 tiny web 实现一个两个数字相加
[root@linuxprobe tiny]# gcc tiny.c -lpthread // 在 netp/tiny 目录下,编译生成tiny可执行文件 a.out
[root@linuxprobe tiny]# gcc -o adder adder.c -lpthread // 进入cgi-bin目录下,编译生成adder可执行文件
[root@linuxprobe tiny]# ./a.out 1024 // // 在 netp/tiny 目录下,执行可执行文件 a.out 后面加上端口号
注册端口( Registered Ports ):从 1024 到 49151,因为前面的端口都是知名端口
这里我选了 1024
此时在主机上的浏览器内输入:http://localhost:1024/cgi-bin/adder?17&39
其中2000是通信端口,adder?17&39表示向 adder 函数提供 参数17和39,问号分割了文件名和参数,参数直接用 & 作为区别
/*
* adder.c - a minimal CGI program that adds two numbers together
*/
/* $begin adder */
#include "csapp.h"
int main(void) {
char *buf, *p;
char arg1[MAXLINE], arg2[MAXLINE], content[MAXLINE];
int n1=0, n2=0;
/* Extract the two arguments */
if ((buf = getenv("QUERY_STRING")) != NULL) {
p = strchr(buf, '&');
*p = '\0';
strcpy(arg1, buf);
strcpy(arg2, p+1);
n1 = atoi(arg1);
n2 = atoi(arg2);
}
/* Make the response body */
sprintf(content, "Welcome to add.com: ");
sprintf(content, "%sTHE Internet addition portal.\r\n<p>", content);
sprintf(content, "%sThe answer is: %d + %d = %d\r\n<p>",
content, n1, n2, n1 + n2);
sprintf(content, "%sThanks for visiting!\r\n", content);
/* Generate the HTTP response */
printf("Content-length: %d\r\n", (int)strlen(content));
printf("Content-type: text/html\r\n\r\n");
printf("%s", content);
fflush(stdout);
exit(0);
}
/* $end adder */
服务器端显示
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nXUee05e-1624204736928)(C:\Users\lh\AppData\Roaming\Typora\typora-user-images\image-20210620155701091.png)]
搭建完成,欧耶!
4.2 访问静态网页 home.html
知识储备:
csapp 11.5.1 web 基础
csapp 11.5.2 web 内容
注意:需要将被访问的网页文件编辑好放在 tiny 的同级文件下,在建立连接后就可以成功访问啦~
// 网页内容
<html>
<head>
<title>Hello World</title>
</head>
<body>
<h1>Welcome to Tiny Web Server</h1>
</body>
</html>
客户端web和服务器端的显示结果:
4.3 访问图片
知识储备:
csapp 11.5.1 web 基础
csapp 11.5.2 web 内容
同上:将被访问的图片直接放在 tiny 的同级文件下,在建立连接后就可以成功访问啦~
4.4 telnet 测试
知识储备:
参考csapp 11.5.3(P667)
介绍了一个详细的 http 请求事务
请求
响应
1、用 shell 终端打开 tiny server
[root@linuxprobe tiny]# ./a.out 1025
2、用 SecureCRT 终端进行连接
[root@linuxprobe tiny]# telnet localhost 1025
Trying ::1...
telnet: connect to address ::1: Connection refused
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
3、输入第1行和第2行的请求报头,注意第2行空行是不能少的,这是请求头的结束标志,后面的3-16行是输出结果
1* GET /home.html HTTP/1.0
2*
3* HTTP/1.0 200 OK
4* Server: Tiny Web Server
5* Content-length: 108
6* Content-type: text/html
7*
8* <html>
9* <head>
10* <title>Hello World</title>
11* </head>
12* <body>
13* <h1>Welcome to Tiny Web Server</h1>
14* </body>
15* </html>
16* Connection closed by foreign host.
4.5 代码说明
1、这里解释了我一开始的疑惑
parse_uri 函数是uri解析函数
tiny 默认静态内容的主目录就是它的当前目录,而可执行文件的主目录是./cgi_bin
任何包含字符串cgi-bin的url都会被认为表示为对动态内容的请求。
默认的静态文件名为 ./home.html.依据uri中是否含有cgi-bin来推断请求的是静态内容还是动态内容。假设没有cgi-bin。则说明请求的是静态内容。
uri中含有cgi-bin。则说明请求的是动态内容。那么,我们须要把参数复制到cgiargs中,把要运行的文件路径写入