操作系统闲谈06——进程管理
一、进程调度
01 时间片轮转
给每一个进程分配一个时间片,然后时间片用完了,把cpu分配给另一个进程
时间片通常设置为 20ms ~ 50ms
02 先来先服务
就是维护了一个就绪队列,每次选择最先进入队列的进程,然后一直运行,直到进程退出或者被阻塞,然后继续从队列中选择一个进程接着运行
不利于 短作业进程
03 优先级调度
高响应比优先调度
主要权衡了长作业和短作业
每次计算响应比优先级
短作业优先调度
从就绪队列中挑选运行时间最短的进程来运行
高优先级调度
从就绪队列中挑选进程优先级最高的先运行
二、进程通信
01 管道
分为匿名管道和有名管道
匿名管道 用于有父子亲缘关系的进程之间的通信
有名管道 则是打破了父子亲缘关系的限制
不管是匿名管道还是有名管道 通信的方向都是单向的 通信数据遵循先进先出的原则
02 消息队列
管道传输数据的大小有限制、并且数据是无格式的字节流
在内核维护了一个消息链表 消息队列的消息体可以是用户自定义的数据类型,采用消息队列进程进程通信
03 共享内存
由于消息队列每次数据的写入和读取都需要经过用户态和内核态的拷贝
引入了共享内存 它是IPC通信最快的方式
直接分配了一个共享空间,每个进程都可以访问
04 信号量
共享内存确实加快了IPC通信的速度,但是也带来了新的问题,就是多个进程同时竞争共享资源引起的数据的错乱
引入了信号量 它主要设置了信号量来保护共享资源,设置两个原子操作,P操作,V操作,用于进程的互斥和同步
05 信号
然后还要IPC通信中的异步通信方式 信号
主要分为软件触发和硬件触发
软件触发 例如 kill
硬件触发 例如 键盘的 ctrl C
06 socket
C/S架构 用于不同主机的进程进行通信
常见的基于TCP的Socket网络通信模型
三、互斥与同步
01 互斥
进程互斥
- 信号量:使用信号量可以在多个进程间实现互斥,信号量是一个整数值,用于计数,在多个进程对共享资源进行访问时,可以通过对信号量的操作来实现互斥。
- 互斥锁:互斥锁是一种常用的互斥机制,可以实现对共享资源的独占访问。
- 管程:管程是一种特殊的进程,它可以管理多个其他进程对共享资源的访问,通过管程的锁定和解锁机制,可以实现互斥。
线程互斥
- 互斥锁:互斥锁是最常用的线程同步机制,可以保证多个线程对共享资源的独占访问。
- 信号量:信号量是一种用于线程同步的机制,它可以用于控制多个线程对共享资源的访问。
- 原子操作:原子操作是一种无需加锁即可实现线程间同步的方法,其特点是操作不可中断。
02 同步
进程同步
- 信号量:信号量是一种用于实现进程间同步的机制,通过对信号量的操作来实现同步。
- 信号:信号是一种异步通信机制,可以在进程间传递信息,以实现同步。
- 消息队列:消息队列是一种内核态的通信机制,可以在不同进程间传递消息。
线程同步
-
信号量(Semaphore):信号量是一种用于线程间同步的机制,通过对信号量的操作来实现同步。
-
条件变量(Condition Variable):条件变量是一种用于线程间协作的同步机制,通过等待和唤醒来实现同步。
-
读写锁(Read-Write Lock):读写锁是一种用于保护共享资源的同步机制,支持多个读线程同时访问,但只允许一个写线程访问。
四、锁
01 锁的基本类型
互斥锁
互斥锁(Mutex):互斥锁是最常见的同步机制,它可以在多线程中保证任意时刻只有一个线程能够访问某个共享资源,从而保证数据的完整性和一致性。
多了线程切换的开销
自旋锁
自旋锁(Spinlock):自旋锁也是一种同步机制,与互斥锁类似,但是自旋锁会一直占用CPU资源,直到获得锁为止,因此当竞争激烈的时候会导致大量的CPU浪费。
读写锁
读写锁是一种特殊的同步机制,它可以同时允许多个读者线程同时访问某个共享资源,但是当有写者线程要修改该共享资源时,就必须阻塞读者线程,从而保证数据的一致性。
02 死锁
死锁的条件
- 互斥条件:一个资源每次只能被一个进程使用。
- 请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。
- 不剥夺条件:进程已获得的资源,在未使用完之前,不能强行剥夺。
- 循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。
如何解决死锁
-
预防死锁:通过一些方法防止系统出现死锁,例如请求资源的顺序,使用银行家算法。
-
避免死锁:通过动态调整系统的状态来避免死锁,例如释放资源。
-
检测死锁:通过定期检测死锁的情况,以便及时解决死锁。
检测死锁的方法有以下几种:
- 资源分配图法:该方法通过分析系统的资源分配图,以检测系统是否存在死锁。资源分配图法通过建立一个描述系统资源分配关系的图,然后寻找图中的环,如果存在环,则说明存在死锁。
- Wound-Wait法:该方法通过记录每一个进程的等待次数和被放弃的次数,来判断是否存在死锁。如果一个进程的等待次数大于0,而该进程被放弃的次数为0,则说明该进程处于死锁状态。
- 银行家算法:该算法是一种预防死锁的方法,也可以用来检测死锁。该算法在每一个进程申请资源之前,先检查系统的资源分配情况,以确定该进程是否能够获得所需的资源。如果系统中存在资源分配不合法的情况,则说明存在死锁。
以上是检测死锁的三种方法,每一种方法都有其优势和劣势,具体使用哪种方法需要根据实际情况来决定。
- 解除死锁:通过撤销一些进程,使系统恢复正常状态。
五、多线程与多进程
01 进程、线程、协程
进程、线程和协程都是并发编程中的重要概念,它们在实现多任务处理时有着不同的作用和特点。
- 进程
进程是操作系统中分配资源的基本单位,一个进程包含程序代码、数据和内存空间等资源,每个进程都拥有独立的地址空间和系统资源,进程之间互不干扰,通信需要使用进程间通信(IPC)机制。
进程之间的切换需要进行上下文切换,会产生较大的开销。多进程适合处理不同任务之间的并行处理,可以充分利用多核 CPU 的性能。
- 线程
线程是进程内的一个执行单元,一个进程可以包含多个线程,线程共享进程的资源,包括内存空间、文件句柄、网络连接等。
不同线程之间的切换需要进行上下文切换,但相对于进程来说,线程的创建和销毁开销较小。线程之间的数据共享相对容易,但也需要注意线程安全和同步问题。多线程适合处理单个任务的并发执行,可以提高程序的执行效率。
- 协程
协程是一种轻量级的线程,它是一种用户态的线程,不需要操作系统的参与,可以在单个线程中实现多个任务的并发执行。协程在执行过程中可以自由切换执行上下文,不需要进行系统调用,因此切换开销较小。
协程之间的数据共享相对简单,但也需要注意同步和互斥问题。协程适合处理大量的 I/O 操作,比如网络通信和文件读写等,可以提高程序的响应速度。
综上所述,进程、线程和协程都有各自的优点和适用场景,需要根据具体的任务需求选择合适的并发编程方式。
02 多进程与多线程
- 定义
首先在定义方面。
多进程是指同时运行多个程序,每个程序都拥有自己独立的虚拟地址空间,相互之间不影响。
多线程是指在同一个程序中,同时运行多个独立的线程,每个线程都可以访问程序的共享内存空间,不同线程之间可以共享数据。
- 资源开销
多进程在创建和销毁进程时会产生较大的开销。
而多线程在同一进程中共享资源,因此创建和销毁线程的开销相对较小
- 数据共享
多进程之间的数据通信通常需要使用进程间通信(IPC)机制,如管道、消息队列等,开销较大;
而多线程之间可以直接共享进程的内存空间,数据共享相对简单。
- 并发性
由于多进程之间相互独立,因此它们的执行是并行的,可以充分利用多核 CPU 的性能;
而多线程之间共享 CPU 资源,因此它们的执行是并发的,需要通过线程调度算法来实现多线程之间的切换。
多线程在同一进程中共享资源,因此创建和销毁线程的开销相对较小