如果你发现了问题或者有新的知识点添加 ,请在文件下方标出行号,并写下修改后的内容,方便大家整理,谢谢!
多道程序系统 原理,缺点
#允许多个程序同时进入内存并运行。即同时把多个程序放入内存,并允许它们交替在CPU中运行,它们共享系统中的各种硬、软件资源。当一道程序因I/O请求而暂停运行时,CPU便立即转去运行另一道程序。
# 多道技术中的多道指的是多个程序,多道技术的实现是为了解决多个程序竞争或者说共享同一个资源(比如cpu)的有序调度问题,解决方式即多路复用,多路复用分为时间上的复用和空间上的复用。
# 时间复用,空间复用
# 空间上的多路复用: 将内存分为几部分,每个部分放入一个程序,这样,同一时间内存中就有了多道程序。
# 空间上的复用最大的问题是:程序之间的内存必须分割,这种分割需要在硬件层面实现,由操作系统控制。如果内存彼此不分割,则一个程序可以访问另外一个程序的内存,
# 首先丧失的是安全性,比如你的qq程序可以访问操作系统的内存,这意味着你的qq可以拿到操作系统的所有权限。
# 其次丧失的是稳定性,某个程序崩溃时有可能把别的程序的内存也给回收了,比方说把操作系统的内存给回收了,则操作系统崩溃。
# 时间上的多路复用: 当一个程序在等待I/O时,另一个程序可以使用cpu,如果内存中可以同时存放足够多的作业,则cpu的利用率可以接近100%
# 操作系统采用了多道技术后,可以控制进程的切换,或者说进程之间去争抢cpu的执行权限。这种切换不仅会在一个进程遇到io时进行,一个进程占用cpu时间过长也会切换,或者说被操作系统夺走cpu的执行权限
# INPUT 数据进入内存
# OUTPUT 数据移除内存
什么是操作系统?
# 操作系统就是一个协调、管理和控制计算机硬件资源和软件资源的控制程序。
# 操作系统由操作系统的内核(运行于内核态,管理硬件资源)以及系统调用(运行于用户态,为应用程序员写的应用程序提供系统调用接口)两部分组成
posix是IEEE提出的一个unix标准,(可移植的操作系统接口Portable Operating System Interface)
操作系统的功能?
# 隐藏了丑陋的硬件调用接口,为应用程序员提供调用硬件资源的更好,更简单,更清晰的模型(系统调用接口)。应用程序员有了这些接口后,就不用再考虑操作硬件的细节,专心开发自己的应用程序即可。
# 将应用程序对硬件资源的竞态请求变得有序化
操作系统的作用?
# 作用一:为应用程序提供如何使用硬件资源的抽象。例如:操作系统提供了文件这个抽象概念,对文件的操作就是对磁盘的操作,有了文件我们无需再去考虑关于磁盘的读写控制
# 作用二:管理硬件资源。操作系统的任务是在相互竞争的程序之间有序地控制对处理器、存储器以及其他I/O接口设备的分配。
什么是进程?进程与程序的区别?
# 进程正在执行的一个过程。进程是对正在运行程序的一个抽象。# 进程是一个实体。每一个进程都有它自己的地址空间,#是系统进行资源分配和调度的基本单位
# 包括文本区域(text region)、数据区域(data region)和堆栈(stack region)。文本区域存储处理器执行的代码;数据区域存储变量和进程执行期间使用的动态分配的内存;堆栈区域存储着活动过程调用的指令和本地变量。
进程与程序的区别
# 程序是指令和数据的有序集合,其本身没有任何运行的含义,是一个静态的概念。
# 而进程是程序在处理机上的一次执行过程,它是一个动态的概念。
# 程序可以作为一种软件资料长期存在,而进程是有一定生命期的。
# 程序是永久的,进程是暂时的。
进程与进程间数据的关系
# 进程直接的内存空间是隔离的
# 父子
# 父进程只负责通知操作系统启动子进程
# 接下开的工作由操作系统接手,父进程继续执行
# 父进程执行完毕之后并不会直接结束程序,而是会等待所有的所有的子进程完毕之后才结束
# 父进程要负责回收子进程的资源
什么是pid?pid的原理是什么?有什么特点?
# PID(Process Identification)操作系统里指进程识别号,也就是进程标识符。
# 特点:
# 只要运行一程序,系统会自动分配一个标识。
# 是暂时唯一:进程中止后,这个号码就会被回收,并可能被分配给另一个新进程。
# 只要没有成功运行其他程序,这个PID会继续分配给当前要运行的程序。
# 如果成功运行一个程序,然后再运行别的程序时,系统会再次自动分配另一个PID。
什么是进程调度三状态图?
# 新提交的任务会进入就绪队列的末尾,操作系统系统会将就绪队列添加到状态中并执行一个单位的时间片,如果在时间片的时间内执行完毕,任务结束。如果没有执行完那么继续将其添加到就绪队列的末尾等待下一次执行。如果在运行的过程中遇到了阻塞那么将其添加进阻塞队列中,等待阻塞的IO执行完毕再添加进就绪队列中,开始新的一轮运行。
进程都有哪些调度算法?
FCFS 原理
# 用于作业调度,进程调度。FCFS算法比较有利于长作业(进程),而不利于短作业(进程)。适合于CPU繁忙型作业,而不利于I/O繁忙型的作业(进程)。
SPF 原理
# 指对短作业或短进程优先调度的算法,用于作业调度,进程调度。但其对长作业不利;不能保证紧迫性作业(进程)被及时处理;作业的长短只是被估算出来的。
RR 原理
# 让每个进程在就绪队列中的等待时间与享受服务的时间成比例。
# 在时间片轮转法中,需要将CPU的处理时间分成固定大小的时间片。如果一个进程在被调度选中之后用完了系统规定的时间片,但又未完成要求的任务,则它自行释放自己所占有的CPU而排到就绪队列的末尾,等待下一次调度。同时,进程调度程序又去调度当前就绪队列中的第一个进程。
# 由于作业调度是对除了CPU之外的所有系统硬件资源的分配,其中包含有不可抢占资源,所以作业调度不使用轮转法。
# 在轮转法中,加入到就绪队列的进程有3种情况:
# 一种是分给它的时间片用完,但进程还未完成,回到就绪队列的末尾等待下次调度去继续执行。
# 另一种情况是分给该进程的时间片并未用完,只是因为请求I/O或由于进程的互斥与同步关系而被阻塞。当阻塞解除之后再回到就绪队列。
# 第三种情况就是新创建进程进入就绪队列。
多级反馈队列算法原理
# 1. 设置多个就绪队列,并为各个队列赋予不同的优先级。第一个队列的优先级最高,第二个队列次之,其余各队列的优先权逐个降低。该算法赋予各个队列中进程执行时间片的大小也各不相同,在优先权愈高的队列中,为每个进程所规定的执行时间片就愈小。
# 2. 当一个新进程进入内存后,首先将它放入第一队列的末尾,按FCFS原则排队等待调度。当轮到该进程执行时,如它能在该时间片内完成,便可准备撤离系统;如果它在一个时间片结束时尚未完成,调度程序便将该进程转入第二队列的末尾,再同样地按FCFS原则等待调度执行;如果它在第二队列中运行一个时间片后仍未完成,再依次将它放入第三队列,……,如此下去,当一个长作业(进程)从第一队列依次降到第n队列后,在第n 队列便采取按时间片轮转的方式运行。
# 3. 仅当第一队列空闲时,调度程序才调度第二队列中的进程运行;仅当第1~(i-1)队列均空时,才会调度第i队列中的进程运行。如果处理机正在第i队列中为某进程服务时,又有新进程进入优先权较高的队列(第1~(i-1)中的任何一个队列),则此时新进程将抢占正在运行进程的处理机,即由调度程序把正在运行的进程放回到第i队列的末尾,把处理机分配给新到的高优先权进程。
什么是并行,串行
# 并行: 同时运行,只有具备多个CPU才能实现
什么是并发
# 并发: 伪并行,单个cpu+多道技术可实现并发
并发的实现:
# 进程并发的实现在于硬件中断一个正在运行的进程,把此时进程运行的所有状态保存下来,为此操作系统维护一张表格,进程表。
# 每个进程占用一个进程表项(进程程序块)
什么是同步,异步,阻塞,非阻塞,说说各个组合的应用?
# 同步一个任务的完成需要依赖另外一个任务时,只有等待被依赖的任务完成后,依赖的任务才能算完成,这是一种可靠的任务序列。要么成功都成功,失败都失败,两个任务的状态可以保持一致。
# 异步是不需要等待被依赖的任务完成,只是通知被依赖的任务要完成什么工作,依赖的任务也立即执行,只要自己完成了整个任务就算完成了。
# 进程在等待输入(I/O)时的状态称为阻塞
# 异步阻塞
# 异步操作是可以被阻塞住的,只不过它不是在处理消息时阻塞,而是在等待消息通知时被阻塞。
# 异步非阻塞
# 即不会一个任务完完整整执行完才去执行另一个一个任务,也不会在任务执行中等待IO完毕再执行任务。
如何创建一个进程?
# 系统初始化
# 一个进程在运行过程中开启子进程
# 用户的交互式请求而创建的进程
# 批处理作业的初始化
# 新进程的创建都是由一个已存在的进程执行了一个用于创建进程的系统调用而创建的
如何结束一个进程?
# 正常退出
# 出错退出
# 严重退出
# 被杀死
进程的属性,和方法
# p.start() 只是向操作系统开启子进程的信号, 子进程创造,运行多长时间应用无法管理。p.start() 会调用run 如果继承类需要重写run
# join() 主进程等待子进程终止. 等到子进程执行完毕后,将占用的操作系统的pid回收.join并没有使进程串行,仅仅是主进程等待调用join方法子进程。
# p.terminate() 只是告诉操作系统杀进程,操作系统什么时候杀,杀没杀完他都不知道
# p.run() 进程启动时运行的方法,是他调用target指定的函数,自定义类必须实现
# p.daemon 在调用start()之前使用 True将子进程设置为守护进程
# p.is_alive() p运行,返回bool 查看子进程是否存活
# p.name 进程名
# p.pid 进程的pid
主进程的任务与子进程的任务分为哪两种情况?
# 在主进程的任务与子进程的任务彼此独立的情况下,主进程的任务先执行完毕后,主进程还需要等待子进程执行完毕,然后统一回收资源。
# 如果主进程的任务在执行到某一个阶段时,需要等待子进程执行完毕后才能继续执行,就需要有一种机制能够让主进程检测子进程是否运行完毕,在子进程执行完毕后才继续执行,否则一直在原地阻塞。
子进程在不同操作系统中有哪些差异?
# windows上开启子进程时将父进程当做模块,,将父进程以导入模块的方式导入子进程执行形成命名空间。 需要开启子进程需要放入main中
# unix通过fork机制复制主进程的名称空间内的变量名。
什么是僵尸进程?应用?
# 一种数据结构 子进程死亡之后占用的内存释放了,
#但保留着进程的pid号,给父进程查看。
# 父进程代码运行完毕并且等所有子进程都死亡之后回收这些ID号。 wait_pid()
#父进程一直不死 还一直不向子进程回收id的操作。僵尸进程越积越多。pid占过多,其他程序起不来。
# linux 用ps aux 查看进程实时查看进程 top
什么是孤儿进程?何时产生?
#父进程被kill之前没回收id 子进程就变成孤儿进程。最后会通过别的机制回收。占pid号还不释放其他的进程就起不来。
join 原理
#1. 如果子进程没执行完就会阻塞,执行完了就不会阻塞
#2. 当期望所有子进程执行完再执行父进程
什么是守护进程?应用?
#1.
# 守护进程会随着主进程代码执行完毕而结束
# 如果主进程代码已经执行完毕,但是子进程还没执行完,守护进程仍然会消失
#2.
# 两种查看电脑应用存活的方式
# 通过网络找到机器,再查看进程是否开启
# 五十台机器主动向我汇报,程序执行就能得到信息
# 守护进程:每隔五分钟就向一台机器汇报自己的状态
锁产生的原因?
# 共享带来竞争资源,竞争带来混乱,同一时间对资源的访问需要串行访问。
锁的属性和方法?
# lock.acquire() 加锁
# lock.release() 释放锁
# 共享空间 ,硬盘空间文件是共享的。
如何解决加锁产生的效率问题?
# 1. 共享文件是硬盘空间 效率低
# 使用内存空间
# 2. 处理好锁的问题
# 队列是管道+锁实现
join与lock的区别?
# 使用join可以将一个任务整体串行
# 互斥锁可以将一个任务中的某一段代码串行
死锁现象是如何产生的?如何解决?
# 两个或两个以上的进程在执行过程中,因争夺资源而造成的一种互相等待的现象。
# 递归锁 RLock
信号量原理是什么? 实现?
# 信号量同一时间允许多个任务拿到锁去使用资源
# 信号量同步基于内部计数器,每调用一次acquire(),计数器减1;每调用一次release(),计数器加1.当计数器为0时,acquire()调用被阻塞
什么是事件?都有哪些属性和方法?
# 进程之间的状态是独立运行且不可预测的。Event对象能够实现进程间的同步。
# Event对象包含一个可由进程设置的信号标志,它允许进程等待某些事件的发生。初始时,信号标志为假,如果有进程等待event对象,那么这些进程会一直被阻塞。如果信号标志设置为真,它将唤醒所有等待对象的进程。
# event.is_set() 返回event的状态值
# event.wait() 如果event.is_set()==False将阻塞进程
# event.set() 设置event的状态为True,所有阻塞池的线程激活进入就绪状态,等待操作系统调度。
# event.clear() 回复envent状态值为False
什么是队列 队列的属性和方法?
# 进程间互相隔离,要实现进程间通信IPC. multiprocessing 支持队列和管道使用消息传递。
# 1.队列内存放的是消息而非大数据
# 2.队列占用的是内存空间,因此maxsize即便是无大小限制也受限于内存大小
# 3.队列只能只在两个进程间传递,不能再进程池内部传递。
# 插入数据到队列
#q.put() 阻塞方法
#q.put_nowait() 非阻塞方法
# 从队列读取并删除一个元素
# q.get() 阻塞方法
# q.get_nowait() 非阻塞方法
# q.empty(),q.full()判断不准确的原因?
# 在多进程场景下进程间的状态是不可预测的。一个进程判断到队列为空或满但此时另一个进程会对队列进行修改
什么是生产者消费者模型?
# 在并发编程中如果处理数据或者生产数据的一方效率过快会让另一方必须等待另一方。为了解决这个问题而实现这个模型。
# 生产者消费者模式是通过一个容器来解决生产者和消费者的强耦合问题。生产者和消费者彼此之间不直接通讯,而通过阻塞队列来进行通讯,所以生产者生产完数据之后不用等待消费者处理,直接扔给阻塞队列,消费者不找生产者要数据,而是直接从阻塞队列里取,阻塞队列就相当于一个缓冲区,平衡了生产者和消费者的处理能力。
# 可以平衡两个角色之间效率
# 使程序解耦合
JoinableQueue 使用方法?
# task_done 使用者使用此方法发出信号,表示q.get()的返回项目已经被处理。如果调用此方法的次数大于从队列中删除项目的数量,引发ValueError异常
# join 生产者调用此方法阻塞,知道队列中所有的项目均被处理。阻塞将持续队列中的每个项目均调用q.task_done()方法为止
# 生产者每放一个数据都会计数,消费者每取一个数据也会计数并会提示处理数据完毕task_done计数-1
什么是管道?属性方法?实现?
# 基于pickle,socket实现 管道是数据不安全的。
# 由两个collection对象组成的元组 表示管道两端的连接对象,必须在产生Process对象之前产生管道
# send() 发送数据pickle支持的类型
# recv() 接收数据,如果没有消息可接收,recv方法会一直阻塞。如果连接的另外一端已经关闭,那么recv方法会抛出EOFError。
# close() 关闭连接
# 开启一个进程,并向进程内传递管道,此时操作系统管理4个端口。每关闭一个端口,端口数减一。直到所有的端口都关闭了剩余一个端口的时候,这时recv没有数据接收判断出结束。就会抛出EOFError异常
为什么要有进程池?
# 服务开启的进程数会随着并发的客户端数目增多而增多,为服务端主机带来压力,进程开启过多,效率反而会下降,所以我们需要让机器在一个可承受的范围运行之内。
# 这就是进程池的用途
进程池都有哪些方法和属性?
# po.apply() apply是同步执行,立刻获取结果
# po. apply_async() 返回值是AsyncResult的实例 使用get来获取apply_aync的结果
# po.join() 等待所有工作进程退出 只能在po.close()或po.teminate()之后调用
# po.close() 关闭进程池。如果所有操作持续挂起,它们将在工作进程终止前完成
# po.map(func,Iterable) 提供异步方式对Iterable元素执行func函数,有返回值。
# po.ready()调用完成返回True
# po.successful() 如果调用完成且没有引发异常,返回True,如果在结果就绪之前调用此方法,引发异常
# po.wait() 等待结果变为可用。
# obj.terminate():立即终止所有工作进程,同时不执行任何清理或结束任何挂起工作。如果p被垃圾回收,将自动调用此函数