多任务编程学习笔记

多任务编程

通过应用程序利多个计算机核心达到多任务同时执行的目的,一次来提升程序的执行效率

多进程,多线程

进程:程序在计算机中一次执行的过程; 

程序和进程的区别:
程序:是一个静态的描述,不占计算机资源
进程:是一个动态的过程,占用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')
	

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值