Skip to content

Commit

Permalink
update md footnotes
Browse files Browse the repository at this point in the history
  • Loading branch information
Iolop committed Mar 12, 2024
1 parent 5d9d510 commit f259389
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 27 deletions.
45 changes: 20 additions & 25 deletions _posts/2024-03-07-cs-app读书笔记-1-计算机系统漫游.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,7 @@ tags: [读书笔记]
---
# 第一章:计算机系统漫游

计算机是一个很庞大的东西,在初次面对的时候难免束手无策,不知从何下手。我们常见的操作系统是Windows,除了它其实还有Linux、Unix、MAC、RTOS这些分类。后续的讲解,将会以Linux[^linux是什么]作为目标,但是请放心,虽然名字各不相同,但是它们的基本组成都还是保持着一致,不必担心知识迁移的问题。


计算机是一个很庞大的东西,在初次面对的时候难免束手无策,不知从何下手。我们常见的操作系统是Windows,除了它其实还有Linux、Unix、MAC、RTOS这些分类。后续的讲解,将会以Linux[^linux-for-what]作为目标,但是请放心,虽然名字各不相同,但是它们的基本组成都还是保持着一致,不必担心知识迁移的问题。

## 文件的表示

Expand Down Expand Up @@ -66,29 +64,27 @@ F: / ? O _ o DEL
接下来,我们一个个的说明这里出现的命令所代表的含义:
1. hexdump是一个命令行[^命令行是什么]工具,用来按照用户需要的格式来展示文件内容。
2. man ascii是一个用来显示关于ascii的帮助手册。你还可以使用`man hexdump`来查看关于这个命令的更多帮助。
1. hexdump是一个命令行[^cmd-for-what]工具,用来按照用户需要的格式来展示文件内容。
2. man ascii是一个用来显示关于ascii的帮助手册。你还可以使用`man hexdump`来查看关于这个命令的更多帮助。
除此外,你还可以使用hexdump去查看任意你有权限访问的文件,比如这个命令:hexdump -C \`which ls\` -n 64。请注意观察它们的区别。在右侧你不再能观察到大量的可读字符,相反,计算机同一用`.`来展示这些不可见字符。这就是我们用来区分文件的一种方式,类似`hello.c`的,我们称为文本文件。相对应的,类似`ls`这种文件的,我们称为二进制文件。
在计算机系统中,`23`代表着一个字节(byte),而每一个字节,由8个比特(bit)组成。这就是计算机内部存储数据的最基本单元。实际上,无论是磁盘文件、内存数据、可执行代码、可读文件、网络数据等等,它们本质上都只是一串比特,只不过由于我们的上下文(context)不同,我们对这些比特流/字节流产生了不同的解读方式。一个同样的字节序列,可以被解释成一个指令、一个无符号整数或者一个浮点数。
> 为什么是8bit,Google搜了一下,据说是和IBM的360系统有关。它们采用8bit,然后约定俗成。同时,我们也能从ascii表中注意到,它的大小恰好是0x80,由于计算机内部采用二进制表示,这刚好能占用8bit的空间。由于计算机的发展原因,一开始很多表示都是英文字符,所以也不需要很大的表示空间,8bit的空间就足够容纳。到现在,为了兼容多国语言表示,ascii已经不够使用,所以Unicode应运而生,不过这就是另一个故事了。有兴趣的朋友请自行搜索—UTF8。
> 为什么是8bit,Google搜了一下,据说是和IBM的360系统有关。它们采用8bit,然后约定俗成。同时,我们也能从ascii表中注意到,它的大小恰好是0x80,由于计算机内部采用二进制表示,这刚好能占用8bit的空间。由于计算机的发展原因,一开始很多表示都是英文字符,所以也不需要很大的表示空间,8bit的空间就足够容纳。到现在,为了兼容多国语言表示,ascii已经不够使用,所以Unicode应运而生,不过这就是另一个故事了。有兴趣的朋友请自行搜索—UTF8。
同时,由于计算机内部是采用了二进制的表达方式,所以注定会存在一个问题:精度。
> 计算机一定是二进制吗?这也是一个历史问题,最开始的计算机采用晶体管,我们常说二极管,其实代表它只有两个状态:开和关,这两种状态很容易区分。其实历史上苏联也有过三进制计算机。我觉得还是由于接受度的问题,二进制计算机流传至今。
> 计算机一定是二进制吗?这也是一个历史问题,最开始的计算机采用晶体管,我们常说二极管,其实代表它只有两个状态:开和关,这两种状态很容易区分。其实历史上苏联也有过三进制计算机。我觉得还是由于接受度的问题,二进制计算机流传至今。
## 程序的翻译
当我们拥有了一份源代码,它还不能马上被我们执行。在Windows中我们常通过双击一个exe文件来试图执行,而在Linux我们通常使用`./FILE_NAME`的形式来执行一个可执行文件。需要从源代码转化到可执行文件,这中间我们还有几步路需要走一下,简化一下各自的功能描述,它们分别是:
1. 预处理(cpp):将源代码展开,引入其他代码文件
2. 编译(ccl):将高级语言翻译成汇编
3. 汇编(as):将汇编语言翻译成机器指令
4. 链接、重定向(ld):解决代码中指向的问题,链接外部库
1. 预处理(cpp):将源代码展开,引入其他代码文件
2. 编译(ccl):将高级语言翻译成汇编
3. 汇编(as):将汇编语言翻译成机器指令
4. 链接、重定向(ld):解决代码中指向的问题,链接外部库
也许你曾经听到过**逆向**这个说法,至少在C语言这个层面,它代表着上述四步中倒着处理的第三步和第二步—反汇编(disassemble)和反编译(decompile)。
Expand All @@ -105,10 +101,10 @@ gcc是我们后面会经常用到的一个工具,它的全名是`GNU Compiler
在我们输入`./hello`的时候,我们实际上是按压键盘,然后电信号被翻译,触发中断,传送到CPU进行处理。随后将对应的字符再输出到屏幕。当我们按下`回车`时,`shell`知道我们结束了输入,并开始对之前的输入进行解析。寻找`hello`,将其拷贝到内存中,跳转到`main`函数,CPU开始读取指令并执行。这样说还是比较抽象,我们需要对计算机的硬件设备做一个非常简单的概括:
1. 总线(bus):负责携带信心并传送到各个部件
2. I/O设备:负责Input/Output的设备,通常代表信息的输入和输出
3. 内存(memory):通常这是一块DRAM(动态随机存储设备),断电后信息不保存。用来保存执行的程序和所需数据。
4. 处理器(CPU):用来解释指令并执行的单元。
1. 总线(bus):负责携带信心并传送到各个部件
2. I/O设备:负责Input/Output的设备,通常代表信息的输入和输出
3. 内存(memory):通常这是一块DRAM(动态随机存储设备),断电后信息不保存。用来保存执行的程序和所需数据。
4. 处理器(CPU):用来解释指令并执行的单元。
现在,我们可以再来描述下`hello`的执行过程了,通过I/O设备,CPU知道我们将会执行的文件,然后将其加载到内存上,并开始执行,在这中间,总线担任了信息传送的功能。
Expand All @@ -120,21 +116,20 @@ gcc是我们后面会经常用到的一个工具,它的全名是`GNU Compiler
抽象是一个很有力的概念,我们可以把它理解成一个封装,用户不需要关心内部的实现,只需要知道,这个封装对外提供了什么接口以供使用,并且这个使用效果是什么即可。比如OS中的文件系统(file system),每一个文件系统的细节(squash fs\ext4\ext3\ramfs\sysfs\procfs……)都不同,但是我们可以通过同样的`read`,`write`来操作。
> 如果你想查看一下自己目前使用了多少文件系统,mount命令可以让你一窥。
> 如果你想查看一下自己目前使用了多少文件系统,mount命令可以让你一窥。
在操作系统中,我们有以下比较高级的抽象概念:
1. 进程/线程:这是os对运行中的程序一种抽象。其中线程是对进程的进一步划分,一种更小的执行单元。
2. 虚拟内存:对进程系统的一种抽象,看起来拥有完整的内存可用权。
3. 文件:最重要的一种抽象,我们常说Linux中的一切都是文件,或许就来源于此。不仅仅是前面的文件文件,甚至I/O设备、磁盘、进程状态信息(procfs)、系统本身信息(sysfs)、网络接口都可以被看成文件。
1. 进程/线程:这是os对运行中的程序一种抽象。其中线程是对进程的进一步划分,一种更小的执行单元。
2. 虚拟内存:对进程系统的一种抽象,看起来拥有完整的内存可用权。
3. 文件:最重要的一种抽象,我们常说Linux中的一切都是文件,或许就来源于此。不仅仅是前面的文件文件,甚至I/O设备、磁盘、进程状态信息(procfs)、系统本身信息(sysfs)、网络接口都可以被看成文件。
在此之上,系统之间通过网络进行通信,它们互相交换数据,才发展到我们现在的互联网。
本书第一章内容非常丰富,概括性的快速带我们走过了计算机,并介绍了其中的关键性质和定义。这里仅仅是我阅读后的小部分理解,有兴趣的朋友可以自己阅读第一章,加深了解。
[^linux是什么]: 请参考 https://linux.do/t/topic/17577/130,并持续催更。
## 参考链接
[^命令行是什么]: 参考 https://zh.wikipedia.org/wiki/%E5%91%BD%E4%BB%A4%E8%A1%8C%E7%95%8C%E9%9D%A2
[^linux-for-what]: 请参考 <https://linux.do/t/topic/17577/130>,并持续催更。
[^cmd-for-what]: 参考 <https://zh.wikipedia.org/wiki/%E5%91%BD%E4%BB%A4%E8%A1%8C%E7%95%8C%E9%9D%A2>
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ struct string{

### 代码的表示

代码意味着一串可以被CPU理解并执行的字节序列。这里就有一个概念出现了—**ABI(Application Binary Interface)**[^ABI是什么]。也许你听说过API。各个系统的ABI一般来说都是不兼容的,这也意味着你在Windows上的应用程序是没法直接在Linux上运行的,你在MAC上的安装包dmg,在Windows和Linux上也难以使用。之前我看到有坛友问,Linux上的unistd.h能在Windows上使用吗,很遗憾这是不可能的。
代码意味着一串可以被CPU理解并执行的字节序列。这里就有一个概念出现了—**ABI(Application Binary Interface)**[^ABI-for-what]。也许你听说过API。各个系统的ABI一般来说都是不兼容的,这也意味着你在Windows上的应用程序是没法直接在Linux上运行的,你在MAC上的安装包dmg,在Windows和Linux上也难以使用。之前我看到有坛友问,Linux上的unistd.h能在Windows上使用吗,很遗憾这是不可能的。

### 一些简单的操作

Expand Down Expand Up @@ -216,5 +216,6 @@ exp位全部为1。frac字段为全0时,表示无穷$$\infty$$。frac不为0
由于非规格化使用了$$E=1-Bias,M=f$$,我们在最大地非规格化和最小地规格化之间平滑过渡。
## 参考链接
[^ABI是什么]: 请参考此链接 https://zhuanlan.zhihu.com/p/386106883
[^ABI-for-what]: ABI的简单说明 <https://zhuanlan.zhihu.com/p/386106883>

0 comments on commit f259389

Please sign in to comment.