操作系统
1 操作系统概述
操作系统是管理和控制计算机系统中各种硬件和软件资源、合理地组织计算机工作流程的系统软件,是用户与计算机之间的接口。
操作系统的四个特性
- 并发:同一段时间内多个程序执行(注意区别并行和并发,前者是同一时刻的多个事件,后者是同一时间段内的多个事件);
- 共享:系统中的资源可以被内存中多个并发执行的进线程共同使用;
- 虚拟:通过时分复用(如分时系统)以及空分复用(如虚拟内存)技术实现把一个物理实体虚拟为多个;
- 异步:系统中的进程是以走走停停的方式执行的,且以一种不可预知的速度推进。
操作系统最基本的特征是并发和共享,两者互为存在条件。
操作系统的五大功能
- 处理机管理:处理机分配都是以进程为单位,所以处理机管理也被看做是进程管理。包括进程控制,进程同步,进程通信和调度(作业调度和进程调度)
- 存储器管理(或者内存管理):内存分配,内存保护,地址映射,内存扩充
- 设备管理:管理所有外围设备,包括完成用户的IO请求;为用户进程分配IO设备;提高IO设备利用率;提高IO速度;方便IO的使用
- 文件管理:管理用户文件和系统文件,方便使用同时保证安全性。包括:文件存储空间管理,目录管理,文件读写管理以及文件共享和保护
- 提供用户接口:程序接口(如API)和用户接口(如GUI)
2 进程
进程的定义
进程:指在系统中能独立运行并作为资源分配的基本单位,它是由一组机器指令、数据和堆栈等组成的,是一个能独立运行的活动实体。
进程只能由父进程建立,系统中所有的进程形成一种进程树的层次体系;挂起命令可由进程自己和其他进程发出,但是解除挂起命令只能由其他进程发出。
进程的状态
- 创建状态:进程在创建时需要申请一个空白PCB,向其中填写控制和管理进程的信息,完成资源分配。如果创建工作无法完成,比如资源无法满足,就无法被调度运行,把此时进程所处状态称为创建状态
- 就绪状态:进程已经准备好,已分配到所需资源,只要分配到CPU就能够立即运行
- 执行状态:进程处于就绪状态被调度后,进程进入执行状态
- 阻塞状态:正在执行的进程由于某些事件(I/O请求,申请缓存区失败)而暂时无法运行,进程受到阻塞。在满足请求时进入就绪状态等待系统调用
- 终止状态:进程结束,或出现错误,或被系统终止,进入终止状态。无法再执行
进程的特性
- 动态性:进程的实质是程序的一次执行过程,进程是动态产生,动态消亡的。
- 并发性:任何进程都可以同其他进程一起并发执行。
- 独立性:进程是一个能独立运行的基本单位,同时也是系统分配资源和调度的独立单位。
- 异步性:由于进程间的相互制约,使进程具有执行的间断性,即进程按各自独立的、不可预知的速度向前推进。
进程的同步、互斥和通信
参考:进程的同步、互斥、通信的区别,进程与线程同步的区别
进程的互斥、同步都是在并发进程下存在的概念。有了并发进程,就会产生资源的竞争与协作,则这些进程之间存在两种基本关系:竞争关系和协作关系。
- 为了解决进程间竞争关系(间接制约关系)引入进程互斥;
- 为了解决进程间松散的协作关系(直接制约关系)引入进程同步;
- 为了解决进程间紧密的协作关系引入进程通信。
a 竞争关系 和 进程互斥
由于创建了多个进程,这些进程共享计算机的资源。而对于一些独占型(就是同一时刻只能有一个进程在占有这些资源)的资源,则会引发进程之间的竞争。
资源竞争出现两种控制问题:死锁和饥饿
- 死锁:是指两个或两个以上的进程(或线程)在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程。
Java中产生死锁的最根本原因是: 一、是多个线程涉及到多个锁,这些所存在着交叉,所以可能会导致了一个锁以来的闭环;二、默认的锁申请操作是阻塞的。例如:进程在获得一个锁L1的情况下再去申请另外一个锁L2,即L2想要包含L2。在获得了L1,且没有释放L1的情况下又去申请L2,这是产生死锁的最根本原因。
死锁产生的四个必要条件:
①互斥条件:进程对于所分配到的资源具有排它性,即一个资源只能被一个进程占用,直到被该进程释放
②请求和保持条件:一个进程因请求被占用资源而发生阻塞时,对已获得的资源保持不放。
③不剥夺条件:任何一个资源在没被该进程释放之前,任何其他进程都无法对他剥夺占用
④循环等待条件:当发生死锁时,所等待的进程必定会形成一个环路(类似于死循环),造成永久阻塞。
避免死锁的三种技术:
①加锁顺序(线程按照一定的顺序加锁):如果能确保所有的线程都是按照相同的顺序获得锁,那么死锁就不会发生。
②加锁时限:在尝试获取锁的时候加一个超时时间,这也就意味着在尝试获取锁的过程中若超过了这个时限该线程则放弃对该锁请求。若一个线程没有在给定的时限内成功获得所有需要的锁,则会进行回退并释放所有已经获得的锁,然后等待一段随机的时间再重试。这段随机的等待时间让其它线程有机会尝试获取相同的这些锁,并且让该应用在没有获得锁的时候可以继续运行
③死锁检测:主要是针对那些不可能实现按序加锁并且锁超时也不可行的场景。每当一个线程获得了锁,会在线程和锁相关的数据结构中将其记下。除此之外,每当有线程请求锁,也需要记录在这个数据结构中。当一个线程请求锁失败时,这个线程可以遍历锁的关系图看看是否有死锁发生。 - 饥饿:指这样