文章目录
操作系统的特点
-
并发
并发和并行的区别。并发是在一段时间内,多个操作均有进行。并行是在同一时刻,多个操作同时进行。并行需要物理系统的支持,如多核处理器、分布式计算系统等。操作系统通过进程和线程的概念实现了并发。
-
共享
系统中的资源可以被过个进程共同使用。
互斥共享与同步共享。 互斥资源也被称作是临界资源,同一时刻只能有一个进程访问,需要使用同步机制来实现互斥访问。
-
虚拟
把物理实体转换为逻辑实体。
计算资源和存储空间的虚拟。 在单核CPU上做到了时分复用,多个进/线程并发执行。在内存上,实现了空分复用,通过逻辑地址和换页算法实现了虚拟内存。
-
异步
程序并不是一次性执行完毕,走走停停,以不可知的速度前进。
操作系统的功能
操作系统的主要硬件:CPU,内存,硬盘,外设
分别对应操作系统的功能:
- 进程管理,对应CPU
- 进程控制、进程创建、同步、通信
- 内存管理,对应内存
- 内存分配、地址映射、内存保护与共享、虚拟内存
- 文件系统管理,对应硬盘
- 空间管理、目录管理,读写保护
- 设备管理,对应外设
- 完成I/O请求,
- 缓存还礼、设备分配处理、虚拟设备
内核态与用户态
如果进程在用户态需要使用系统功能,就进行系统调用陷入内核态,由操作系统完成。
Linux系统调用:
- 进程控制:fork, exit, wait
- 进程通信:pipe, shmget, mmap
- 文件操作:open, read, write
- 设备操作:ioctl, read, write
- 信息维护:getpid, alarm, sleep
- 安全:chmod, umask, chown
进程与线程的概念、区别
进程是对运行时程序的封装,并且是资源分配的最小单位,线程是CPU调度的最小单位。
最重要有四个方面的区别:
- **从层级上说:**进程包含线程,线程是进程的子任务,一个线程只属于一个进程,但一个进程包含多个线程。
- 从内存资源上说:不同的进程有各自独立的内存空间。而一个进程的线程间共享进程的内存资源。虽然多个线程共享 代码段、数据段、堆,但是每个线程有自己独立的栈用于存放局部变量和临时变量。
- **从系统开销上说:**进程的创建以及切换 的开销是比 线程要大的,因为创建时需要分配资源、切换时需要保存CPU运行环境,线程创建与切换一般不涉及这样的操作。
- **从相互通信上说:**线程间的通信由于共享内存变得容易,那进程的话,需要采用消息队列、信号量等手段。
为什么要有进程或线程
进程同步
1.临界区
对临界资源进行访问的那段代码称为临界区
未来路互斥访问临界资源,每个进程在进入临界区前,需要进行检查
2.同步与互斥
- 同步:多个进程因合作产生制约关系,使得进程有一定的先后执行关系
- 互斥:多个进程在同一时刻只有一个能进入临界区
3.信号量
是一个整型变量,可对其进行 down 和 up操作,对应 P(减)和 V(增)操作。
- P:如果信号量大于0,则减1;如果信号量等于0,则 让进程睡眠,等待信号量大于0
- V:对信号量加1,唤醒睡眠的进程,让其完成P操作。
- P和V操作都是原子操作,在执行时屏蔽中断。
- 如果信号量只取0或1,那么就成了互斥量 Mutex,0表示临界区已加锁,1表示解锁
4.管程
- 信号量的缺点:客户端需要做很多控制,容易出错。
- 管程:把控制代码独立出来,不容易出错,且客户端代码调用更容易。
- 在一个时刻只有一个进程能够使用管程,进程在不满足管程的条件变量时,会阻塞挂起,让出管程让下一个进程使用。
- 采用条件变量的概念,以及wait() 和 signal() 来实现同步操作。对条件变量执行 wait() 操作会导致调用进程阻塞,把管程让出来给另一个进程持有。signal() 操作用于唤醒被阻塞的进程。
进程间的通信
进程通信和进程同步的区别:同步是控制多个进程按一定顺序执行,通信是进程间传输信息,通信是手段,同步是目的。
方式包括:管道、系统(IPC*,Inter-Process Communication)*(消息队列、信号量、信号、共享内存)、套接字
1.管道
- linux通过调用pipe函数创建管道,是内核操作,系统调用
- 普通无名管道PIPE
- 用于具有亲缘关系的父子进程间的通信
- 半双工,数据某时刻只能在一个方向是流动,单向交替传输
- 特殊的文件形式,但不是普通文件,不属于文件系统,只存在于内存中
2.FIFO
- 命名管道FIFO:除管道功能外,还允许无亲缘关系进程间的通信
- 有路径名与之关联,以一种特殊设备文件形式存在于文件系统中
3.消息队列
- 消息的链接表,存放在内核中,独立于进程而存在。
- 消息队列克服了信号传递信息少,管道只能承载无格式字节流及缓冲区大小受限等特点。
- 不需要进程提供同步方法,进程可以有选择地接收消息
4.信号量
-
是一个计数器,用于为多个进程提供对共享数据对象的访问。
-
信号量用于实现进程间的互斥与同步,而不是存储进程间的通信数据。
-
信号量用于进程间同步,若要在进程间传递数据,需要结合共享内存。
-
信号量基于系统的PV操作,程序对信号量的操作都是原子操作。
5.信号
是一种比较复杂的通信方式,用于通知进程某个事件已经发生。
是软件层面的中断机制,软中断,不能传递数据。
6.共享内存
多个进程访问同一块内存空间,不同进程可以及时看到数据的更新。但是需要依靠同步操作,如互斥锁和信号量。信号量+共享内存通过结合起来使用,信号量用来同步对共享内存的访问。
7.套接字
socket用于不同主机机器间的进程通信
线程间的通信??对吗
1.临界区
多线程的串行化来访问公共资源或代码,速度快,适合控制数据访问
2.互斥量
采用互斥机制,只有拥有互斥 对象的线程才有权限,因为互斥对象只有一个,可以保证资源不被多个线程同时访问
3.信号量
为控制具有优先数量的用户资源而设计,允许多个线程同时刻访问资源,但是需要限制同时刻访问资源的最大线程数目。
4.事件/信号
通过通知操作的方式保存多线程同步
linux 虚拟地址空间
操作系统中程序的内存结构
缺页中断
fork和 vfork的区别
并发和并行的区别
页表寻址
死锁条件和如何解决死锁
操作系统
信号量与条件变量会怎么考
LRU编程实现
进程与线程的区别
- 最小单位区别,进程内存分配,线程CPU调度
- 内存资源的区别
- 系统开销的区别,特别是切换
- 内部通信的区别
- 层级的区别,进程间相互不影响,线程挂了会导致进程中其他线程也挂掉
- 适用场景:多进程适合于CPU密集型,多线程适合于I/O密集型,不必因为I/O阻塞导致频繁的进程切换。
线程模型
- future模型
- fork join 模型
- actor模型
- 生产者消费者模型,使用缓存来保存任务
- master-worker模型
缺页置换算法
虚拟内存的机制,在程序运行过程中,不会讲所有的资源都放入内存中,而是通过请求分页机制实现。
如果访问的页面不在内存中,产生缺页中断,如果此时操作系统内存没有空闲页面,则必须在内存中选择一个页将其移出,选择淘汰哪一页的规则叫做页面置换算法。
换页的时候,把哪些页换掉,即效率高又可以降低缺页率是置换算法的两个评价指标。
局部页面置换算法:进程内部的页面
- 先进先出,淘汰最早进入页面
- LRU,使用一个栈,新页面或者命中的页面则将该页面移动到栈底,每次替换栈顶的缓存页面。
- 时钟算法,使用位设置为1,给一次复活机会,扫描到就置0
- 修改的时钟算法,增加了页数据修改位
全局页面置换算法:所有可换出的页面
- 工作集,只保留工作集范围内的页面
- 缺页率算法,根据缺页率调整常驻集的大小
死锁
https://blog.youkuaiyun.com/qq_22238021/article/details/80225459
[https://cyc2018.github.io/CS-Notes/#/notes/%E8%AE%A1%E7%AE%97%E6%9C%BA%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F%20-%20%E6%AD%BB%E9%94%81](https://cyc2018.github.io/CS-Notes/#/notes/计算机操作系统 - 死锁)
两个及以上进程在执行过程因争夺资源而产生相互等待的现象。
四个必要条件:
- 互斥条件:进程的资源只能独占访问,其他进程需等待
- 请求和保持:进程获得资源后,会请求其他资源
- 不可剥夺:进程已获得的资源在完成前不可被剥夺,只能自己释放
- 环路等待:存在进程-资源间的环形链
处理方式:
- 鸵鸟
- 死锁检测与恢复
- 死锁预防
- 死锁避免
死锁检测与恢复:
检测:
- 每种类型一个资源的死锁检测:检测有向图是否存在环。
从一个节点出发进行深度优先搜索,对访问过的节点进行标记,如果访问到了已经标记的节点,则表示有向图存在环,也就是检测到了死锁。 - 每种类型多个资源的死锁检测:
资源总向量E,资源剩余向量A,进程资源占用矩阵C,进程资源请求矩阵R
检测算法:- 寻找未标记过的进程,其所请求的资源小于等于A
- 如果找到这样一个进程,执行该进程后,将C中该进程的向量加入A中,并对其进行标记,然后转到上一步继续
- 如果没找到这样一个进程,则算法终止。未被标记过的进程为死锁进程。
恢复:
- 抢占:不通知进程,将其资源强行取走给另一个进程使用,完后归还
- 回滚:混滚复位到更早的状态
- 杀死进程:杀进程释放资源,最好杀死不会带来副作用的进程
死锁预防:
破坏四个必要条件之一:
- 破坏互斥条件:一般不这样做,不然会造成同步问题
- 破坏请求和保持条件:
- 资源一次性分配,在运行过程中就不会出现请求
- 在进程每次提出申请新资源前,释放所占有的资源,然后一次性尝试获得所有的资源
- 破坏不可剥夺条件
- 破坏环路等待条件:
- 资源有序分配:系统给每类资源分配序号,进程按照编号递增的方式请求资源,破坏环路等待的条件
死锁避免:
检测下一步操作是否是安全状态,如果是就执行,否则拒绝。
- 单个资源的银行家算法
- 和资源检测算法类似,通过判断是否存在请求资源小于当前剩余的进程以及所有进程能够全部执行来觉得当前状态是否安全。
- 多个资源的银行家算法
- 和单个资源的区别是向量和单个数字的区别
进程与线程的通信
进程间通信方式:
- 管道,pipe
- 命名管道
- 消息队列
- 信号量semophore
- 信号
- 共享内存
- 套接字
线程间的通信,线程由于共享内存空间,不需要通信,但是需要同步机制:
- 互斥锁
- 条件变量
- 读写锁
- 信号量机制
- 信号机制
- 自旋锁
- RCU,ready-copy-update
进程调度
批处理系统
- 先来先服务 FCFS
- 短作业优先
- 最短剩余时间优先
交互式系统
- 时间片轮转
- 优先级调度:为每个进程分配优先级,按优先级调度,随时间推移,增加等待进程的优先级
- 多级反馈队列,多个队列,每个队列时间片依次增加,时间片越小的队列优先级越高
实时系统
实时系统要求一个请求在一个确定时间内得到响应。
分为硬实时和软实时,前者必须满足绝对的截止时间,后者可以容忍一定的超时。
协程
协程也是子程序,但在子程序内部可中断。
和多线程相比:
- 协程有极高的执行效率,没有线程切换的开销。
- 不需要锁机制,只有一个线程,不存在同步冲突。
系统调用
- 复制进程
- 管道
- 文件读写,
用户态切换到内核态
系统调用
异常
中断
编译链接过程
源代码 - 预处理 得到 文本文件 - 编译 得到 汇编语言文件 - 汇编得到二进制可重定位执行文件 - 链接 得到 程序
静态链接 :
- 速度快
- 将所有的代码都放在一起。浪费空间
- 不方便升级,修改需重新编译
动态链接
- 速度慢
- 动态链接执行
- 方便更新升级
I/O模型
https://www.jianshu.com/p/d863a26dd32a
https://www.cnblogs.com/sharing-java/p/10791802.html
五种模型
- 阻塞式I/O
- 非阻塞式I/O
- I/O复用
- 信号驱动I/O
- 异步I/O
阻塞I/O
应用进程会一直阻塞直到内核缓冲区
有数据报到达且被复制到应用进程缓冲区
例子:商场排队吃饭,只能老老实实排队,并且排队的时候不能做其他事情
非阻塞式I/O
在设置连接为非阻塞时,当应用进程系统调用recvfrom
没有数据返回时,内核会立即返回一个EWOULDBLOCK
错误,而不会一直阻塞到数据准备好。
应用进程这样循环调用recvfrom
时,我们称之为轮询polling
。这么做往往会耗费大量CPU时间,实际使用很少
例子:还是商场吃饭,只是现在可以取号了。不过仍然需要时不时的去看一下有没有叫到号
I/O复用
所以IO多路复用的特点是通过一种机制一个进程能同时等待多个文件描述符,而这些文件描述符(套接字描述符)其中任意一个进入就绪状态,select函数就可以返回。
Linux I/O复用模型提供了select poll epoll
三组系统调用可做选择,进程通过将一个或多个文件描述符(fd)
传递给select
或poll
或epoll
系统调用,通过它们来监测多个fd
是否处于就绪状态。select
或poll
是顺序扫描fd
是否就绪,而且支持的fd
数量有限,因此使用上有制约。epoll
调用基于事件驱动,因此性能更高,当fd
就绪时会立即回调rollback
不难发现进程会阻塞于select
调用,直到所关注的某一个文件描述符(套接字)变为可读状态
例子:还是商场吃饭,但是现在你可以在手机APP上同时叫多个号了,只要多个号里面有一个号好了就会通知你了
信号驱动I/O
通过系统调用sigaction
,并注册一个信号处理的回调函数,该调用会立即返回,但是当内核数据就绪时,内核会为该进程产生一个SIGIO
信号,并回调我们注册的信号回调函数,这样我们就可以在信号回调函数中系统调用recvfrom
获取数据
例子:商场吃饭,只要取了号,你也不用去一直看看大屏幕有没有好了,要是叫到号了,会主动发消息告诉你了
异步I/O
异步I/O
与 信号驱动I/O
最大区别在于,信号驱动
是内核通知我们何时开始一个I/O操作
,而异步I/O
是由内核通知我们I/O
操作何时完成,两者有本质区别
例子:都不用去商场吃饭了,直接点个外卖,把等待上菜的时间也给省了
磁盘结构
盘面,磁道,扇区,磁头,制动手臂,主轴
磁盘调度算法:
- 先来先服务,按照磁盘请求顺序进行调度
- 最短寻道时间优先,优先调度与当前磁头所在磁道距离最近的磁道
- 电梯算法:总是按照一个方向运行,直到该方向没有请求,然后改变运行方向。
函数,该调用会立即返回,但是当内核数据就绪时,内核会为该进程产生一个SIGIO
信号,并回调我们注册的信号回调函数,这样我们就可以在信号回调函数中系统调用recvfrom
获取数据
例子:商场吃饭,只要取了号,你也不用去一直看看大屏幕有没有好了,要是叫到号了,会主动发消息告诉你了
异步I/O
异步I/O
与 信号驱动I/O
最大区别在于,信号驱动
是内核通知我们何时开始一个I/O操作
,而异步I/O
是由内核通知我们I/O
操作何时完成,两者有本质区别
例子:都不用去商场吃饭了,直接点个外卖,把等待上菜的时间也给省了
磁盘结构
盘面,磁道,扇区,磁头,制动手臂,主轴
磁盘调度算法:
- 先来先服务,按照磁盘请求顺序进行调度
- 最短寻道时间优先,优先调度与当前磁头所在磁道距离最近的磁道
- 电梯算法:总是按照一个方向运行,直到该方向没有请求,然后改变运行方向。