1021 笔记

操作系统发展史

1.穿孔卡片

手工操作,且一个计算机机房,只能被一个用户使用

2.联机批处理系统

支持多用户去使用一个计算机机房,主机与输入机之间增加一个存储设备——磁带,在运行于主机上的监督程序的自动控制下,计算机可自动完成

3.脱机批处理系统

为克服与缓解:高速主机与慢速外设的矛盾,提高CPU的利用率

特征是:增加一台不与主机直接相连而专门用于与输入/输出设备打交道的卫星机。主机与卫星机可并行工作,二者分工明确,可以充分发挥主机的高速计算能力。

高速磁盘: 提高文件的读取速度

为改善CPU的利用率,又引入了多道程序系统

4.多道程序系统

所谓多道程序设计技术,就是指允许多个程序同时进入内存并运行,并允许它们交替在CPU中运行,当一道程序因I/O请求而暂停运行时,CPU便立即转去运行另一道程序

单道程序运行过程

多个使用者使用CPU时是串行的

img

在A程序计算时,I/O空闲, A程序I/O操作时,CPU空闲(B程序也是同样);必须A工作完成后,B才能进入内存中开始工作,两者是串行的,全部完成共需时间=T1+T2。

多道程序运行过程

将A、B两道程序同时存放在内存中,它们在系统的控制下,可相互穿插、交替地在CPU上运行

* 空间上的复用:	
	多个程序公用一个内存,彼此隔离,物理级别的隔离
* 时间上的复用:	
	共用一个cpu
	1.若CPU遇到IO操作,会立即将当前程序CPU使用权断开
	​	优点:	CPU利用率高
	2.若一个程序使用CPU的时间过长,会立即将房钱执行程序CPU使用权断开
	​	缺点:	程序执行率降低

多道程序系统的出现,标志着操作系统渐趋成熟的阶段,先后出现了作业调度管理、处理机管理、存储器管理外部设备管理、文件系统管理等功能。

并发与并行

​ 并发: 指的是看起来像同时在运行,其实是多个程序不停切换+保存状态

​ 并行: 真实意义上的同时运行,在多核的情况下,同时执行多个程序. 多核

​ 串行: 一个任务完整执行结束,再运行下一个任务

进程

进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础

1.程序与进程

程序: 一堆代码

程序是指令和数据的有序集合,其本身没有任何运行的含义,是一个静态的概念

进程: 一堆代码运行的过程

进程是程序在处理机上的一次执行过程,它是一个动态的概念。

2.进程调度

1.先来先服务调度:

a,b程序,若a程序先来,先占用CPU

缺点: 程序a先使用,程序b必须等待程序a使用CPU结束后才能使用

2.短作业优先调度:

a,b程序,谁的用时短,先优选调度使用CPU

缺点: 若程序a使用时间最长,有N个程序使用时间短,必须等待所有用时 短的程序结束后才能使用

3.时间片轮转法:

CPU执行的时间1秒中,加载N个程序,要将1秒等分为N个时间片

4.分级反馈队列

将执行优先分为多层级别

​ 1级:优先级最高

​ 2级:优先级第二

​ 3级:...

5.调度状态

进程执行时的间断性,决定了进程可能具有多种状态。

就绪态

所有进程创建时都会进入就绪态,准备调度

运行态

调度后的进程,进入进程态

阻塞态

凡是遇到I/O操作的进程,都会进入阻塞态,I/O结束后,必须重新进入就绪态

6.进程回收

1.进程回收的两种条件

  • join,可以回收子进程与主进程
  • 主进程正常结束,子进程与主进程也会被回收

2.僵尸进程

指的是子进程已经结束,但PID号还存在,未销毁

缺点: 占用PID号,占用操作系统资源

PID号:PID是各进程的代号,运行时系统随机分配,但是进程终止后PID标识符就会被系统回收,进程号具有固定数量.

3.孤儿进程

指的是子进程还在执行,但父进程意外结束.

操作系统优化机制:自动回收此类子进程

4.守护进程

