1 操作系统
-
定义:操作系统是用户和计算机的接口,同时也是计算机硬件和软件的接口。控制和管理整个计算机系统的硬软件资源,合理组织调度计算机的工作和资源分配。
-
多道程序处理:单个用户通常不能总是使得CPU和I/O设备都忙,多道程序设计通过组织作业(编码或数据)使CPU总有一个作业可执行(类比于律师在一段时间内不只为一个客户工作),从而提高了CPU的利用率。
-
分时系统:分时系统使多道程序设计的延伸。在分时系统中,虽然CPU还是通过在作业之间的切换来执行多个作业,但是由于切换频率很高,用户可以在程序运行期间与之进行交互。具有人机交互、多用户共享主机的优点。
-
实时系统:可以及时响应,并规定时间内完成,控制所有实时任务协调一致的运行(嵌入式系统)。
-
五大功能:
-
处理器管理
处理器管理最基本的功能是处理中断事件,配置了操作系统后,就可对各种事件进行处理。处理器管理还有一个功能就是处理器调度,针对不同情况采取不同的调度策略。
-
存储器管理
存储器管理主要是指针对内存储器的管理。主要任务是分配内存空间,保证各作业占用的存储空间不发生矛盾,并使各作业在自己所属存储区中不互相干扰。
-
设备管理
设备管理是指负责管理各类外围设备,包括分配、启动和故障处理等。主要任务是当用户使用外部设备时,必须提出要求,待操作系统进行统一分配后方可使用。
-
文件管理
文件管理是指操作系统对信息资源的管理。在操作系统中,将负责存取的管理信息的部分称为文件系统。文件管理支持文件的存储、检索和修改等操作以及文件的保护功能。
-
进程(作业)管理
每个用户请求计算机系统完成的一个独立的操作称为作业。作业管理包括作业的输入和输出,作业的调度与控制,这是根据用户的需要来控制作业运行的。
-
-
四大特征:
-
并发
两个或多个事件在同一时间间隔*** 内发生,区分于并行*:两个或多个事件在同一***时刻*** 发生
-
共享
系统中的资源可供内存中多个并发执行的进程共同使用。先定了时间(进程在内存期间)地点(内存)
-
虚拟
把通过某种技术将一个物理实体 变为若干个逻辑上的对应物的功能,通常用时分复用 和空分复用 实现
-
异步
在多道程序环境下,系统允许多个进程并发执行,以走走停停的方式执行的,并以不可预知的速度推进
-
2 进程
-
进程
具有一定独立功能的程序在一个数据集合上的一次动态执行过程。进程不只是程序代码还包括当前活动和堆栈段和数据段,还可能包括堆。
(强调:程序本身不是进程;程序只是被动实体,而进程是活动实体,他有一个程序计数器用来表示下一个要执行的命令和相关资源集合。当一个可执行文件被装入内存时,一个程序才能成为进程)
-
进程周期
-
进程调度
- 调度队列:进程进入系统时,会被加到作业队列中,该队列包括系统中的所有进程。驻留在内存中就绪的、等待运行的进程保存在就绪队列中。该队列通常用链表来实现,其头节点指向链表的第一个和最后一个PCB块的指针,每个PCB包括一个指向就绪队列的下一个PCB指针域。
- 调度:进程在其生命周期中会在各种调度队列之间迁移。
- 缓冲池:对于批处理系统,进程更多地是被提交,而不是马上执行,这些进程会被放到大容量存储设备(磁盘)的缓冲池中,以便后面执行。
- 长期调度程序或作业调度程序从该池中选择进程,并装入内存以准备执行。
- 短期调度程序或 CPU调度程序从准备执行的进程中选择进程,并为之分配CPU。
- 上下文切换:将CPU切换到另一个进程需要保存当前进程的状态并恢复另一个进程的状态。当发生上下文切换时,内核会将旧进程的状态保存在其PCB中,然后装入经调度要执行的并已保存的新进程的上下文。
-
进程通信
-
独立进程和协作进程
- 独立进程:一个进程不能影响其他进程或被其他进程影响(不与其他进程共享数据的进程)。
- 协作进程:一个进程能影响其他进程或被其他进程所影响(与其他进程共享数据的进程)。
-
需要提供环境允许协作进程的原因
- 信息共享:多个用户可能对同样的信息感兴趣,所以必须提供环境以允许对这些信息进行并发访问。
- 提高运算速度:将一个特定任务快速运行,必须将其分成子任务,每个子任务可以与其他子任务并行执行。要实现这个加速需要计算机有多个处理单元(CPU或I/O通道)
- 模块化:可能需要按模块化方式构造系统,可将系统功能分成独立进程或线程。
- 方便:单个用户也可能执行许多任务。
-
进程间通信的两种方式
-
共享内存
建立一块供协作进程共享的内存区域,进程通过向此共享区域读写数据来进行交换信息
共享内存比消息传递快,消息传递系统通常用系统调用来实现,因此需要更多的内核介入时间消耗,在共享内存系统中,仅在建立共享内存区域时需要系统调用,一旦建立了共享内存,所有的访问都被处理为常规的内存访问,不需要来自内核的帮助。
-
消息传递
通过在协作进程间交换消息实现通信,是以格式化的消息为单位的,通过系统提供的发送消息和接收消息两个原语进行数据交换。
-
-
消息传递对于交换较少数量的数据很有用,因为不需要避免冲突,对于计算机间的通信,消息传递也比共享内存更易于实现。
- **管道通信**
管道指用于连接一个读进程和一个写进程以实现它们之间通信的一个共享文件,又名pipe文件,主要是通过文件读写的方式。
实际操作中,管道分为:匿名管道、命名管道。匿名管道是一个未命名的、单向管道,通过父进程和一个子进程之间传输数据。匿名管道只能实现本地机器上两个进程之间的通信,而不能实现跨网络的通信。命名管道不仅可以在本机上实现两个进程间的通信,还可以跨网络实现两个进程间的通信。
-
进程同步
进程同步的任务就是对多个相关进程在执行顺序上进行协调,使并发执行的多个进程之间可以有效的共享资源和相互合作。进程间的通信可以通过调用原语send( )和receive( )来进行。消息传递可以是阻塞或非阻塞的——也称同步和非同步。
- 阻塞send:发送进程阻塞,直到消息被接收进程或邮箱接收。
- 非阻塞send:发送进程发送消息并再继续操作。
- 阻塞receive:接收者阻塞,知道有消息可用。
- 非阻塞receive:接收者收到一个有效消息或空消息。
-
pv操作
-
信号量S:用来记录资源数量,看是否能满足申请资源的操作。例如:S=3 表示三个可用空闲资源,S<0表示可用空闲资源无,进程申请要进入等待队列中。
-
P操作:申请资源操作;V操作:释放资源操作。
-
理发师问题:
一个理发师,一把理发椅,n把等候理发的顾客椅子,如果没有顾客则理发师便在理发椅上睡觉 ,当有一个顾客到达时,首先看理发师在干什么,如果理发师在睡觉,则唤醒理发师理发,如果理发师正在理发,则查看是否有空的顾客椅子可坐, 如果有,坐下等待,如果没有,则离开。
/*定义信号量 * 顾客信号:wait = 0; 理发师信号:barber = 1; * 当前顾客数:custNum; 互斥量: mutex = 1; */ //顾客操作: Customer(){ Coming; //顾客来到 P(mutex);//申请资源 if(custNum>0){ if(custNum<=n){//如果顾客有椅子 custNum++; V(mutex); //释放互斥量,表示理发开始 P(wait); //申请资源 }else{ //顾客没有等待椅子 V(mutex); //释放资源 离开; } }else{ //当前没有顾客 V(mutex) //释放资源 V(barber); 理发; 离开; P(mutex); custNum--;//顾客数-1 V(mutex); V(wait); } } //理发师进程: Barber(){ While(1){ P(mutex); if(custNum == 0){ V(mutex); P(Barber); }else{ V(mutex); 理发; } } }
-
3 线程
-
线程
线程是CPU使用的基本单元,它由线程ID、程序计数器、寄存器集合和栈组成。它与属于同一进程的其他线程共享代码段、数据段和其他操作系统资源,如打开文件和信号。传统重量级的进程只有单个控制线程,如果进程有多个控制线程,那么它能同时做多个任务。
-
多线程
-
多线程优点:
-
响应度高:
如果对一个交互程序采用多线程,那么即使其部分阻塞或执行较冗长的操作,该程序仍然能继续执行,从而增加了对用户的响应程度。(例如多线程Web浏览器在用一个线程装入图象时能通过另一个线程与用户交互)
-
资源共享:
线程默认共享他们所属进程的内存和资源。代码和数据共享的优点是他能允许一个应用程序在同一地址空间有多个不同的活动线程。
-
经济:
进程创建所需要的内存和资源的分配比较昂贵,由于线程能共享他们所属进程的资源,所以创建和切换线程会更为经济。
-
利用多处理器体系结构:
充分使用多处理器体系结构,以便每个进程能并行运行在不同的处理器上,不管有多少CPU,单线程进程只能运行在一个CPU上,在多CPU上使用多线程加强了并发功能。
-
-
-
多线程模型
-
多对一模型
将许多用户级线程映射到一个内核线程。线程管理是由线程库在用户空间进行的,因为效率比较高,但是如果一个线程执行了阻塞系统调用,那么整个进程都会阻塞。而且因为任一时刻只有一个线程能访问内核,多个线程不能并行运行在多个处理器上。
-
一对一模型
将每个用户线程映射到一个内核线程。该模型在一个线程执行阻塞系统调用时,能允许另一个线程继续执行。所以提供了比多对一更好的并发功能。也允许多个线程能并行地运行在多处理器系统上。唯一缺点是每创建一个用户线程就需要创建一个相应的内核线程(限制线程数量)。
-
多对多模型
多对一模型允许开发人员创建任意多的用户线程,但是因为内核一次只能调度一个线程,所以并没有增加并发性。开发人员可创建任意多的用户线程,并且响应内核线程能在多处理器系统上并发执行。当一个线程执行阻塞系统调用时,内核能调度另一个线程来执行。
-
-
线程同步
参考 Java线程:线程的同步与锁
-
互斥量(Synchronized/Lock)
-
对于同步方法:使用Synchronized关键字修饰方法,(由于Java的对象都会有一个内置锁,当用此关键字修饰方法时,内置锁会保护整个方法,所以在调用该方法前需要获得内置锁,否则处于阻塞状态)
public synchronized void fun() { ......; }
-
对于同步代码块:使用synchronized修饰代码块,该块会自动被加上内置锁,从而实现同步。
public void fun() { synchronized (this) { ......; } }
-
-
信号量(Semphare)
允许同一时刻多个线程访问同一资源,但是需要控制同一时刻访问此资源的最大线程数量
-
事件/信号(Wait/Notify)
通过通知操作的方式来保持多线程同步,还可以方便的实现多线程优先级的比较操作
-
-
线程池
线程池的主要思想是在进程开始时创建一定数量的线程,并放入到池中以等待工作。当服务器收到请求,他就会唤醒池中的一个线程(如果当前有可用线程),并将要处理的请求传递给他,一旦线程完成了服务,他就会返回到池中再等待工作。如果池中没有可用的线程,服务器会一直等待直到有空线程。
- 线程池优点
- 通常用现有的线程去处理请求比等待创建新的线程要快。
- 线程池限制了在任何时候可用线程的数量。(对不能支持大量并发线程的系统非常重要)
- 线程池中的线程数量由系统CPU的数量、物理内存的大小和并发客户请求的期望值等因素决定。
- 线程池优点
-
线程和进程之间的联系
- 区别
- 进程有独立的地址空间、线程没有。
- 每个独立的进程程有一个程序运行的入口、顺序执行序列和程序的出口。但线程不能够独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制。
- 进程在执行过程中拥有独立的内存单元,而多个线程共享内存,从而极大地提高了程序的运行效率。
- 进程是资源分配的最小单位,线程是CPU调度的最小单位
- 通信方式不同,线程之间的通信比较方便,进程之间的通信只能通过进程通信的方式进行
- 进程上下文切换开销大,线程开销小
- 一个进程挂掉了不会影响其他进程,而线程挂掉了会影响其他线程
- 联系
- 一个程序至少有一个进程,一个进程至少有一个线程,一个线程只能属于一个进程。
- 线程的划分尺度小于进程,使得多线程程序的并发性高
- 资源分配给进程,同一进程的所有线程共享该进程的所有资源。
- 线程在执行过程中,需要协作同步。不同进程的线程间要利用消息通信的办法实现同步
- 区别
4 CPU调度
-
调度
-
定义
在一个进程必须等待的时间内,另一个进程可以拿走CPU的使用权。即每当CPU空闲时,操作系统必须从就绪队列中选择一个进程来执行。
-
发生情况
- 当一个进程从运行状态切换至等待状态(例如I/O请求,或调用wait等待一个子程序的终止)
- 当一个进程从运行状态切换到就绪状态(例如出现中断时)
- 当一个进程从等待状态切换到就绪状态(例如I/O完成)
- 当一个进程终止时。
-
抢占和非抢占
-
抢占式
操作系统将正在运行的进行强行暂停,由调度程序将CPU分配给其他就绪进程的调度方式。
-
非抢占式
一旦CPU分配给一个进程,那么该进程会一直使用CPU直到进程终止或切换到等待状态。
-
-
-
调度算法
-
先到先服务调度(FCFS)
先请求先分配
-
最短作业优先调度(SJF)
平均等待时间最短,但难以知道下一个CPU区间长度,SJF 是最优的算法,但是有致命缺陷:无法预测需要的 CPU 运行时间而且会导致“饥饿”(长作业一直得不到调度)
-
最短剩余时间优先(SRTF)
抢占式的 SJF 算法
-
优先级调度
优先级越高越先分配到CPU,相同优先级先到先服务,存在的主要问题是:低优先级进程无穷等待CPU,会导致无穷阻塞或饥饿;
-
转轮法调度(RR)
每个进程被分配一个时间段,称作它的时间片,即该进程允许运行的时间。如果在时间片结束时进程还在运行,则cpu将被剥夺并分配给另一个进程。如果进程在时间片结束前阻塞或结束,则cpu当即进行切换。
-
多级队列调度
将就绪队列根据进程的属性(如内存大小、进程优先级、进程类型)分成多个独立队列(永久分配)。
-
多级反馈队列调度
根据先来先服务原则给就绪队列排序,为就绪队列赋予不同的优先级数,不同的时间片,按照优先级抢占CPU。
-
5 死锁
-
死锁
在多道程序环境下,多个进程可能竞争一定数量的资源,某个进程申请资源,如果这时资源不可用,那么该进程进入等待状态。如果所申请的资源被其他等待进程占有,那么该等待进程有可能再也无法改变其状态。
-
死锁特征
-
必要条件
- 互斥:至少有一个资源必须处于非共享模式,即一次只有一个进程使用。如果另一个进程申请该资源,那么申请进程必须等到资源被释放为止。
- 占有并等待:一个进程必须占有至少一个资源,并等待另一资源,而该资源为其他进程所占有。
- 非抢占:资源不能被抢占,即资源只能在进程完成任务后自动释放。
- 循环等待:有一组等待进程{P0,P1,P2,…Pn},P0等待的资源被P1所占有,P1等待的资源被P2所占有…Pn等待的资源被P0所占有。
必须同时满足以上四个条件才会出现死锁。
-
-
处理方法
- 可使用协议以预防或避免死锁,确保系统不会进入死锁状态
- 避免死锁:系统对申请资源的进程进行动态检查,如果可能发生死锁则不分配资源,否则分配。
- 预防死锁:破坏必要条件中的任意一个(除了资源互斥没办法避免。例如“非抢占”条件,进程不能获得所需要的全部资源时便处于等待状态,等待期间他占有的资源将被隐式的释放重新加入到 系统的资源列表中,可以被其他的进程使用)
- 发生死锁时,检测和恢复死锁
- 死锁检测:通过调用检测算法以确定是否出现死锁(较为复杂,没明白算法)
- 死锁恢复:通过抢占某些死锁进程的资源以恢复。
- 可使用协议以预防或避免死锁,确保系统不会进入死锁状态
6 内存管理
csdn看到的写的比较好的内存管理博客 操作系统-内存管理
-
内存
内存通常分为两个区域:一个驻留操作系统,一个用于用户进程,通常需要将多个进程同时放到内存中,因此需要考虑如何为输入队列中需要调入内存的进程分配内存空间。采用连续内存分配时,每个进程位于一个连续的内存区域。
-
内存分配
多分区方法:一个分区空闲时,可以输入队列中的一个进程,以调入空闲分区,当进程终止时,其分区可以被其他进程所使用。
-
分页
帧:实现分页的基本方法涉及将物理内存分为固定大小的块,成为帧。
页:将逻辑内存也分为同样大小的块,称为页。
当需要执行进程时,其页从备份存储中调入到可用的内存帧中,备份存储也分为固定大小的块,其大小与内存帧一样。
页号映射为物理块号:需要一个页表来记录逻辑地址和实际存储地址的映射关系,以实现从页号到物理块号的映射。(hashMap)
-
分段
分段可以满足在编写代码时的一些逻辑需求,是一种符合用户视角的内存分配管理方案。逻辑地址空间是由一段组成的,每个段都有名称和长度,地址指定了段名称和段内偏移。(用户通过两个量来指定地址:段名称和偏移)
-
分页和分段的区别
该部分借鉴于 操作系统面试问题集锦 第7题
- 段式存储管理是一种符合用户视角的内存分配管理方案。在段式存储管理中,将程序的地址空间划分为若干段(segment),如代码段,数据段,堆栈段;这样每个进程有一个二维地址空间,相互独立,互不干扰。段式管理的优点是:没有内碎片(因为段大小可变,改变段大小来消除内碎片)。但段换入换出时,会产生外碎片(比如4k的段换5k的段,会产生1k的外碎片)
- 页式存储管理方案是一种用户视角内存与物理内存相分离的内存分配管理方案。在页式存储管理中,将程序的逻辑地址划分为固定大小的页(page),而物理内存划分为同样大小的帧,程序加载时,可以将任意一页放入内存中任意一个帧,这些帧不必连续,从而实现了离散分离。页式存储管理的优点是:没有外碎片(因为页的大小固定),但会产生内碎片(一个页可能填充不满)。
- 两者的不同点:
- 目的不同:分页是由于系统管理的需要而不是用户的需要,它是信息的物理单位;分段的目的是为了能更好地满足用户的需要,它是信息的逻辑单位,它含有一组其意义相对完整的信息;
- 大小不同:页的大小固定且由系统决定,而段的长度却不固定,由其所完成的功能决定;
- 地址空间不同: 段向用户提供二维地址空间;页向用户提供的是一维地址空间;
- 信息共享:段是信息的逻辑单位,便于存储保护和信息的共享,页的保护和共享受到限制;
- 内存碎片:页式存储管理的优点是没有外碎片(因为页的大小固定),但会产生内碎片(一个页可能填充不满);而段式管理的优点是没有内碎片(因为段大小可变,改变段大小来消除内碎片)。但段换入换出时,会产生外碎片(比如4k的段换5k的段,会产生1k的外碎片)。
7 虚拟内存
-
虚拟内存
如果存在一个程序,所需内存空间超过了计算机可以提供的实际内存,那么由于该程序无法装入内存所以也就无法运行。单纯的增加物理内存只能解决一部分问题,但是仍然会出现无法装入单个或者无法同时装入多个程序的问题。但是可以从逻辑的角度扩充内存容量,即可解决上述两种问题。
整理内容来源:《操作系统概念 第7版》 高等教育出版社 郑扣根 译