CSAPP:第一章——计算机系统漫游

一、信息,就是位+上下文

计算机系统中的所有信息——包括磁盘文件、内存中的程序、内存中存放的用户数据以及网络上传送的数据,都是由一串比特序列(也可以说是字节序列,一个字节八个位,即八比特)表示的。区分不同数据对象的唯一方法是我们读到这些数据对象时的上下文。比如,在不同的上下文中,一个同样的字节序列可能表示一个整数、浮点数、字符串或者机器指令。

// 文件名:hello.c
#include <stdio.h>

int main() {
	printf("hello,world!\n");
	return 0;
}

上面源程序hello.c,以文本文件的形式被我们所看到,但是计算机中无法存放字符,只能存放0和1,而0和1只表示数字,所以大佬们就制定了一种全世界统一的标准,比如ASCII编码(或者其他编码),用一个数字代表、且只能代表一个字符。所以文本文件实际上在磁盘和内存中是以二进制的形式存放的,根据ASCII编码标准,每个字符都有特定且唯一的数值来表示。hello.c对应ASCII编码如下:
在这里插入图片描述
i字符对应的十进制数值是105,则在计算机中,i字符是以105的二进制数1101001存放的。根据区分计算机中不同数据对象的唯一方法——读到这些数据对象时的上下文可明白,当计算机中的比特序列1101001表示字符时,它就是字符i,当1101001表示无符号整数时,他就是105

二、程序被编译成不同的格式

hello.c程序的生命周期是从一个高级C语言程序开始的,因为这种形式能够被人读懂。然而为了在系统上运行hello.c程序,每条C语句都必须被其他程序转化为一系列的低级机器语言指令。然后这些指令按照一种称为可执行目标程序的格式打包好,并以二进制磁盘文件的形式存放起来。目标程序也称为可执行目标文件。
在这里插入图片描述
上面编译系统的整个过程,在编译器结构中详细介绍过。

三、处理器读并解释存储在内存中的指令

1.系统硬件的组成

总线:贯穿整个系统的一组电子管道,称做总线,他携带信息字节并负责在各个部件间传递。总线被设计成传送定长的字节块,即字(word),字的字长由机器的位数决定,4字节(32位)还是8字节(64位)。

I/O设备:键盘,鼠标,显示器,磁盘等。

  • 每个I/O设备通过一个控制器或适配器与I/O总线相连。控制器和适配器的区别在于他们的封装方式:控制器是置于I/O设备本身的或者系统的主板上的芯片组;适配器则是一块插在主板插槽上的卡。
  • 两者功能都是在I/O总线和I/O设备之间传递信息。

主存:是一个临时存储设备,在处理器执行时,存放程序和程序处理的数据。

  • 从物理上来说:由一组动态随机存取存储器(DRAM)组成。
  • 从逻辑上来说:线性的字节数组,每个字节都有其唯一的地址(数组索引),这些地址是从零开始的。

处理器:解释(或执行)存储在主存中指令的引擎。处理器的核心是一个字长的存储设备或寄存器,称为程序计数器(PC,就是CS:IP)。在任何时刻,程序计数器都指向主存中的某条机器语言指令(也就是PC中存放着该条指令的地址)。
从通电到断电,处理器一直在不断地从PC指向的内存中读取指令,解释指令中的位,执行该指令提示的简单操作(加载、存储、ALU运算、跳转),然后更新PC,使其指向下一条指令,而这条指令并不一定和在内存中刚执行完的指令相邻。

在这里插入图片描述

2.运行hello程序

直接存储器存取(DMA)技术:数据可以不通过处理器而直接从磁盘到达主存。
在这里插入图片描述
在这里插入图片描述

四、高速缓存

hello程序的机器指令最初放在磁盘上,程序加载时,被复制到主存,处理器运行程序时,指令又从主存复制到处理器。

程序运行时,系统需花费大量的时间把信息从一个地方挪到另一个地方,但是主存和处理器之间的读取速率相差太大,主存拖后腿,增加额外的时间开销。所以系统设计者为了尽可能快的完成这一操作,搞了高速缓存这么个玩意,作为暂时的集结区域,用来存放处理器近期可能用到的信息。
在这里插入图片描述

五、存储设备层次结构

存储器层次结构的主要思想是:上一层的存储器作为低一层存储器的高速缓存。

  • L1高速缓存的容量可以达到数万字节,访问速度几乎和访问寄存器一样快。
  • L2高速缓存的容量十万到数百万字节,通过一条特殊的总线连接到处理器。比L1长5倍。但还是比访问主存快5~10倍。
  • L1 和 L2高速缓存是用一种叫做静态随机访问存储器(SRAM)的硬件技术实现。
    在这里插入图片描述

六、操作系统管理硬件

操作系统是介于应用程序和硬件之间的一个软件,它有两个基本功能:

  • 防止硬件被失控的应用程序滥用
  • 向应用程序提供简单一致的机制来控制复杂而又大相径庭的低级硬件设备。

在这里插入图片描述
操作系统通过几个基本的抽象概念(进程, 虚拟内存, 文件 )来实现这两个功能。注意这只是抽象出来的概念,并非真实存在的设备,文件是对IO设备的抽象,虚拟内存是对主存和文件的抽象,进程是对处理器、内存和文件的抽象。
在这里插入图片描述

1.进程

进程是操作系统对一个正在运行的程序的一种抽象。当一个程序被加载到内存中并成为一个进程时,它可以分为四个部分——堆栈、堆、文本和数据。进程数都是多于可以运行他们的CPU个数的。传统系统在一个时刻只能执行一个程序,而先进的多核处理器能够执行多个程序,无论实在单核还是多核系统,一个CPU看上去都像是在并发地执行多个进程。这是通过处理器在进程间切换来实现的,操作系统实现这种交错执行的机制称为上下文切换

