多任务编程学习笔记
多任务编程
通过应用程序利多个计算机核心达到多任务同时执行的目的,一次来提升程序的执行效率
多进程,多线程
进程:程序在计算机中一次执行的过程;
程序和进程的区别:
程序:是一个静态的描述,不占计算机资源
进程:是一个动态的过程,占用CPU内存的资源,有一定的生命周期
同一个程序,每次执行都是不同的进程,因为分配的计算机资源不同
1, 进程的创建流
用户空间运行程序,发起进程创建申请
---> 调用操作系统内核接口创建进程
---> 分配计算机资源,确定进程状态
---> 将新的进程提供给用户使用
2, 多个进程如何占用CPU
a, 一个内核同一个时刻只能运行一个任务
b, 多个进程对内核资源进行争夺,操作系统决定那个进程占有计算资源
c, 占有计算机的计算资源,我们称为占有cpu的时间片
3, 进程有哪些信息如何保存
PCB--Process Control Block: 在linux/unix系统中进程创建后,会在内存开辟一块空间存放进程的相关信息,称为PCB
ps -aux
4, 进程特征
a, 进程是操作系统 资源分配的最小单位;(线程是占有cpu内核的最小单位)
b, 每个进程单独占有4G的虚拟内存
c, 进程之间相互独立,运行不受影响
进程的状态:有三态和五态之说
三态:
就绪态:进程具备运行条件,等待系统分配cpu资源
运行态: 进程占用cpu,处于运行的状态
等待态/阻塞:又称为阻塞态,睡眠态,指进程暂时不具备运行的条件,需要阻塞等待(sleep, accept...)
五态
三态+ 新建和终止 两状态
ps -aux --> STAT 表示进程装填
D: 等待态--不可中断等待
S:等待态--可中断等待
T:等待态--暂停Time-out
R:运行态run
Z:僵尸态
+ 前台进程 (不带+,后台进程)
< 高优先级
N 低优先级 Negative
l 有进程链 link, 有关联进程
s 会话组 session,有一组进程;
进程优先级:
进程优先级决定一个进程的执行权限和占有资源的有线程度
top:动态查看当前运行的进程状态, NI表示优先级, <>翻页
linux中优先级范围
-20 -- 19
-20最高
用户程序默认优先级0
nice:以指定的优先级运行进程
nice -9 command
renice: 改变进程的优先级
renice 优先级 pid
进程树
pstree
使用两个进程分别完成预定事件
os.fork()
功能: 创建一个新的进程
参数: 无
返回值:
失败,返回是一个负数 ,一般是 -1
成功:0 在子进程中fork的返回值
>0 的正整数,(新的进程PID),在父进程中的返回值
如果成功,os.fork() 会在内存中开辟一个新的内存空间,并将代码自我COPY一份到新内存空间,即创建一个新的子进程;
此时父进程os.fork()返回新创建子进程的pid 号, 子进程开辟新空间后也会执行相同代码--从os.fork()执行;
但子进程os.fork()返回值为0;
注意: 1, 在fork()之前有print(),将值会print1次,子进程只执行fork下面的代码
2, fork()之前有变量,子进程也会有该变量;因为父进程复制子进程所有代码段
3, fork()之后的修改不会影响到对方,父子进程执行上互不影响
4, 子进程虽然复制父进程的空间,但是有自己的特性,比如自己的pid,进程PCB,进程栈空间等;
举例说明:
#洗衣服需要10min, 烧水需要6min;
#两间事情需要同时处理
import os
from time import sleep
#创建进程
pid = os.fork()
#创建子进程失败
if pid < 0:
print("create process failed")
#创建子进程成功,处理子进程
elif pid == 0:
print("This is childprocess:pid return {}".format(pid))
for _ in range(1,7):
sleep(1)
print('烧水时间{}'.format(_))
print('水烧开啦.')
#创建子进程成功,处理父进程部分
else:
print("父进程执行, this is father process, my childprocess pid= {}".format(pid))
for _ in range(1,11):
sleep(1)
print('洗衣服时间:{}'.format(_))
print('衣服洗完啦!')
print("finished")
进程相关函数:
os.getpid() 获取当前进程的pid,返回值即PID
os.getppid() 功能:获取当前进程父进程的PID
os._exit(status)功能: 结束一个进程
参数: 表示进程的结束状态,是一个整数
sys.exit([status])
功能: 结束一个进程,抛出异常,可以被try捕获
参数: 传入一个正整数,表示结束状态;
传入一个字符串,表示结束打印
import os
from time import sleep
pid = os.fork()
if pid < 0:
print('创建失败')
elif pid == 0:
sleep(0.1)
print("子进程")
print(os.getpid()) #获取自己的pid
print(os.getppid()) #获取父进程pid
print("--------------------")
else:
print("父进程")
print(pid)
print(os.getpid())
孤儿进程:父进程先于子进程退出,此时子进程变为孤儿进程;
孤儿进程会被系统指定进程所”收养“,该进程称为孤儿继承的新父进程
eg:
import os
from time import sleep
pid = os.fork()
if pid < 0:
print('childprocess failed')
elif pid == 0:
print('created childprocess')
#打印父进程pid
print('child's old father process pid:', os.getppid())
#进行sleep,此时父进程已结束,孤儿进程被继父接管;
sleep(0.1)
print('new father PID:', os.getppid())
else:
print('father process pid:', os.getpid())
僵尸进程: 子进程先于父进程退出,但父进程没有处理子进程的退出状况,子进程就会称为僵尸进程
*僵尸进程会滞留PCB的部分信息在内存中,大量的僵尸进程会消耗系统资源,所以应尽量避免僵尸进程的产生
eg:创建僵尸进程
import os
pid = os.fork()
if pid < 0:
print('failed')
elif pid == 0:
print(os.getpid())
else:
#子进程完成,父进程未处理;从而成为僵尸进程
while True:
pass
如何避免僵尸进程的产生:
1, 让父进程先退出(不易控制)
2, 让父进程处理子进程的退出
*使用wait或者waitpid函数
*使用信号处理
3, 创建二级子进程
os.wait()
功能: 等待子进程的退出
参数: 无
返回值: 一个二元元祖,第一个值为退出的子进程PID,第二个只为子进程的退出状态
os.waitpid(pid,option)
功能: 处理子进程的退出
参数:pid: -1 表示等待任意子进程的退出
>0 表示等待相应PID号的子进程退出
option: 0 表示阻塞等待
os.WNOHANG: 表示非阻塞等待
返回值: 一个二元元祖,第一个值为退出的子进程PID,第二个只为子进程的退出状态
os.waitpid(-1,0) 等效 os.wait()
import os
from time import sleep
pid = os.fork()
if pid < 0:
print('childprocess failed')
elif pid == 0:
sleep(5)
print('created childprocess')
print('childs old father process pid:', os.getppid())
sleep(0.1)
else:
#设置为非阻塞状态,循环处理,查看子进程状态
while True:
sleep(1)
p,status = os.waitpid(pid,os.WNOHANG)
print(p,status)
print('father process pid:', os.getpid())
while True:
pass
创建二级子进程
父进程创建子进程,处理特定时期;
子进程创建二级子进程,处理额外的事情
一级子进程退出,使二级子进程称为孤儿进程,被接管;
从而父进程和二级子进程相互处理不同事情,互不影响
二级子进程代码
#创建二级子进程处理僵尸进程
import os
from time import sleep
#子进程函数
def subprocess():
childpid = os.fork()
if childpid < 0:
print('二级子进程创建失败')
elif childpid == 0:
print('二级子进程创建成功',os.getpid())
print('做其他事情')
else:
os._exit(0)
pid = os.fork()
if pid < 0:
print('创建失败')
os._exit(0)
elif pid == 0:
#创建二级子进程
print('创建一级子进程成功')
subprocess()
else:
p,status = os.wait()
print(p,status)
print('这是父进程, pid', pid)
print('do something')