阅读笔记之——深入理解计算机系统

第一章 计算机系统漫游

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 根目录与家目录的区别:

  1. ~ 代表是home目录,也就是家目录, / 代表的是根目录
  2. 用户登录后在 家目录 ,可用pwd命令查看,
    1. 普通用户为 /home/用户名
    2. root用户为 /root
  3. 根目录是在最顶端的目录(因为已经不能cd …到上一级目录了 )
  4. 根目录是所有用户的都可以操作的,家目录用户才有权限操作(管理员可以分配权限)

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 */
image-20210620155732498

服务器端显示

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(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和服务器端的显示结果:

image-20210620162056957 image-20210620162035972
4.3 访问图片

知识储备:

csapp 11.5.1 web 基础

csapp 11.5.2 web 内容

同上:将被访问的图片直接放在 tiny 的同级文件下,在建立连接后就可以成功访问啦~

image-20210620162700958 image-20210620162740000
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中,把要运行的文件路径写入

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值