【深入理解计算机操作系统】01_计算机系统漫游
学习总路线
以hello程序的整个生命周期来开始对系统的学习
#include<stdio.h>
int main()
{printf("hello world!\n");return 0;
}
一、信息:位+上下文
hello程序的生命周期
- 从源程序(源文件)开始,即程序员编写的hello.c文件
- 源程序是由0和1组成的位(比特)序列
- 8个位为一组,称为一个字节
- 每个字节表示程序中的某些文本字符
- 现代计算机大多使用ASCII标准表示文本字符(唯一的单字节整数值来表示一个字符)
- hello程序以字节序列储存在文件中
- 第一个字符"#"对应ASCII的整数值是35,第二个字符"i"对应的是105,以此类推…
- hello.c这样只由ASCII字符构成的文件称为文本文件,所有其他文件称为二进制文件
hello程序说明的一个基本思想
- 系统中所有的信息都是一串比特表示,区分不同数据对象的唯一方法就是读到这些对象时的上下文
- 磁盘文件、内存中的程序、内存中存放的用户数据、网络上传送的数据等等
- 不同的上下文中,一个同样的字节序列可能表示一个整数、浮点数、字符串或机器指令
二、程序被其他程序翻译成不同的格式
为了在系统上运行hello.c程序,必须将程序转化为一系列低级机器语言指令
- 这些指令按照一种称为可执行目标程序的格式打好包,并以二进制磁盘文件的形式存放起来。
- 目标程序也称为可执行目标文件
- Unix系统上:gcc -o hello hello.c
1.预处理阶段
- 预处理器(cpp)根据以字符#开头的命令,修改原始的C程序
- #include<stdio.h>命令高速预处理器读取系统头文件stdio.h的内容,并把它直接插入程序文本中,得到了另外一个C程序,以.i为文件扩展名
2.编译阶段
- 编译器(ccl):将文本文件hello.i翻译成文本文件hello.s,它包含了一个汇编语言程序,该程序包含main的定义
3.汇编阶段
- 汇编器(as)将hello.s翻译成机器语言指令,并把这些指令打包成一种叫做可重定位目标程序(relocatable object program)的格式,并将结果存在目标文件hello.o中
- hello.o是二进制文件,用文本编辑器打开是乱码
4.链接阶段
- printf函数是C标准库中的一个函数,存在printf.o中
- 链接器(ld):将printf.o合并到hello.o中,得到hello文件(可执行目标文件)
三、为什么要知道操作系统如何工作
了解操作系统如何工作是有很多益处的
- 优化程序性能
- 现代编译器都十分成熟,我们无需为了写高效代码而去了解编译器工作原理
- 但为了在C程序中做出好的编码选择,我们确实需要了解一些编译器将不同的C语句转换为机器代码的方式
- 理解链接时出现的错误
- 避免安全漏洞
- 多年来,缓冲区溢出错误的造成大多数为了和Internet服务器安全漏洞的主要原因
四、处理器读并解释储存在内存中的指令
想要在Unix上执行hello程序,需要将它的文件名输入到shell的应用程序中
linux> ./hello hello world! linux>
shell是命令行解释器:输出一个提示符,等待输入一个命令行,然后执行这个命令
- 如果第一个单词不是内置的shell命令,则shell会假设这是一个可执行文件的名字,加载并运行这个文件
1、系统的硬件组成
1.总线
总线:贯穿整个系统的一组电子管道,携带信息字节并负责在各个部件间传递
- 总线通常被设计成传送定长的字节块,也就是字(word)
- 字中的字节数(即字长)是一个基本的系统参数,不同的系统可能不一样
- 大多数要么是4字节(32位),要么8字节(64位)
2.I/O设备
I/O(输入/输出)设备是系统与外部世界的联系通道
- 用户输入的键盘和鼠标
- 用户输出的显示器
- 用于长期存储数据和程序的磁盘驱动器等等
每一个I/O设备都是通过一个控制器或适配器与I/O总线相连
- 控制器和适配器的区别:封装方式
- 控制器是I/O设备本身或系统的主印制电路板(通常称作主板)上的芯片组
- 适配器是一块插在主板插槽上的卡
3.主存
主存是一个临时存储设备,在处理器执行程序时,用来存放程序和程序处理的数据
- 物理上:由一组动态随机存取寄存器(DRAM)芯片组成
- 逻辑上:存储器是一个线性的字节数组,每个字节都有其唯一的地址(数组索引),这些地址是从0开始的
4.处理器
中央处理器(CPU),简称处理器,是解释(或执行)存储在主存中的指令的引擎
- 核心:大小为一个字的存储设备(或寄存器),称为程序计数器(PC)
- 任何时刻,PC都指向主存中的某条机器语言指令(即PC中存放该指令的地址)
寄存器文件(register file):一个小的存储设备,由一些单个字长的寄存器组成,每个寄存器都有唯一的名字
算数/逻辑单元(ALU):计算新的数据和地址值
简单的几个CPU在指令的要求下执行可能会的操作
- 加载:从主存复制一个字节或一个字到寄存器,以覆盖寄存器原来的内容
- 存储:从寄存器复制一个字或一个字节到内存中某个位置,以覆盖该位置的内容
- 操作:把两个寄存器的内容复制到ALU,ALU对这两个数进行运算,并将结果存在寄存器中,覆盖原理寄存器的内容
- 跳转:指令本身抽取一个字,并将这个字复制到PC中,覆盖PC的值
处理器看上去是对指令集架构的简单实现,但现代的处理器都用了十分复杂的机制来加速程序的执行
- 指令集架构描述每条机器代码指令的
2、运行hello程序
初始化:shell程序执行它的指令,等待我们输入一个命令
1.当我们输入"./hello"后
- shell程序逐个字符读入寄存器,然后放到内存中(下图深黑色的线)
2.当我们敲回车时
- shell程序知道命令已经结束
- shell程序执行一系列指令来加载可执行的hello文件
- 这些指令将hello目标文件中的代码和数据从磁盘复制到主存
- 利用直接存储器存取(DMA)技术,数据可以不通过处理器而直接从磁盘到主存
3.hello程序中的代码和数据被加载到内存后
- 处理器开始执行hello程序的main程序中的机器语言指令
- 将"hello world\n"字符串中的字节从主存复制到寄存器文件,再从寄存器文件中复制到显示设备,最终显示在屏幕上
五、高速缓存至关重要
上述hello程序揭示一个问题:系统花费大量时间把信息从一个地方挪到另一个地方
- 复制需要开销,所以系统设计者的目的是使得复制尽可能快的完成
根据机械原理:快速设备造价远高于同类的低俗设备
- 磁盘比主存大1000倍,但处理器从主存读一个字的时间开销比从磁盘块1000万倍
- 典型的寄存器文件只存储几百字节的信息,主存一般可存放十几亿字节,但处理器从寄存器文件读数据比从主存几乎快100倍
- 更麻烦的时,随着半导体技术的进步,这种处理器和主存间差距还在持续增大
解决处理器和主存之间的差异:采用更小更快的高速缓存存储器(cache memory)
- 作为暂时的集结区域,存放处理器近期可能会需要的信息
- 为什么高速存储器可行:程序的局部性原理
- 通过cache中存放可能经常访问的数据,大部分内存操作都可以在cache中完成
- 处理器芯片上的L1高速缓存的容量达到几万字节,速度几乎和访问寄存器文件一样
- L2达到数十万到数百万字节,通过一条特殊的总线连接到处理器,访问L2比L1时间长5倍
- L1和L2高速缓存是静态随机访问存储器(SRAM)
- 有些系统还有L3
六、存储设备形成的层次结构
自上而下,速度越慢、容量越大、造价越便宜
七、操作系统管理硬件
shell程序加载和运行hello程序以及hello程序输出自己的消息时,shell程序和hello程序都没有直接访问键盘、显示器、磁盘或主存,而是依靠操作系统提供的服务
- 操作系统可以看成应用程序和硬件之间插入的一层软件
操作系统两个基本功能:
- 防止硬件被失控的应用程序滥用
- 向应用程序提供简单一致的机制来控制复杂而又大不相同的低级硬件设备
操作系统通过几个基本的抽象概念来实现这两个功能
- 文件:对I/O设备的抽象表示
- 虚拟内存:对主存和磁盘I/O设备的抽象表示
- 进程:处理器、主存和I/O设备的抽象表示
1、进程
进程是操作系统对一个正在运行的程序的一种抽象
- 一个系统可以同时有多个进程并发执行,系统上每个进程都好像在独占使用硬件
- 并发执行:一个进程的指令和另一个进程的执行交错执行
- 一个处理器同时最多只能有一个进程在执行,而看上去像是在并发是通过进程间切换来实现的
- 进程间切换:上下文切换
操作系统保持跟踪进程运行所需的所有状态信息
- 状态:上下文
- PC和寄存器文件的当前值
- 主存的内容等
- 上下文切换:保存当前进程的上下文,恢复新进程的上下文,然后控制器传递给新进程,新进程就会从上次停止的地方继续执行
hello程序的调用为例
- 一开始,只有shell程序在运行
- 运行hello程序时,shell通过调用一个专门的函数(系统调用)来执行我们的请求,系统调用会将控制权传递给操作系统
- 操作系统保存shell进程的上下文,创建新的hello进程及其上下文,然后将控制权交给新的hello进程
- hello进程结束后,操作系统恢复shell进程的上下文,并将控制权传给新shell进程
进程切换由操作系统内核(kernel)管理
- 内核是操作系统代码常驻内存的部分
- 当应用程序需要操作系统的某些操作时,就执行一条特殊的系统调用(system call)指令,将控制器传递给内核,内容执行被请求的操作并返回给应用程序
- 内核不是一个独立的进程,是系统管理全部进程所用代码和数据结构的集合
2、线程
一个进程可由多个线程组成
进程:资源分配的基本单位
线程:调度的基本单位
3、虚拟内存
虚拟内存是一个抽象的概念:使每个进程都以为独占了内存,,看到的内存都一样,称为虚拟地址空间
以Linux为例
地址空间最上面的区域是保留给操作系统中的代码和数据的
底部区域存放用户进程定义的代码和数据
进程看到的虚拟地址空间由大量准确定义的区构成,每个区都有专门的概念,自下而上:
- 程序代码和数据
- 堆
- 共享库
- 栈
- 内核虚拟内存
4、文件
文件就是字节序列
- 每个I/O设备,包括磁盘,键盘,显示器,网络都可以看成文件
八、系统之间利用网络通信
到目前为之,我们一直把系统视作一个孤立的硬件和软件集合体。实际上,现代系统经常会通过网络和其他系统连接在一起
网络可以看成I/O设备:系统从主存复制一串字节到网络适配器时,数据流结果网络到达另一台机器,系统也能从其他机器读取发来的数据并复制到主存
到如今电子邮件、即时通信、万维网、FTP和telnet等都是基于网络复制信息的功能
hello程序为例,可以是使用熟悉的telnet应用在远程主机上运行hello程序
九、重要主题
1、Amdahl定律
Gene Amdahl对提升系统某一部分性能所带来的效果做出了简单却有见地的观察,这个观察称为Amdahl定律
- 当我们对系统某个部分加速时,其对整体性能的影响取决于该部分的重要性和加速程度
该定律的主要观点:要显著加速更个系统,必须提升全系统中相当大部分的速度
计算公式
- 执行某应用程序需要的时间:Told、系统某部分执行时间占总时间的比例为α,该部分的性能提升比例为k
- 该部分初始所需的时间为αTold、现在所需时间(αTold)/k
- Tnew = (1-α)Told + (αTold)/k
- 加速比S=Told/Tnew
- S = 1/((1-a)+a/k)
当k趋于无穷,即某一部分的性能加速到一个点,该点时间可以忽略不计
- S = 1/(1-a)
- 若系统有60%都加速到这种状态,则加速比只有1/0.4=2.5X
- 所以更加说明了只有优化系统的大部分组件才能获得更好的优化
2、并发和并行
计算机进步的持续动力:计算机做更多、运行更快
1.线程级并发
一开始只有一个处理器(单处理器系统)
- 实现并发:进程快速切换
由单操作系统内核控制的多处理器组成的系统:多处理器系统
- 将多个CPU(核)集成到一个集成电路芯片上
超线程(hypethreading):又称同时多线程(simultaneous multi-threading)
- 允许一个CPU执行多个控制流的技术
- 常规处理器需要大约20 000个时钟周期做不同线程间的切换,而超线程处理器可以在单个周期的基础上决定要执行哪个线程,使得CPU更好的利用它的资源处理
- 超线程从两方面提高系统性能
- 减少了在执行多个任务时模拟并发的需要
- 应用程序运行更快(需要程序以多线程方式来书写)
2.指令级并行
早期的微处理器,如Intel 8086,需要(3~10个)时钟周期来执行一条指令
最近的处理器可以保持每个时钟周期2~4条指令的执行速率
- 实际上每条指令从开始到结束需要20或更多个周期,单处理器使用了流水线(pipelining)技术
处理器可以达到比一个周期一条指令更快的执行速率,称为超标量(super-scalar)处理器
3.单指令、多数据并行
在最低层次上,许多现代处理器拥有特殊的硬件,允许一条指令产生多个可以并行执行的操作,称为单指令、多数据,即SIMD并行
- 新几代的Intel核AMD处理器都有并行对8对单精度浮点数(C语言的float)做加法的指令
- 提供SIMD指令多是为了提高处理影像、声音、视频数据应用的执行速度
- 有些编译程序会试图从C程序中自动抽取SIMD并行性
- 但更可靠的方法是用编译器支持的特殊的向量数据类型来写程序
- GCC支持向量数据类型
3、计算机系统中抽象的重要性
为一组函数规定一个简单的应用程序接口(API)就是一个很好的编程习惯,程序员无须了解它的内部工作便可以使用这些代码
处理器里,指令集架构提供了对实际处理器硬件的抽象
【深入理解计算机操作系统】01_计算机系统漫游相关推荐
- 计算机漫游模式,深入理解操作系统之一 —— 计算机系统漫游
这些内容都是摘自<深入理解操作系统>这本书,很多年前学习操作系统都是马马虎虎,突然感觉现在很需要再次深入了解操作系统,读了这本书感觉对自己有用的就记下来了,方面以后查阅. 计算机系统漫游这 ...
- 深入理解计算机操作系统(一)
目录 1.1 信息就是位加上下文 1.2 程序被其他程序翻译成不同的格式 1.3 了解编译系统如何工作是大有益处的 1.4 处理器读并解释储存在内存中的指令 1.4.1系统的硬件组成 1.4.2 运行 ...
- 深入理解计算机操作系统(五)
阅读经典--<深入理解计算机系统>04 函数调用时的栈结构变化是一个很有趣的话题,本文就来详细剖析这个过程. 栈帧结构 寄存器使用惯例 这段代码的含义? 栈帧结构 在计算机系统概述中我们介 ...
- 计算机原理(计算机系统漫游)
计算机五大组成部件:运算器(ALU),控制器,存储器,输入部件,输出部件 1.控制器 2.运算器 逻辑运算(判断事物的对与错) 数学运算(1+1) 控制器+运算器=中央处理器(CPU) 3.存储器 包 ...
- 深入理解计算机操作系统:第2章 信息的表示和处理(学习笔记)
现代计算机存储和处理的信息都是用二进制表示的,即0和1. 用多个二进制比特位的不同组合和不同解释能够表示数量有限的元素,比如用32位比特的组合则有2^32种可能,因此它能表示从0开始到42949672 ...
- 深入理解计算机操作系统:链接笔记
链接的本质 简单版 实际版 可重定位目标文件 可执行目标文件 符号与符号表 静态库 动态库
- 深入理解计算机操作系统:链接
文章目录 链接器的由来: 链接过程的本质: 目标文件的两种视图 可重定位文件概述 ELF头和节头表 可执行文件概述 程序头表和存储器印象 符号和符号表的基本概念 全局符号的强弱特性 多重符号定义举例 ...
- 计算机操作系统第三章知识点,深入理解计算机操作系统第三章家庭作业
3.58 y=y-z; x=x*y; return x ^ (y<<63>>63); 3.59 无符号64位,ux 和 uy 有符号64位,x 和 y 设 x 和 ux 具有相 ...
- 计算机操作系统与生态系统
规律,世界的运转遵循着一定的规则.比如地球围绕着太阳转,月球围绕着地球转.我们无法理解月球为什么叫月球,因而CPU也是如此,他为什么用的是这个名词而不是别的,这些是一些约定俗成的东西.我们只需要理解他 ...
最新文章
- 写给新手炼丹师:2021版调参上分手册
- Unable to instantiate Action, MenuAction, defined for 'QueryMenuAll' in namespace '/'MenuAction
- bcftools合并vcf文件
- Java小结(三)——打印完美杨辉三角
- 远离盛行道德绑架的团队
- 面向对象初始应用和认知2
- Crossing River(信息学奥赛一本通-T1232)
- C语言强制转换与输出格式不对应问题
- 博客首页全新改版;博客代码片支持折叠;原创博文新增打赏功能……【2022.1.17】
- H+ HPlus创建新的标签页/选项卡
- [内附完整源码和文档] 基于JAVA的干部档案管理系统
- 适合mysql的网络存储_mysql 选择合适的存储引擎
- 小米2017校招面试经历
- 【PPic】在PPic图床中如何配置使用七牛
- 直播系统---从直播答题看SEI帧的原理和作用
- 映射IP使模拟器可以通信
- Mysql5 实现交叉表查询
- 【javaScript】获取某年某月的的最后一天(即当月天数) 妙用
- 【数学建模】灰度预测之关联度求解
- python操作三大数据库百度云_【python操作三大】下载 - 面包树
热门文章
- 对研究生教育有什么看法_我对研究员特征的看法
- python to datetime_python-pd.to_datetime或解析日期时间不适用于我...
- 液晶屏TTL屏、LVDS屏的区别
- 获取图片地址的最后的图片名称
- java imageio处理图像_Linux geoserver调优之Java图像处理优化(原生JAI和ImageIO和java默认库相互转换)...
- 关于Apache/Tomcat/JBOSS/Neginx/lighttpd/Jetty等一些常见服务器的区别比较和理解
- 机智云OTA过程MCU端程序设计学习(二)
- PSIM仿真简单例程(频率响应)
- win10 打开chm文件内容空白如何解决
- 如何破解4399上的小游戏