以下内容几乎来自王道计算机考研视频,感谢王道计算机考研的公开教学视频。
一、进程线程模型
进程:程序段、数据段、PCB三部分组成了进程实体(进程映像)。一般情况下,我们把进程实体就简称为进程(可以独立运行的程序单位)。所谓创建进程与撤销进程,实质上就是创建与撤销进程实体中的PCB。
线程:(为了增加并发度)线程是一个基本的CPU执行单元,也是程序执行流的最小单位。
进程就是线程的集合,进程是由一个或多个线程构成的,线程是操作系统进行运算调度的最小单位,是进程中的最小运行单元。多线程就是一个进程中同时执行多个线程。
二、并发与同步、异步、并行
临界资源:一个时间段内只允许一个进程使用的资源称为临界资源。
临界区:进程中访问临界资源的代码段。
串行:一段时间内只能执行一个进程,这个进程完成后才能继续获取和执行下一个进程。
互斥:(间接制约关系)进程互斥指当一个进程访问某临界资源时,另一个想要去访问该临界资源的进程必须等待。当前访问临界资源的进程访问结束后,释放该资源以后,另一个进程才能去访问该临界资源。
同步:(直接制约关系)同步是指为完成某种任务而建立的两个或多个进程,这些进程因为需要在某些位置上协调它们的工作次序而产生的制约关系。进程间的直接制约关系就是源于它们之间的相互合作。
异步:进程具有异步性的特征。异步性是指各并发执行的进程以各自独立的、不可预知的速度向前推进。
并行:同一时刻有多条指令在多个处理器上同时执行,这意味着并行必须依赖多个处理器。
并发:处理器同一时刻只能执行一条指令,并发是指多个线程对应的多条指令被快速轮换地执行。
互斥访问实现遵循原则
(一)基于软件或硬件实现进程互斥的方法
基于软件实现的进程互斥方法有:
基于硬件实现的进程互斥方法有:
(二)原语概念
原语是一种特殊的程序段,其执行只能一气呵成,不可被中断(原子操作)。原语是由关中断/开中断指令(特权指令)实现的。
在执行原语程序段前会首先执行关中断指令,使得CPU在核心态下忽略外部中断信号从而顺利执行原语,结束后执行开中断指令恢复。
(三)信号量机制
信号量可以是一个整数,也可以是更复杂的记录型变量,其可用来表示系统中某种资源的数量。用户进程可以通过使用操作系统提供的一对原语(wait(S)与signal(S)又名P(S)与V(S),S为信号量)来对信号量进行操作,从而很方便地实现了进程互斥、进程同步。
1、整型信号量(S代表整型信号量)
wait(S)原语实现了“检查”和“上锁”一气呵成,避免了并发、异步导致的问题。其存在的问题是不满足“让权等待”原则,会发生“忙等现象”。
(注:由于C++函数引用传递与值传递的区别,此处应该传入int& S才能实现静态变量的值改变)
2、记录型信号量(S代表记录型信号量)
对信号量S的一次P操作意味着进程请求一个单位的该类资源,因此需要执行S.value--,表示资源数减一,当S.value<0时表示该类资源已分配完毕,因此进程应调用block原语进行自我阻塞(当前进程从运行态转变为阻塞态),主动放弃处理机,并插入该类资源的等待队列S.L中。可见,该机制遵循了“让权等待”原则,不会出现忙等现象。
对信号量S的一次V操作意味着进程释放一个单位的该类资源,因此需要执行S.value++,表示资源数加一,若加一后仍是S.value<=0,表示依然有进程在等待该类资源,因此调用wakeup原语唤醒等待队列中的第一个进程(被唤醒进程从阻塞态转变为就绪态)。
(注:此处同理应传入引用变量)
三、内存管理
存储单元:在存储器中有大量的存储元,把他们按相同的位划分为组,组内所有的存储元同时进行读出或写入操作,这样的一组存储元称为一个存储单元。(分为字存储单元与字节存储单元,存储单元是CPU访问存储器的基本单位)存储单元的大小由编址方式(按字或按字节)决定,内存地址从0开始,每个地址对应一个存储单元。
存储单元的地址和地址的内容:存储单元的地址是存储单元的编号来表示存储器中的一个位置,而地址的内容表示这个位置里存放的数据。
字长:字长是CPU的主要技术指标之一,指的是CPU一次能并行处理的二进制位数,字长总是8的整数倍。(字长直接反映了一台计算机的计算精度)
地址长度:表示相应数目的存储单元所需的二进制位个数。
内部碎片:分配给某进程的内存区域中,该进程未利用上的部分。
外部碎片:内存中的某些空闲分区由于太小而难以利用。
内存:CPU能直接寻址的存储空间,是存取速率快的硬件(程序执行前需要先放到内存中才能被CPU处理,CPU是超快速设备,内存的运行将直接影响计算机整体运算的快慢)。
外存:存储容量大但是存取速率低的硬件(此类存储器一般断电后仍然能保存数据)。常见的外存储器有硬盘、软盘、光碟、U盘等。
连续分配:为用户进程分配的必须是一个连续的内存空间。
非连续分配:为用户进程分配的可以是一些分散的内存空间。
页框,又名页帧、内存块、物理块:内存空间中分为一个个大小相等的分区。每个页框有一个编号,页框号从0开始。
页,又名页面:将用户进程的地址空间也分为与页框大小相等的一个个区域。每个页面也有一个编号(页号)也是从0开始。(为了方便计算页号、页内偏移量,页面大小一般设为2的整数次幂)
页表(记录进程的每个页面在内存中存放的位置的数据结构):每个页表项由”页号“和”块号“组成。一个进程对应一张页表,进程的每一页对应一个页表项。页表记录进程页面和实际存放的内存块之间的对应关系。
页表寄存器(PTR):在系统中存放页表在内存中的起始地址F和页表长度M(该进程所分成的页面个数)。进程未执行时,页表的始址和页表长度放在进程控制块PCB中,当进程被调度时,操作系统内核会把它们放到页表寄存器中。
时间局部性:如果执行了程序中的某条指令,那么不久后这条指令很有可能再次执行;如果某个数据被访问过,不久之后该数据很可能再次被访问。(基于程序中通常存在大量的循环)
空间局部性:一旦程序访问了某个存储单元,在不久之后,其附近的存储单元也很有可能被访问。(基于很多数据在内存中是连续存放的)
快表,又称联想寄存器(TLB):一种访问速度比内存快很多的高速缓冲存储器,用来存放当前访问的若干页表项,以加速地址变换的过程。与此对应,内存中的页表常称为慢表。
页目录表,或称外层页表、顶层页表:将很长的页表进行分组,使每个内存块刚好可以放入一个分组,并为离散分配的页表再建立的一张页表。
分段:按照程序自身的逻辑关系划分为若干个段,每个段都有一个段名(在低级语言(如汇编语言)中,程序员使用段名来编程),每段从0开始编址。内存分配以段为单位。
段表:程序分多个段,各段离散地装入内存,为了保证程序能正常运行,就必须能从物体内存中找到各个逻辑段的存放位置。为此,为每个进程所建立起来的一张段映射表,简称”段表“。每一个段对应一个段表项,其中记录了该段在内存中的起始位置(又称”基址“)和段的长度。
(虽然段表的段长可以各不相同,但是以最大段长即可固定。所以各个段表项的长度是相同的)
段表寄存器:用于存放进程的段表在内存中的起始地址和长度。在进程没有上处理机运行的时候,段表始址和段表长度信息是被存放在进程的PCB中的;当进程上处理机运行时,其信息会被放于很快的段表寄存器当中。
纯代码,或称可重入代码:不能被修改的代码(不属于临界资源),这样的代码是可以共享的。(可修改的代码是不能共享的,容易造成数据不一致)
计算机中存储器的层次结构:外存 -> 内存 -> 高速缓存 -> 寄存器(以上硬件的容量依次减小、速度增快、成本增加)。
基本分页存储的地址转换计算
页号=逻辑地址(相对地址)/页面长度(取除法的整数部分)
页内偏移量=逻辑地址(相对地址)%页面长度(取余)
①算出逻辑地址对应的页号;
②根据页表知道页号对应的页面在内存中的起始地址;
③算出逻辑地址在页面内的”偏移量“;
④物理地址=页面内存始址+页内偏移量。
图一 查询页表方法(两次访存,一次查询页表、一次直接访问物理地址)
图二 快表查询方式(快表会自动存储副本最近查询的页表信息)
(快表命中,一次访存;快表未命中,需同图一完成两次访存)
图三 两级页表访问
基本分段存储管理方式
图四 基本分段存储管理
段页式管理方式
内存空间扩充基本概念(从逻辑上扩充内存容量)
特别强调的是,(一次性)传统存储管理方式中(连续分配和非连续分配上述方法)作业必须一次性全部装入内存后才能开始运行;(驻留性)传统存储管理方式中,一旦作业被装入内存,就会一直驻留在内存中,直至作业运行结束。
①覆盖技术
②交换技术
③虚拟存储技术(建立在离散分配的内存管理方式基础上)
虚拟内存的定义:在操作系统的管理下,在用户看来似乎有一个比实际内存大得多的内存,这就是虚拟内存。
虚拟内存的最大容量是由计算机的地址结构(CPU寻址范围)确定的;
虚拟内存的实际容量=min(内存和外存容量之和,CPU寻址范围)
虚拟内存的特征:
①多次性:无需在作业运行时一次性全部装入内存,而是允许被分成多次调入内存。
②对换性:在作业运行时无需一直常驻内存,而是允许在作业运行过程中,将作业换入、换出。
③虚拟性:从逻辑上扩充了内存的容量,使用户看到的内存容量远大于实际的容量。
虚拟内存的实现方法:(信息存储状态符表示是否位于内存)
(在程序执行过程中,当所访问的信息不在内存时,由操作系统负责将所需信息从外存调入内存,然后继续执行程序;若内存空间不够,由操作系统负责将内存中暂时用不到的信息换出到外存)
①请求分页存储管理
②请求分段存储管理
③请求段页式存储管理
进程运行的基本原理
编译:由编译程序将用户源代码编译成若干个目标模块。(编译就是把高级语言翻译为机器语言。编译生成的指令中一般是使用逻辑地址(相对地址),因为一般实际在生成机器指令的时候并不知道该进程的数据会被放到内存什么位置)
链接:由链接程序将编译后形成的一组目标模块,以及所需库函数链接在一起,形成一个完整的装入模块。链接的三种方式分别为静态链接、装入时动态链接以及运行时动态链接。
装入(装载):由装入程序将装入模块装入内存运行。装入有三种方式,分别为绝对装入(编译程序将产生绝对地址的目标代码,装入程序按照装入模块中的地址,将程序和数据装入内存)、静态重定位(编译链接后的装入模块的地址都是从0开始的逻辑地址。装入时对地址进行“重定位”,将逻辑地址基于内存的起始物理地址变换为物理地址)和动态重定位(编译链接后的装入模块的地址都是从0开始的。装入程序把装入模块装入内存后,并不会立即把逻辑地址转换为物理地址,而是把地址转换推迟到程序真正要执行时才进行。因此装入内存后所有的地址依然是逻辑地址。这种方式需要一个重定位寄存器(存放装入模块存放的内存起始物理地址)的支持)。
存储单位换算
bit是二进制的一位,即二进制数中的一个数位,其作为信息技术的最基本存储单元。
思维导图
基本地址变换例题
若页面大小L为1K字节,页号2对应的内存块号b=8,将逻辑地址A=2500转换为物理地址E。
(等价描述)某系统按字节寻址,逻辑地址结构中,页内偏移量占10位,页号2对应的内存块号b=8,将逻辑地址A=2500转换为物理地址E。