上下文:即是进程运行所需的所有状态信息,比如PC和寄存器文件的当前值,以及主存内容。

上下文切换:进程的上下文切换是指 cpu 从一个进程切换到另一个进程。即保存当前进程的上下文,恢复将要运行的新进程的上下文,然后将控制权传递给新进程,新进程就会在上一次停止的地方开始。

在这里插入图片描述

进程上下文切换主要包含两个主要过程:进程地址空间切换处理器状态切换

进程地址空间切换

  • 切换原因:进程地址空间指的是进程所拥有的虚拟地址空间,而这个地址空间是假的,是 linux 内核通过数据结构来描述出来的,从而使得每一个进程都感觉到自己拥有整个内存的假象,cpu 访问的指令和数据最终会落实到实际的物理地址,对于进程而言通过缺页异常来分配和建立页表映射。进程地址空间内有进程运行的指令和数据,因此到调度器从其他进程重新切换到我的时候,为了保证当前进程访问的虚拟地址是自己的必须切换地址空间。
  • 切换方式:将当前进程的 pgd 虚拟地址转换为物理地址存放在用户控件的页表基址寄存器,当访问用户空间地址的时候 mmu 会通过这个寄存器做遍历页表,获得物理地址。
  • 原理是进程想要访问一个用户空间虚拟地址,cpu 的 mmu 所做的工作,就是从页表基址寄存器拿到页全局目录的物理基地址,然后和虚拟地址配合来查查找页表,最终找到物理地址进行访问(当然如果 tlb 命中就不需要遍历页表),每次用户虚拟地址访问的时候(内核空间共享不考虑),由于页表基地址寄存器内存放的是当前执行进程的页全局目录的物理地址,所以访问自己的一套页表,拿到的是属于自己的物理地址(实际上,进程是访问虚拟地址空间的指令数据的时候不断发生缺页异常,然后缺页异常处理程序为进程分配实际的物理页,然后将页帧号和页表属性填入自己的页表条目中),就不会访问其他进程的指令和数据,这也是为何多个进程可以访问相同的虚拟地址而不会出现差错的原因。
  • ps:地址空间切换过程中,还会清空 tlb(页表缓存:用于存放虚拟地址映射至物理地址的标签页表条目),防止当前进程虚拟地址转化过程中命中上一个进程的 tlb 表项,一般会将所有的 tlb 无效,但是这会导致很大的性能损失,因为新进程被切换进来的时候面对的是全新的空的 tlb,造成很大概率的 tlb miss,需要重新遍历多级页表

处理器状态切换

  • 切换原因:需要将进程的内核栈和执行流进行切换。
  • 切换方式:处理器状态切换就是将前一个进程的 sp,pc 等寄存器的值保存到一块内存上,然后将即将执行的进程的 sp,pc 等寄存器的值从另一块内存中恢复到相应寄存器中,恢复 sp 完成了进程内核栈的切换,恢复 pc 完成了指令执行流的切换。
    sp 寄存器在任意时刻会保存我们栈顶的地址.
    pc 寄存器也称为程序寄存器,用于存储指向下一条指令的地址,也即将将要执行的指令代码。

2.线程

一个进程实际可以由多个称为线程的执行单元组成,每个线程都运行在进程的上下文中,并共享同样的代码和全局数据。多线程比多进程更容易共享数据,有多处理器的时候,多线程也是一种使程序更快运行的方法。

3.虚拟内存

虚拟存储器是一个抽象的概念,它为每个进程提供了一个假象,即每个进程独占地使用所有主存。每个进程看到的内存都是一致的,称为虚拟地址空间。

地址空间最上面的区域为操作系统的代码和数据保留的,这对所有进程都是一样的。地址空间的底部区域存放用户进程定义的代码和数据。

在这里插入图片描述
每个进程的虚拟地址空间由大量准确定义的区构成,每个区都有专门的功能。从最低地址开始,逐步向上介绍:

  • 程序代码和数据:对于所有进程来说,代码从一固定地址开始,紧接和C全局变量相对应的数据位置。代码和数据区是直接按照可执行目标文件的内容初始化的。

  • :代码和数据区紧随着运行时堆。代码和数据区是在进程一开始就被规定了大小,与此不同,调用malloc和free时堆动态的扩展和收缩。

  • 共享库:地址空间的中间部分存放C标准库和数学库这样共享库代码和数据的区域。共享库概念非常强大,相当难懂。

  • : 用户虚拟地址顶部的是用户栈,编译器用它来实现函数调用。和堆一样,在执行时动态的扩展和收缩。

  • 内核虚拟存储器: 内核总是驻留在内存中,是操作系统一部分。

4.文件

文件 就是 字节序列,仅此而已。所有I/O设备 都可视为文件,包括磁盘、键盘、显示器、甚至是网络。系统中的所有输入输出都是通过使用Unix I/O 的系统函数调用读写文件来实现。

七、系统之间利用网络通信

从一个单独的系统来看,网络可视为一个I/O设备。如系统从主存中赋值一串字节经过网络适配器,再到另一台机器。
在这里插入图片描述

我们平时用XShell操作服务器时,程序运行的基本步骤与下面一样。

在这里插入图片描述

八、并发和并行

并发:是一个通用概念,指一个同时具有多个活动的系统。
并行:指的是用并发使一个系统运行的更快。并行可以在计算机多个抽象层次运用。

多处理系统县城及并发:独立的L1,L2高速缓存,寄存器;共享更高层次的高速缓存。
在这里插入图片描述

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

yelvens

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值