操作系统基本特性
并行与并发的区别
- 并发是指一个处理器同时处理多个任务。并行是指多个处理器或者是多核的处理器同时处理多个不同的任务。并发是逻辑上的同时发生(simultaneous),而并行是物理上的同时发生。来个比喻:并发是一个人同时吃三个馒头,而并行是三个人同时吃三个馒头。
- 并发性是指两个或者多个事件在同一时刻发生。而并行性是指两个或者多个事件在同一时间间隔内发生。并发指在同一时刻只能有一条指令执行,但多个进程指令被快速的轮换执行,使得在宏观上具有多个进程同时执行的效果,但在微观上并不是同时执行的,只是把时间分成若干段,使多个进程快速交替的执行。
- 当有多个线程在操作时,如果系统只有一个CPU,则它根本不可能真正同时进行一个以上的线程,它只能把CPU运行时间划分成若干个时间段,再将时间段分配给各个线程执行,在一个时间段的线程代码运行时,其它线程处于挂起状态。这种方式我们称之为并发(Concurrent)。当系统有一个以上CPU时,则线程的操作有可能非并发。当一个CPU执行一个线程时,另一个CPU可以执行另一个线程,两个线程互不抢占CPU资源,可以同时进行,这种方式我们称之为并行(Parallel)。
什么是操作系统及操作系统的功能。
- 操作系统是管理计算机硬件与软件资源的程序,是计算机的基石。
- 操作系统本质上是一个运行在计算机上的软件程序,用于管理计算机硬件和软件资源。
- 操作系统的存在屏蔽了硬件层的复杂性。
- 操作系统的内核是操作系统的核心部分,它负责系统的内存管理,硬件设备的管理,文件系统的管理以及应用程序的管理。
操作系统内核及其作用
操作系统内核的功能
- OS内核:紧靠着硬件的软件层次,常驻内存
- 与硬件紧密相关的模块如中断处理程序
- 常用设备的驱动程序
- 运行频率较快的模块:时钟管理,进程调度
- 为了防止OS本身及其关键数据如PCB等遭到应用程序的恶意或无意破坏,将处理机的执行状态分为系统态和用户态。
- 管态:较高特权,能够执行一切指令,访问所有寄存器和存储区。
- 目态:仅能执行规定的指令,访问指定的寄存器和存储区。
- 支撑功能
- 中断处理:
- 时钟管理
- 原语操作:原子操作,在执行过程中不允许被中断。
- 资源管理功能
- 进程管理:进程同步原语,进程通信原语
- 存储器管理:地址转换机构,内存分配与回收,对换功能。
- 设备管理:缓冲管理,驱动程序,设备独立性功能的软件。
用户态:用户态运行的进程或可以直接读取用户程序的数据。
系统态:可以简单地理解系统态运行的进程或程序几乎可以访问计算机的任何资源,不受限制。
我们运行的程序基本上都是运行在用户态,如果我们调用操作系统提供的系统态级别的子功能,需要使用到系统调用。
也就是说在我们运行的用户程序中,凡是与系统态级别的资源有关的操作(文件管理,进程控制,内存管理等),都必须通过系统调用的方式向操作系统提出服务请求,并由操作系统代为完成。
系统调用按照功能分类:
设备管理:完成设备的请求或者释放,以及设备的启动等功能。
文件管理:完成文件的读,写,创建及删除等功能。
进程控制:完成进程的创建,撤销,阻塞或者唤醒等功能。
进程通信:完成进程之间的消息传递或者信号传递等功能。
内存管理:完成内存的分配,回收以及获取作业占用内存区大小及地址等功能。
Linux 的系统调用主要有以下这些:
Task | Commands |
---|---|
进程控制 | fork(); exit(); wait(); |
进程通信 | pipe(); shmget(); mmap(); |
文件操作 | open(); read(); write(); |
设备操作 | ioctl(); read(); write(); |
信息维护 | getpid(); alarm(); sleep(); |
安全 | chmod(); umask(); chown(); |
硬件同步机制:关中断,测试并建立指令---》其他访问进程必须不断进行测试,处于一种忙等的状态,不符合让权等待的原则。
信号量机制:
管程机制:有自己名字的特殊模块,由关于共享资源的数据结构和在其上的操作过程组成,进程可调用管程的过程以操作管程中的数据结构;编译器复杂管程的互斥,设置条件变量及等待唤醒操作解决同步问题。每次只有一个进程进入管程,执行这组过程,使用共享资源,达到对共享资源访问的统一管理
信号量的作用
进程通信的途径?管道、信号量、消息队列、共享内存区等等
消息传递(管道、FIFO、消息队列)
同步(互斥量、条件变量、读写锁、文件和写记录锁、信号量)
共享内存(匿名的和具名的)
远程过程调用(Solaris门和Sun RPC)
消息传递系统
进程通信的方式
(1)管道(Pipe):管道可用于具有亲缘关系进程间的通信,允许一个进程和另一个与它有共同祖先的进程之间进行通信。
(2)命名管道(named pipe):命名管道克服了管道没有名字的限制,因此,除具有管道所具有的功能外,它还允许无亲缘关系进程间的通信。命名管道在文件系统中有对应的文件名。命名管道通过命令mkfifo或系统调用mkfifo来创建。有名管道严格遵循先进先出(first in first out)。有名管道以磁盘文件的方式存在,可以实现本机任意两个进程通信。
(3)信号(Signal):信号是比较复杂的通信方式,用于通知接受进程有某种事件发生,除了用于进程间通信外,进程还可以发送信号给进程本身;linux除了支持Unix早期信号语义函数sigal外,还支持语义符合Posix.1标准的信号函数sigaction(实际上,该函数是基于BSD的,BSD为了实现可靠信号机制,又能够统一对外接口,用sigaction函数重新实现了signal函数)。
(4)消息(Message)队列:消息队列是消息的链接表,包括Posix消息队列system V消息队列。有足够权限的进程可以向队列中添加消息,被赋予读权限的进程则可以读走队列中的消息。消息队列克服了信号承载信息量少,管道只能承载无格式字节流以及缓冲区大小受限等缺点。
(5)共享内存:使得多个进程可以访问同一块内存空间,是最快的可用IPC形式。是针对其他通信机制运行效率较低而设计的。同进程可以及时看到对方进程中对共享内存中数据的更新。往往与其它通信机制,如信号量结合使用,来达到进程间的同步及互斥。
(6)信号量(semaphore):主要作为进程间以及同一进程不同线程之间的同步手段。信号量是一个计数器,用于多进程对共享数据的访问,信号量的意图在于进程间同步。
(7)套接字(Socket):更为一般的进程间通信机制,可用于不同机器之间的进程间通信。起初是由Unix系统的BSD分支开发出来的,但现在一般可以移植到其它类Unix系统上:Linux和System V的变种都支持套接字。
(8)管道与消息队列的联系和区别:管道和消息队列的通信数据都是先进先出的原则。与管道(无名管道:只存在于内存中的文件;命名管道:存在于实际的磁盘介质或者文件系统)不同的是消息队列存放在内核中,只有在内核重启(即,操作系统重启)或者显示地删除一个消息队列时,该消息队列才会被真正的删除。消息队列可以实现消息的随机查询,消息不一定要以先进先出的次序读取,也可以按消息的类型读取.比 FIFO 更有优势。
- 进程是具有一定功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源调度和分配的一个独立单位。
- 线程是进程的实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位。
- 一个进程可以有多个线程,多个线程也可以并发执行
线程的实现
从Java内存区域的角度看进程与线程的区别:
注:一个进程由多个线程,多个线程共享进程的堆和方法区(JDK1.8之后的元空间)资源,但是每个线程都有自己的程序计数器,虚拟机栈和本地方法栈。
? 线程同步是两个或多个共享关键资源的线程的并发执行。应该同步线程以避免关键的资源使用冲突。操作系统一般有下面三种线程同步的方式:
处理机调度的层次
周转时间和响应时间
作业调度算法
进程调度的任务
- 保存处理机的现场信息
- 按照某种算法选取进程
- 把处理器分配给进程。
进程调度算法
RR:轮转调度算法-》就绪队列中的线程每次仅运行一个时间片
时间片较小,意味着频繁地执行进程调度和进程上下文的切换,无疑增加系统的开销。
时间片较大,每个进程都能在一个时间片内完成,无法满足短作业和交互式用户的需求。
时间片大小的确定:略大于一次交互所需要的时间
多级反馈队列
进程的调度算法
- 先到先服务(FCFS)调度算法 : 从就绪队列中选择一个最先进入该队列的进程为之分配资源,使它立即执行并一直执行到完成或发生某事件而被阻塞放弃占用 CPU 时再重新调度。
- 短作业优先(SJF)的调度算法 : 从就绪队列中选出一个估计运行时间最短的进程为之分配资源,使它立即执行并一直执行到完成或发生某事件而被阻塞放弃占用 CPU 时再重新调度。
- 时间片轮转调度算法 : 时间片轮转调度是一种最古老,最简单,最公平且使用最广的算法,又称 RR(Round robin)调度。每个进程被分配一个时间段,称作它的时间片,即该进程允许运行的时间。
- 多级反馈队列调度算法 :前面介绍的几种进程调度的算法都有一定的局限性。如短进程优先的调度算法,仅照顾了短进程而忽略了长进程 。多级反馈队列调度算法既能使高优先级的作业得到响应又能使短作业(进程)迅速完成。,因而它是目前被公认的一种较好的进程调度算法,UNIX 操作系统采取的便是这种调度算法。
- 优先级调度 : 为每个流程分配优先级,首先执行具有最高优先级的进程,依此类推。具有相同优先级的进程以 FCFS 方式执行。可以根据内存要求,时间要求或任何其他资源要求来确定优先级。
定义:在两个或者多个并发进程中,如果每个进程持有某种资源而又等待其它进程释放它或它们现在保持着的资源,在未改变这种状态之前都不能向前推进,称这一组进程产生了死锁。通俗的讲就是两个或多个进程无限期的阻塞、相互等待的一种状态。
引起死锁的原因:
- 竞争不可抢占性资源
- 竞争可消耗资源
- 进程推进顺序不当
死锁产生的四个条件(有一个条件不成立,则不会产生死锁)
- 互斥条件:一个资源一次只能被一个进程使用
- 请求与保持条件:一个进程因请求资源而阻塞时,对已获得资源保持不放
- 不可剥夺条件:进程获得的资源,在未完全使用完之前,不能强行剥夺
- 循环等待条件:若干进程之间形成一种头尾相接的环形等待资源关系
处理死锁的方法
预防死锁:破坏四个条件之一
避免死锁:在资源动态分配的过程中,防止系统进入不安全状态。银行家算法
检测死锁
解除死锁
何谓悲观锁与乐观锁
乐观锁对应于生活中乐观的人总是想着事情往好的方向发展,悲观锁对应于生活中悲观的人总是想着事情往坏的方向发展。
悲观锁
总是假设最坏的情况,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会阻塞直到它拿到锁(共享资源每次只给一个线程使用,其它线程阻塞,用完后再把资源转让给其它线程)。传统的关系型数据库里边就用到了很多这种锁机制,比如行锁,表锁等,读锁,写锁等,都是在做操作之前先上锁。Java中synchronized和ReentrantLock等独占锁就是悲观锁思想的实现。
乐观锁
总是假设最好的情况,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,可以使用版本号机制和CAS算法实现。乐观锁适用于多读的应用类型,这样可以提高吞吐量,像数据库提供的类似于write_condition机制,其实都是提供的乐观锁。在Java中java.util.concurrent.atomic包下面的原子变量类就是使用了乐观锁的一种实现方式CAS实现的。
两种锁的使用场景
从上面对两种锁的介绍,我们知道两种锁各有优缺点,不可认为一种好于另一种,像乐观锁适用于写比较少的情况下(多读场景),即冲突真的很少发生的时候,这样可以省去了锁的开销,加大了系统的整个吞吐量。但如果是多写的情况,一般会经常产生冲突,这就会导致上层应用会不断的进行retry,这样反倒是降低了性能,所以一般多写的场景下用悲观锁就比较合适。
乐观锁常见的两种实现方式
乐观锁一般会使用版本号机制或CAS算法实现。
版本号机制
应该是当前最后更新的version与操作员第一次的版本号是否相等”来判断是否有权利更新,更新之后version++。一般是在数据表中加上一个数据版本号version字段,表示数据被修改的次数,当数据被修改时,version值会加一。当线程A要更新数据值时,在读取数据的同时也会读取version值,在提交更新时,若刚才读取到的version值为当前数据库中的version值相等时才更新,否则重试更新操作,直到更新成功。
举一个简单的例子:
假设数据库中帐户信息表中有一个 version 字段,当前值为 1 ;而当前帐户余额字段( balance )为 100 。当需要对账户信息表进行更新的时候,需要首先读取version字段。
操作员 A 此时将其读出( version=1 ),并从其帐户余额中扣除 $50( $100-50 )。
在操作员 A 操作的过程中,操作员B 也读入此用户信息( version=1 ),并从其帐户余额中扣除 $20 ( $100-?20 )。
操作员 A 完成了修改工作,提交更新之前会先看数据库的版本和自己读取到的版本是否一致,一致的话,就会将数据版本号加1( version=2 ),连同帐户扣除后余额( balance=?50 ),提交至数据库更新,数据库记录 version 更新为 2 。
操作员 B 完成了操作,提交更新之前会先看数据库的版本和自己读取到的版本是否一致,但此时比对数据库记录版本时发现,此时数据版本号为 2 ,而自己先前读取到的版本号为1 ,不满足 “ 当前最后更新的version与操作员第一次读取的版本号相等 “ 的乐观锁策略,因此,操作员 B 的提交被驳回。
这样,就避免了操作员 B 用基于 version=1 的旧数据修改的结果覆盖操作员A 的操作结果的可能。
CAS算法
即compare and swap(比较与交换),是一种有名的无锁算法。无锁编程,即不使用锁的情况下实现多线程之间的变量同步,也就是在没有线程被阻塞的情况下实现变量的同步,所以也叫非阻塞同步(Non-blocking Synchronization)。CAS算法涉及到三个操作数
需要读写的内存值 V
进行比较的值 A
拟写入的新值 B
当且仅当 V 的值等于 A时,CAS通过原子方式用新值B来更新V的值,否则不会执行任何操作(比较和替换是一个原子操作)。一般情况下是一个自旋操作,即不断的重试。
乐观锁的缺点
ABA 问题
如果一个变量V初次读取的时候是A值,并且在准备赋值的时候检查到它仍然是A值,那我们就能说明它的值没有被其他线程修改过了吗?很明显是不能的,因为在这段时间它的值可能被改为其他值,然后又改回A,那CAS操作就会误认为它从来没有被修改过。这个问题被称为CAS操作的 "ABA"问题。
JDK 1.5 以后的 AtomicStampedReference 类就提供了此种能力,其中的 compareAndSet 方法就是首先检查当前引用是否等于预期引用,并且当前标志是否等于预期标志,如果全部相等,则以原子方式将该引用和该标志的值设置为给定的更新值。
循环时间长开销大
自旋CAS(也就是不成功就一直循环执行直到成功)如果长时间不成功,会给CPU带来非常大的执行开销。 如果JVM能支持处理器提供的pause指令那么效率会有一定的提升,pause指令有两个作用,第一它可以延迟流水线执行指令(de-pipeline),使CPU不会消耗过多的执行资源,延迟的时间取决于具体实现的版本,在一些处理器上延迟时间是零。第二它可以避免在退出循环的时候因内存顺序冲突(memory order violation)而引起CPU流水线被清空(CPU pipeline flush),从而提高CPU的执行效率。
只能保证一个共享变量的原子操作
CAS 只对单个共享变量有效,当操作涉及跨多个共享变量时 CAS 无效。但是从 JDK 1.5开始,提供了AtomicReference类来保证引用对象之间的原子性,你可以把多个变量放在一个对象里来进行 CAS 操作.所以我们可以使用锁或者利用AtomicReference类把多个共享变量合并成一个共享变量来操作。
CAS与synchronized的使用情景
简单的来说CAS适用于写比较少的情况下(多读场景,冲突一般较少),synchronized适用于写比较多的情况下(多写场景,冲突一般较多)
对于资源竞争较少(线程冲突较轻)的情况,使用synchronized同步锁进行线程阻塞和唤醒切换以及用户态内核态间的切换操作额外浪费消耗cpu资源;而CAS基于硬件实现,不需要进入内核,不需要切换线程,操作自旋几率较少,因此可以获得更高的性能。
对于资源竞争严重(线程冲突严重)的情况,CAS自旋的概率会比较大,从而浪费更多的CPU资源,效率低于synchronized。
补充: Java并发编程这个领域中synchronized关键字一直都是元老级的角色,很久之前很多人都会称它为 “重量级锁” 。但是,在JavaSE 1.6之后进行了主要包括为了减少获得锁和释放锁带来的性能消耗而引入的 偏向锁 和 轻量级锁 以及其它各种优化之后变得在某些情况下并不是那么重了。synchronized的底层实现主要依靠 Lock-Free 的队列,基本思路是 自旋后阻塞,竞争切换后继续竞争锁,稍微牺牲了公平性,但获得了高吞吐量。在线程冲突较少的情况下,可以获得和CAS类似的性能;而线程冲突严重的情况下,性能远高于CAS。
备份主存中常用数据,减少处理机对主存储器访问次数。进程的程序和数据存放在主存储器中,每当要访问时被临时复制在一个高速缓存中。
大幅度提高程序的执行速度,有利于CPU快速访问。
介于寄存器和存储器之间的存储器,相比于访问主存的速度,访问高速缓存更快。
将缓存用于读多写少的场景,缓存时间越长,命中率越高。
缓存的粒度越小,命中率越高。即缓存单个对象和缓存一个集合。
缓存的容量。如果容量有限容易引起缓存失败,换入换出。
磁盘的I/O速度远远低于对主存的访问速度,为了缓和两者在速度上的不匹配,设置了磁盘缓存。
主要用于暂时存放频繁使用的一部分磁盘数据和信息,以减少访问磁盘的次数。
但是,磁盘缓存与高速缓存不同,其本身并不是一种实际存在的存储器,而是利用主存中的部分存储空间暂时存放从磁盘中读出或者写入的数据
把内存中暂时不能运行的进程或者暂时不用的程序和数据换出到外存上,以便腾出足够的内存空间,再把已经具备运行条件的进程或进程所需要的程序和数据换入内存。
对换的类型
对换空间管理
磁盘空间分成文件区和对换区两部分。
文件区:主要目标:提高文件存储空间的利用率,然后才是提高对文件的访问速度。
对换区:主要目标:提高进程换入和换出的速度,然后才是提高文件存储空间的利用率
进程换入和换出
- 段是信息的逻辑单位,它是根据用户的需要划分的,因此段对用户是可见的 ;页是信息的物理单位,是为了管理主存的方便而划分的,对用户是透明的。
- 段的大小不固定,由它所完成的功能决定;页的大小固定,由系统决定
- 段向用户提供二维地址空间;页向用户提供的是一维地址空间
- 段是信息的逻辑单位,便于存储保护和信息的共享,页的保护和共享受到限制。页是信息的物理单位。
分页存储管理方式
页表:实现从页号到物理块号的地址映射。通常存放在主存中。
地址变换机构:将用户地址空间的逻辑地址转换为内存空间的物理地址,页表寄存器:页表始址+页表长度
两次访问内存:
快表:联想寄存器,TLB。一次访问内存或者两次访问内存
页面太小产生内部碎片,但是会导致页表太长,占用大量内存
页面太大可以减少页表长度,提高页面换入换出速度,但会使内部碎片增大
分段存储器管理
分段的原因
段表:段号+段长+基址
作业的地址空间被划分为若干个段,每个段定义了一组逻辑信息
产生外部碎片
更易于实现信息的共享和保护
段页式存储管理
从逻辑上对内存容量进行扩充:程序运行之前无需全部装入内存,而仅需要将当前要运行的少量页面或者段先装入内存便可以运行,其余留在盘上。
程序的局部性原理
请求分页存储管理方式
影响缺页率的因素
- 页面大小:页面越大,缺页率越低
- 进程所分配的物理块数
- 页面置换算法
- 程序固有属性
页面置换算法:
抖动现象:不适当的置换算法,刚被换出的页面很快又被访问,频繁地更换页面。
抖动的预防措施:
- 采用局部置换:进程发生缺页时,只能从分配给自己的内存空间进行置换,不会对其他进程产生影响
- 把工作集融入到处理机调度中:
- 采用L=S准则调节缺页率:平均缺页时间,置换一个页面所需时间
- 选择暂停的进程
请求分段存储器管理
设备分配
设备分配的步骤
- 缓和CPU和I/O设备间速度不匹配矛盾
- 减少对CPU的中断频率
- 解决数据粒度不匹配问题
- 提高CPU和I/O设备之间的并行性
中断是程序并发的必要条件。如果没有中断,操作系统不能获得系统控制权,无法按调度算法对处机进行重新分配,一个程序将一直运行到结束而不会被打断。
在SPOOLING系统中,多台外围设备通过通道或DMA器件和主机与外存连接起来,作业的输入输出过程由主机中的操作系统控制。 操作系统中的输入程序包含两个独立的过程,一个过程负责从外部设备把信息读入缓冲区,另一个过程是写过程,负责把缓冲区中的信息送入外存输入井中。在系统输入模块收到输入作业输入请求后,输入管理模块中的读过程负责将信息从输入装置读入缓冲区。当缓冲区满时,由写过程将信息从缓冲区写到外存输入井中。读过程和写过程反复循环,直到一个作业输入完毕。当读过程读到一个硬件结束标志后,系统再次驱动写过程把最后一批信息写入外存并调用中断处理程序结束该次输入。然后,系统为该作业建立作业控制块JCB,从而使输入井中的作业进入作业等待队列,等待作业调度程序选中进入内存。
中断向量的内容是由操作系统程序确定的。向量的内容包括中断处理程序的入口地址和程序状态字(中断处理程序运行环境),中断处理程序是由操作系统装入内存的,操作系统将根据装入的实际地址和该中断处理程序的运行环境来填写中断向量。
便于设计安全可靠的操作系统。管态和目态是计算机硬件为保护操作系统免受用户程序的干扰和破坏而引入的两种状态。通常操作系统在管态下运行,可以执行所有机器指令;而用户程序在目态下运行,只能执行非特权指令。如果用户程序企图在目态下执行特权指令,将会引起保护性中断,由操作系统终止该程序的执行,从而保护了操作系统。
联机批处理:操作员将一批作业的卡片放到读卡机上,监督程序通过内存将这批作业传送到磁带机上,输入完成后,监督程序开始处理这批作业。它自动的将第一个作业读入内存,并对其程序进行汇编或编译,然后将产生的目标程序与所需要的例行子程序连接在一起,继而执行该程序,计算完成之后输出其结果。第一个作业处理完后立即处理第二个作业,如此反复直到所有作业处理完毕。然后,监督程序将第二批作业由读卡机传送到磁带机,重复以上过程。 脱机批处理:对联机批处理进行了改进。待处理的作业由卫星机负责经读卡机传送到输入磁带上,主机由输入磁带读入作业并加以处理,其结果送到输出磁带上,最后由卫星机负责将输出磁带上的结果信息在打印机上输出。 执行系统:对脱机批处理进行了改进,即引入了通道,作业由读卡机到磁带机的传输以及运行结果由磁带机到打印机的传输由通道完成。通道取代了卫星机,也免去了手工装卸磁带的麻烦。
从透明性上看,分布式操作系统优于网络操作系统。网络用户能够感觉到所访问的资源是在本地还是在远地;而在分布式系统中,用户感觉不到所访问的资源是否在本地,分布式操作系统掩盖了资源在地理位置上的差异。
从资源共享上看 ,分布式操作系统比网络操作系统能共享更多的资源。在网络操作系统中,一个计算任务不能由一台主机任意迁移到另外一台主机上运行;而在分布式操作系统中,所有作业可以由一台主机任意迁移到另外一台主机上处理,即可实现处理机资源的共享,从而达到整个系统的负载平衡。
中断发生时,被中断程序的现场信息已被压入系统堆栈中。而中断续元运行于目态,它执行完毕后将由用户堆栈区中恢复现场。 为此,操作系统在转到中断续元之前还应当将系统堆栈中的现场信息弹出并压入用户堆栈中,否则中断续元执行完毕后将无法恢复现场返回断点。
① 发生进程切换时一定发生中断。系统由一个运行进程转去运行另外一个进程,前提条件是必须进入操作系统,即处于系统态,因为处于用户态运行的进程不可能将cpu的使用权直接交给另一个进程,而中断是从用户态转换为系统态的必要条件。即中断是进程切换的前提(必要)条件。
② 发生中断时未必发生进程切换。如果中断处理完后原进程不再具有继续运行的条件,则一定会发生进程切换;反之,如果中断处理完后原进程仍具有继续运行的条件,则可能会发生进程切换,也可能不发生进程切换,这与处理机调度策略有关。
a. 用户级别线程
优点:(1)不依赖于操作系统,调度灵活;
(2)同一进程中的线程切换不需进入操作系统,切换速度快 缺点:(1)同一进程中多个线程不能真正并行,即使在多处理机环境中
(2)由于线程对操作系统不可见,调度在进程级别,某进程中的一个线程通过系统调用进入操作系统受阻,该进程的其它线程也不能运行
b. 核心级别线程
优点:(1)同一进程内多线程可以并行执行
(2)一线程进入核心等待,其它线程仍可执行 缺点:(1)系统开销大,同一进程内多线程切换速度慢 (2)调度算法不能灵活控制 c. 混合线程
优点:用户级线程系统不可见,系统级线程用户不可见,用户级线程与系统级线程之间通过轻进程建立联系,轻进程是用户和系统都可见的实体。
在内存没有空闲页架的情况下,需要按照置换算法淘汰一个内存页架,然后读入所缺页面,缺页进程一般需要等待两次I/O传输时间。若内存总保持一个空闲页架,当发生页故障时,所缺页面可以被立即调入内存,缺页进程只需等待一次I/O传输时间。读入后立即淘汰一个内存页面,此时可能也需执行一次I/O传输,但对缺页进程来说不需等待,因而提高了响应速度。
(1)覆盖技术是只将全局代码和数据静态地放在内存,其它部分分阶段地动态装入,后装入的对象重复使用以前对象所占有的空间,即覆盖以前的对象。动态装入的成分被称作覆盖。 解决程序大、空间小、装不下的问题。
(2)交换技术:每当发生进程切换时,总是将当前进程的所有代码、数据、栈全部从内存复制到外存(换出),再将新当前进程的所有代码、数据、栈全部从外存复制到内存(换入)。 解决程序多、空间小、装不下的问题。
在操作系统空间中保存有一组缓冲区,发送进程在执行send命令时,产生自愿性中断进入操作系统,操作系统为其分配一个缓冲区,并将所发送的消息内容由发送进程空间拷贝到缓冲区,然后将缓冲区连到接收进程的消息链中,便完成了发送。当接收进程执行到receive命令时,也产生自愿性中断进入操作系统,操作系统将载有消息的缓冲区由消息链中取出,并将消息内容拷贝到接收进程空间中,然后收回该空闲缓冲区,如此就完成了消息的接收。
a.资源独占:一个资源在同一时刻只能分配给一个进程。 b.不可剥夺:资源只能由占有者在使用完后自愿释放。
c.保持申请:进程在占有部分资源后还可申请新的资源,而且在申请新资源时并不释放已占有资源。
d.循环等待:存在一个进程等待序列{p1,p2,…,pn},其中p1等待p2所占有的某一资源,p2等待p3所占有的某一
资源,...,pn等待p1所占有的某一资源。
① 首址寄存器:存放当前执行指令的基地址。
② 限长寄存器:存放当前执行指令的长度。
③ 联想寄存器(快表):用于保存正在运行指令中的一部分项目。
在段式存储管理中,段的长度不能大于内存的长度,因为一个独立的段占用一段连续的内存空间,内存分配是以段为单位进行的,如果一个段的长度大于内存的长度,那么该段将无法调入内存。在段页式存储管理中,段的长度可以大于内存的长度。因为内存分配的单位是页,一个段内逻辑上连续的页面,可以分配到不连续的内存页面中,不要求一个段的所有逻辑页都进入内存。
(1)文件名是文件的外部名字,通常是一个符号名(字符串),同一文件可以有多个文件名(如通过link)。 (2)文件号是文件的内部名字,通常是一个整数,文件号与文件具有一对一的关系。
(3)文件描述符是文件打开时返回的整数(入口地址),对应用户打开文件表中的一个入口。同一文件可以被多个用户同时打开,此时返回的文件描述符一般不同。同一文件也可以被同一用户多次打开,每次打开时返回的文件描述符一般也不同。
首先,文件名是一个字符串,操作速度慢且占空间大,而文件描述符为一整数,其处理效率明显高于字符串。 其次,文件被打开后其控制信息 ( FCB )被缓冲到内存系统空间,文件描述符作为用户打开文件表中的入口地址直接与内存 FCB建立起联系,而文件名无法做到这一点。
用户打开文件表中包含以下内容: 文件描述符
打开方式
读写指针
系统打开文件表入口
由于文件是可共享的,多个进程可能会同时打开同一文件,而其打开方式可能是不同的,当前的读写位置通常也是不一样的。如果将这些信息合并到系统打开文件表中,就会导致一个共享文件占用多个系统打开文件表表目,这些表目的大部分内容是重复的。当一个进程对文件的操作导致FCB内容变化时,该进程关闭文件时就要将FCB回写到外存。增加了内外存传输的次数,也容易导致FCB内容的不一致。因此,通常将打开方式和读写指针记录在另外一个表,即用户打开文件表中。
① 公共目录:在系统中设有若干个可被所有用户访问的公共目录,将可被所有用户共享的文件登记在这些目录中,每个用户均可访问记录于这些目录中的文件,如此可实现用户对文件的共享。
② 连接:通过连接可使一个文件具有多个名字,不同用户可使用不同名称访问同一个文件,从而实现文件共享。对共享的限制通过对于连接的限制来实现。
③ 共享说明:每个文件在创建时由文件主规定一个共享说明。 20、常用的文件物理结构。
(1)顺序结构:一个文件占有若干个连续的物理块,其首块号及块数记录于文件控制块FCB中。 优点:速度快,节省空间 缺点:长度变化困难
(2) 链接结构:一个文件占若干个不连续的存储块,各块之间以指针相连,首块号及块数记录于该文件的控制块FCB中。优点:节省空间,长度变化容易。 缺点:随机访问速度慢。
(3)索引结构:一个文件占有若干个不连续的存储块,这些块的块号记录于一个索引块中。 优点:速度快,长度变化容易 缺点:索引块占空间
(4)散列结构:适用于定长记录和按键随机查找的访问方式,常用于构造文件目录。 (5)倒排结构:以键值和记录地址构成的索引结构 优点:适合于不同的查找方式,速度很快; 缺点:索引会带来较大的系统开销。
(1)记录式文件:记录的序列
a.等长记录(优点:处理方便,速度快;缺点:空间浪费) b.不等长记录(优点:省空间;缺点:处理不便,速度慢)
(2)流式文件:字节的序列
(1)程序控制查询方式:处理机代表进程向相应的设备模块发出I/O请求,处理机反复查询设备状态,直至I/O完成;可采用硬件提供的专用I/O指令,也可采取内存操作指令完成,其缺点是:忙式等待,效率较低。
(2)中断驱动方式:设备具有中断CPU的能力,可与CPU并行,既可采用硬件提供的专用I/O指令,也可采用内存映射I/O指令完成。其缺点是:当设备较多时,对CPU的打扰很多。
(3)DMA方式:硬件有DMA控制器,操作系统可采用DMA方式进行I/O操作,一个DMA可控制多个设备(并发)进行DMA传输,无论DMA位置何处,都可独立CPU直接访问总线。
(4)通道方式:通道是专门的处理机,有自己的指令系统,可实施复杂的I/O控制,一个通道程序可以控制若干设备进行多次IO传输,没有独立的存储空间,与主机共享同一个内存。
系统中设有两个缓冲池管理程序,分别用于缓冲区的分配和去配。设一个缓冲池中缓冲区的总数为 N,定义描述资源的信号量:buff_num,初值=N,对缓冲池的链操作需互斥进行,定义互斥信号量:mutex,初值=1。
a.执行P(buff_num),申请一个缓冲区,当buff_num≥0,表示有空闲缓冲区,可分配,否则,不分配。
b.执行P(mutex),表示对缓冲池的链操作需互斥进行。
c.执行V(buff_num),释放一个缓冲区,当buff_num≤0,表示有进程在等待空闲缓冲区,需将等待队列中的一个进程唤醒。
d.执行V(mutex),表示释放对缓冲池的互斥权,其他进程可访问缓冲区。
原文:https://www.cnblogs.com/GarrettWale/p/14411417.html