指的是主进程结束后,该主进程产生的所有子进程跟着结束,并回收.

p.daemon = true 设置为守护进程

p.daemon = true  (设置为守护进程)
p.start
# 必须在p.start之前设置,如果在之后会报错

3.进程对象的属性

1.current_process().pid

在子进程内使用,可以获取子进程号

from multiprocessing import Process
from multiprocessing import current_process

def task():
    print('开始执行...',current_process().pid)
    print('结束执行')
    
if __name__ == '__main__':
    p = Process(target=task)  # 获得process对象
    p.start()  # 创建子进程
    p.join()    # 执行完子进程在执行主进程
    print('主进程')
'''开始执行... 2092
结束执行
主进程'''

2.os.getpid()

在主进程中获得主进程号.

from multiprocessing import Process
from multiprocessing import current_process
import os

def task():
    print('开始执行...',current_process().pid)
    print('结束执行')

if __name__ == '__main__':
    p = Process(target=task)  # 获得process对象
    p.start()  # 创建子进程
    p.join()    # 执行完子进程在执行主进程
    print('主进程',os.getpid())
'''
开始执行... 11072
结束执行
主进程 13892
'''

3.os.getppid

可以查看主主进程的进程号(pycharm中运行代码,主主进程就是pycharm)

def task():
    print('开始执行...',current_process().pid)
    time.sleep(1)
    print('结束执行')

if __name__ == '__main__':
    p = Process(target=task)  # 获得process对象
    p.start()  # 创建子进程
    p.join()    # 执行完子进程在执行主进程
    print('主进程',os.getpid())
    print('主主进程',os.getppid())
    time.sleep(1000)
'''
开始执行... 12368
结束执行
主进程 10332   # python.exe
主主进程 4152  # pycharm64.exe
'''

4.join()方法

代码

会让子进程结束后再结束主进程

# 让子进程结束后,父进程才结束
from multiprocessing import Process
import time

def task(name):
    print('任务开始')
    time.sleep(1)
    print('任务结束')

if __name__ == '__main__':
    p = Process(target= task,args=('你好',))
    p.start() # 告诉操作系统,开启子进程
    print('join上面的不算')
    p.join()   # 告诉操作系统,等子进程结束后,父进程再结束
    print('主进程')
'''
join上面的不算
任务开始
任务结束
主进程'''

多个子程序的运行

# 多个子进程的运行
from multiprocessing import Process
import time

def task(name,n):
    print(f'{name}任务{n}开始')
    time.sleep(1)
    print(f'{name}任务{n}结束')

if __name__ == '__main__':
    p1 = Process(target= task,args=('AAA',1))
    p2 = Process(target= task,args=('BBB',2))

    p1.start() # 告诉操作系统,开启子进程
    p2.start() # 告诉操作系统,开启子进程
    print('join上面的不算')
    p1.join()   # 告诉操作系统,等子进程结束后,父进程再结束
    p2.join()   # 告诉操作系统,等子进程结束后,父进程再结束
    print('主进程')
'''
join上面的不算
AAA任务1开始
BBB任务2开始
AAA任务1结束
BBB任务2结束
主进程
'''
打印时会出现任务1,2顺序的不一致,貌似是因为程序并行导致cpu分配执行打印速度导致

5.is_alive()

判断子进程是否存活

def task():
    print('开始执行...',current_process().pid)

if __name__ == '__main__':
    p = Process(target=task)  # 获得process对象
    p.start()  # 创建子进程
    print(p.is_alive())   # 判断子进程是否存活
    print('主进程',os.getpid())
'''
True
主进程 3740
开始执行... 7004'''

6..terminate()

直接告诉操作系统,终止子程序

def task():
    print('开始执行...',current_process().pid)

if __name__ == '__main__':
    p = Process(target=task)  # 获得process对象
    p.start()  # 创建子进程
    # 判断子进程是否存活
    print(p.is_alive())
    # 告诉操作系统直接终止掉子进程
    p.terminate()
    time.sleep(0.1)
    # 判断子进程是否存活
    print(p.is_alive())
    print('主进程',os.getpid())
