计算机基础知识——操作系统(1)
目录
- 进程和线程的区别
- 并行和并发的区别
- 用户态和核心态
- 进程调度算法有哪些
- 进程间有哪些通信方式
- 解释进程同步和互斥,如何实现
- 什么是死锁?如何预防死锁?
- 虚拟内存怎么理解?
- 线程同步的方式
- 介绍经典的锁
- 有哪些页面置换算法
一、进程和线程的区别
- 【进程】是资源分配和调度的基本单位。【线程】是程序执行的最小单位,线程是进程的子任务。一个进程可以有多个线程,线程间共享同一块内存。
- 每个进程都有自己的独立的内存空间,创建和销毁进程的开销较大,上下文切换开销大。线程间共享同一块内存,所以上下文切换开销小。
- 通信同步:进程间相互隔离,他们之间通信需要一些特殊机制,比如管道、消息队列等。由于线程间共享内存空调机,可以直接访问共享内存数据。
- 进程间相互隔离,一个进程的崩溃对其他进程的影响较小。一个线程错误可能会影响整个进程的稳定性。
二、并行和并发的区别
- 并行:同一时刻执行多个任务
- 并发:在相同时间段内执行多个任务,任务可能交替执行,通过调度实现。
- 多核CPU可以真正实现并行,但单核就只能并发。
三、用户态和内核态的区别
这两种状态是CPU为保护系统资源和实现权限控制的CPU运行级别。
- 用户态:程序只能访问受限的资源或指令集,不能直接访问操作系统核心部分,不能直接访问硬件资源。
- 内核态:进程可以直接访问硬件资源,执行系统调用、管理内存、文件系统等操作。
- 系统调用:当一个进程需要请求操作系统提供的服务时,会通过系统调用由用户态变为核心态。
- 异常、中断:当程序执行发生错误、外部设备产生中断信号。
四、进程调度算法有哪些?
- 先来先服务:按照请求顺序进行调度。但可能导致长作业阻塞短作业。
- 最短作业优先:非抢占式。按估计运行时间最短的顺序进行调度。但这样可能导致长作业“饥饿”。
- 最短剩余时间优先:基于最短作业的改进,抢占式的,按剩余运行时间的顺序进行调度。若新进程需要的时间比当前进程剩余的时间更短,则抢占先执行。
- 优先级算法:为每个进程分配一个优先级,按优先级进行调度。为了防止低优先级的进程永远等不到调度,会根据时间的推移动态调整优先级。
- 时间片轮转:为每个进程分配一个时间片,进程轮流执行。时间片用完后就自动切换到下一个。
- 多级队列算法:
- (抢占式)每个进程创建时被划分到某个固定队列,这些队列有优先级,系统会优先执行高优先级队列的任务,进程不能跨队列迁移。
- 多级反馈队列:初始时所有进程都从队列1开始,每个队列会划分一个时间片,若时间片耗尽但任务未完成,则被降级到下一队列。若长时间未获得调度,可能被提升回上一级(防止饥饿)。优点是更公平、更灵活。
五、进程间有哪些通信方式?
- 共享内存:一个进程创建共享内存段,并将其附加到自身地址空间,另一个进程也通过相同的key附加该段内存。这时两个进程在这段共享内存中直接读写数据。
- 管道:半双工,只能用于具有父子进程关系的进程间使用。父进程写入数据到内核中的缓存区,子进程读取。
- 命名管道:与管道类似,但它不允许在不相关的进程间通信。
- 消息队列:支持多对多通信,支持异步通信,无需亲缘关系的进程通信。
- 信号:用于发送通知到进程,告知其发生了某些事情。
- 信号量:是一个计数器,主要用于控制多个进程来访问同一个共享资源,通常作为一种锁机制。可以防止某进程在访问共享资源时,其他进程也访问该资源。
- Socket:允许本机两个进程或不同主机进程通信。主要用于客户端和服务器之间通过网络通信。支持全双工通信。
六、解释进程同步与互斥,如何实现
- 进程同步:多个并发执行的进程之间协调和管理他们的执行顺序,以确保按照一定的顺序或时间间隔执行。
- 进程互斥:同一时刻只允许一个进程访问某个共享资源。
- 方法一:信号量和PV操作
- 信号量表示系统中某种资源的状态或数量。P【检查信号量,若资源可用,则减少计数,然后使用该资源】。V【归还资源,增加信号量计数,并可能唤醒等待的进程】
- 方法二:临界区。
- 将可能引发互斥问题的代码成为临界区,里面包含需要互斥访问的资源。进入这个区域前要先获取锁,推出后释放锁。
- 方法三:互斥锁
- 每个共享资源都关联一个互斥锁,进程在访问该资源前都要获取互斥锁,使用完后释放锁。
- 方法四:条件变量+互斥锁
- 首先获得锁,判断条件若不满足则wait()自动释放锁+阻塞,等到线程改变条件时广播,唤醒等待进程。
七、什么是死锁?如何预防?
死锁指的是多个进程为了争夺同一个共享资源而造成的一种僵局。
- 互斥条件:一个进程占用某个资源,其他进程无法同时占用。
- 请求保持条件:一个线程因为请求某个资源而阻塞时,不会释放自己的资源。
- 不可剥夺条件:资源不可强制从一个进程中剥夺,只能由持有者资源释放。
- 循环等待条件:每个进程都在等待下一个进程占有的资源。
通过破坏死锁的四个必要条件之一来预防死锁。比如,破坏循环等待条件(所有进程按相同顺序来请求资源);检测死锁(通过检测系统中的资源分配来判断是否存在死锁)。解除死锁(检测到死锁存在,可以通过如抢占资源,终止某些进程或进行资源回收来解除死锁)。
八、虚拟内存
在每个进程创建加载的过程中,会分配一个连续的虚拟地址空间,它不是实际存在的,而是通过映射与实际物理地址空间对应,看起来每个进程有自己独立的连续地址空间,并且允许访问比物理地址内存更大的地址空间。
- 内存扩展:允许每个进程获得比实际物理内存更大的内存空间
- 内存隔离:虚拟内存提供了进程之间的内存隔离
- 内存管理(页面置换):当物理内存不足时,操作系统可以将部分数据从物理内存写入硬盘的虚拟内存中。当需要时又可以从虚拟内存中加载到物理内存。
九、线程同步的方式
- 互斥锁:同一时刻允许一个线程去访问被保护的临界区域
- 条件变量:通常与互斥锁一起使用。允许一个线程等待某个条件满足,而其他线程可以发出信号通知等待线程。
- 读写锁:允许多个线程同时读,但只允许一个线程写。
- 信号量:二进制信号量(相当于互斥锁)和计数型信号量。
十、介绍典型的锁
- 互斥锁:同一时刻只有一个线程能得到锁,然后访问资源。
- 自旋锁:基于忙等待的锁,即线程在尝试获取锁时会不断轮询,直到锁被释放。
- 读写锁:
- 悲观锁:在访问共享资源时都要上锁
- 乐观锁:先不管,修改了共享资源再说,若出现同时修改的情况,再放弃本次操作。
十一、页面置换算法
举例: 假设有3个物理页框,页访问序列是:A B C A D E,初始页框都为空。 1. LRU 当前页访问 页框内容 替换的页 说明 A A _ _ 无 空位置放 A B A B _ 无 空位置放 B C A B C 无 空位置放 C A A B C 无 A 已在内存,更新使用时间 D D B C 替 A A 最近访问最早,换掉 A E D E C 替 B B 最近最久没访问,换掉 B 👉 总共换页 2 次 2. Clock 当前访问 页框状态(R位) 替换页 说明 A A(1) _ _ 无 放入 A,设 R=1 B A(1) B(1) _ 无 放入 B,设 R=1 C A(1) B(1) C(1) 无 放入 C,设 R=1 A A(1) B(1) C(1) 无 命中,不变 D A(1) B(1) C(1) → A(0) B(0) C(0) → D(1) 替 A 扫一圈没 R=0 → 清零 → 换掉 A E D(1) B(0) C(0) → B(0) C(0) → E(1) 替 B B 的 R=0,替换 ✅ 总结对比 项目 LRU 时钟算法 (Clock) 是否精确 是(记录时间顺序) 否(只知道是否“近期用过”) 数据结构 链表、栈、队列 环形数组 + R 位 开销 较大 (频繁更新使用时间) 较小(只改 R 位 + 扫描) 实际表现 更接近理论最优 略逊色但性能好,系统中常用(如Linux)
- 最近最久未使用LRU:选择最长时间未被使用的页面进行置换。——缺点:要频繁更新每个页面的更新时间,开销太大。
- 时钟算法:核心思想是通过一个指针在环形链表上遍历,检查页面是否被访问过,当需要进行页面置换时,从时钟指针的位置开始遍历环形链表。若当前页面的访问位为0,表示该页面最久未被访问,可以选择置换,将访问位设置为1,继续遍历下一个页面。若找打页面为0的,就直接置换。
- 先进先出算法:最先进入内存的页面最先被置换出去。
- 最不经常使用LFU:淘汰访问次数最少的页面,考虑页面的访问频率。
- 最佳置换算法:根据未来的页面访问情况,选择最长时间不会被访问到的页面进行置换,但这是一种理想的算法,实际上做不到。
十二、select、poll和epoll的区别
I/O多路复用通常通过等系统调用来实现。
- select:早期多连接聊天室,20个用户在线聊天,每个连接都要监听是否有消息。但文件描述符数量有限,效率低。
- poll:局域网聊天程序,连接数多余1024仍然能支持。但每次轮询全部fd,效率不高。
- epoll:Nginx、Redis、mysql等系统内部常见。特点是支持“回调通知”,只处理有事件的fd,事件驱动型。
- kqueue:在macOS上的epoll替代。
- IOCP(Windows特有):Windows 上的 Web 服务、SQL Server、IIS、网游服务器,真正的异步模型,线程不会被阻塞在 I/O 上。
浙公网安备 33010602011771号