'''
True
False
主进程 7976'''

7.tasklist | findstr+进程号

# cmd 中查询进程号: tasklist | findstr 进程号

4.进程的创建

错误示范

from multiprocessing import Process
import time
# 1.定义一个任务
def task(name):
    print(f'{}的任务开始执行')
    time.sleep(1)

# target = 执行函数的地址  args= 是传入函数的变量元组形式
p = Process(target=task,args=('abc0',))
# 向操作系统提交创建进程的任务
p.start()
'''注意: 在Windows下:创建子进程,会将当前父进程的代码重新加载执行一次
以上执行创建子进程时会创建新的空间,会形成递归.
linux/mac:  会将当前父进程代码重新拷贝一份,再去执行
'''

1.创建进程方式1

from multiprocessing import Process
import time
# 1.定义一个任务
def task(name):
    print(f'{name}的任务开始执行')
    time.sleep(1)
    print(f'{name}的任务结束执行')

if __name__ == '__main__':
    # target = 执行函数的地址  args= 是传入函数的变量元组形式
    p = Process(target=task,args=('abc0',))
    # 向操作系统提交创建进程的任务
    p.start()
    print('主进程')
    '''# 先执行主进程,在创建的字进程执行
主进程
abc0的任务开始执行
abc0的任务结束执行
'''

2.创建进程方式2

自定义一个类,并继承Process

# 1.自定义一个类,并继承Process
class MyProcess(Process):
    # 父类的方法
    def run(self):
        print('任务开始执行...')
        time.sleep(1)
        print('任务结束执行...')

if __name__ == '__main__':
    p = MyProcess()
    p.start()  # 创建子进程
    print('主进程')
'''
主进程
任务开始执行...
任务结束执行...
'''

5.进程之间的数据相互隔离

主进程子进程会产生各自的名称空间

from multiprocessing import Process

x = 100

def func():
    global x
    x = 20

if __name__ == '__main__':
    p = Process(target= func)
    p.start()
    print(x)
    print('主程序')
    
'''x = 100 '''

并行/串行/并发

1. 概念

假设有AB两个任务,则串行、并行、并发的区别如图1所示。

###### 串行

A和B两个任务运行在一个CPU线程上,在A任务执行完之前不可以执行B。即,在整个程序的运行过程中,仅存在一个运行上下文,即一个调用栈一个堆。程序会按顺序执行每个指令。

###### 并行

并行性指两个或两个以上事件或活动在同一时刻发生。在多道程序环境下,并行性使多个程序同一时刻可在不同CPU上同时执行。比如,A和B两个任务可以同时运行在不同的CPU线程上,效率较高,但受限于CPU线程数,如果任务数量超过了CPU线程数,那么每个线程上的任务仍然是顺序执行的。

###### 并发

并发指多个线程在宏观(相对于较长的时间区间而言)上表现为同时执行,而实际上是轮流穿插着执行,并发的实质是一个物理CPU在若干道程序之间多路复用,其目的是提高有限物理资源的运行效率。 并发与并行串行并不是互斥的概念,如果是在一个CPU线程上启用并发,那么自然就还是串行的,而如果在多个线程上启用并发,那么程序的执行就可以是既并发又并行的。

同步和异步

指的是提交任务的方式

同步

若有两个任务需要提交,在提交第一个任务时,必须等待该任务执行结束后,才能继续提交并执行第二个任务

同步,是所有的操作都做完,才返回给用户结果

异步

指的是若有两个任务需要提交,在提交第一个任务时,不需要原地等待,立即可以提交并执行第二个任务

异步,不用等所有操作等做完,就响应用户请求

阻塞与非阻塞

阻塞

阻塞态,遇到IO一定会阻塞

非阻塞

就绪态,运行态

面试题

同步和异步,阻塞与非阻塞是同一个概念么

答:不是同一个概念,不能混为一谈. IO操作与代码的执行

最大化提高CPU的使用率提高,尽可能减少io操作

原文地址:https://www.cnblogs.com/fwzzz/p/11715736.html