python多任务编程之OS模块创建父子进程

os.fork()创建父子进程实现多任务编程

import  os

pid = os.fork()

if pid < 0:
	print(“创建进程失败”)
elif pid == 0:
	print(“新创建的进程”)
else:  # 即pid大于0的代码块,可以在此代码块中获取新进程的进程号
	print(“原来的进程”)
  • 功能:创建一个新的进程
  • 参数:无
  • 返回值:
  • 失败:返回-1
  • 成功:在原有进程中返回新进程的pid号(大于0的正整数)
    在新进程中返回0

说明:

  • *fork之前的代码只有父进程会执行
  • *子进程会复制父进程全部代码段,包括fork之前产生的内存空间
  • *子进程从fork的下一行开始执行
  • *子进程通常会根据fork的返回值的差异选择执行不同的代码
  • *子进程虽然复制父进程的代码空间,但是有自己的特有属性,比如PID号PCB等
  • *父子进程在执行上互不干扰,执行顺序不确定
  • *父子进程空间独立,在本进程中对空间的操作不会影响到其他进程

获取进程号:

  • os.getpid()
    功能:获取当前进程的进程号
    返回值:返回进程号
  • os.getppid()
    功能:获取父进程进程号
    返回值:返回进程号

进程的退出:

  • os._exit(status)
    功能:退出进程
    参数:进程的退出状态 整数(1:异常退出 , 0:正常退出)
  • sys.exit([status])
    功能:退出进程
    参数:不写时默认为0
    传入一个整数表示退出状态
    传入一个字符串,则在进程退出时打印该字符串
    sys.exit可以通过捕获SystemExit异常,阻止其异常退出

示例演示1:

import os
from time import sleep

#fork之前的代码只有父进程会执行
print("*"*30)
#fork之前产生内存空间的储存,子进程也会有


#创建新的进程
pid=os.fork()

if pid<0:
	print("创建进程失败")
#只有子进程执行的部分
elif pid==0:
	sleep(3)
	print("新创建的进程")
#只有父进程运行的部分
else:
	sleep(5)
	print("原来的进程")
	
#if结构外的代码,父子结构都会执行
print("程序执行完毕")

fatpuffer@ubuntu:~/mysocket$ python3 fork.py
******************************
***(3s后打印)***
新创建的进程
程序执行完毕
***(5秒后打印)***
原来的进程
程序执行完毕

  • 由此来看,我们创建的父子进程运行上互不干扰,且在if语句块之外的代码父子进程都会执行。

示例演示2:

import os
from time import sleep

#创建新的进程
pid=os.fork()

a = 1

if pid < 0:
	print("创建进程失败")
#只有子进程执行的部分
elif pid == 0:
	print("a=",a)
	a = 10000
	print("新创建的进程")
	print("a=",a)
#只有父进程运行的部分
else:
	sleep(1)
	print("原来的进程")
	print("a=",a)
	
#if结构外的代码,父子结构都会执行
print("程序执行完毕")

fatpuffer@ubuntu:~/mysocket$ python3 fork.py
a= 1
新创建的进程
a= 10000
程序执行完毕
***(1秒后输出)***
原来的进程
a= 1
程序执行完毕

  • 由此可见,fork之后的代码子进程也会拥有,且父子进程空间独立,互不干扰,虽然子进程将变量a重新赋值为100,单父进程拿到的结果依然是1

示例演示3:

import os
from time import sleep

#创建新的进程
pid=os.fork()

if pid<0:
	print("创建进程失败")
elif pid==0:  # 子进程空间
	#获取当前进程号
	print("子进程PID",os.getpid())
	#获取父进程号
	print("父进程PID",os.getppid())
else:  # 父进程空间
	# 创建成功,在原有进程中返回新进程的pid号
	print("父进程PID",os.getpid())
	print("子进程PID",pid)  # 即子进程进程号
fatpuffer@ubuntu:~/mysocket$ python3 fork.py
父进程PID 2863
子进程PID 2864
子进程PID 2864
父进程PID 2863

  • 创建进程成功,在原有进程中返回新进程的pid

接下来我们来说说僵尸进程

孤儿进程的形成:

  • 父进程先于子进程退出,此时子进程会成为孤儿进程。

孤儿进程特征:

  • 孤儿进程会被系统指定的进程收养,即系统进程会成为孤儿进程新的父进程,当孤儿进程退出时,“继父”会处理孤儿进程退出状态,使其不会成为僵尸进程

僵尸进程的形成:

  • 子进程先于父进程退出,父进程没有处理子进程的退出状态,此时子进程就会称为僵尸进程

僵尸进程的危害:

  • 僵尸进程会滞留部分pcd信息在内存中,大量的僵尸进程会消耗系统资源,应尽量避免僵尸进程的产生。

如何表面僵尸进程的产生:

  • 1、让父进程先退出(不佳,因为不好控制)
  • 2、父进程处理子进程的退出状态

父进程处理子进程状态的方法:

(1)在父进程中阻塞等待子进程的退出os.wait()

  • 返回值:
  • pid:退出的子进程的PID号
  • status:退出的子进程的退出状态
import os
from time import sleep

pid = os.fork()

if pid < 0:
	print("Creat process failed")

elif pid == 0:
	sleep(3)
	print("Child process over")
	os._exit(3)
	
else:
	# 等待子进程执行完毕
	pid,status = os.wait()
	print("*"*30)
	print(os.WEXITSTATUS(status))  # 获取退出状态
	print(pid,status)
	while True:
		pass
fatpuffer@ubuntu:~/mysocket$ python3 fork.py
Child process over
******************************
3
3042 768

(2)非阻塞循环等待子进程退出os.waitpid(pid,option)

  • 参数:
  • pid
  • -1:表示等待任意子进程退出
  • >0:表示等待对应PID号的子进程退出
  • option
  • 0: 表示阻塞等待
  • WNOHANG: 表示非阻塞(os.WNOHANG)
import os
from time import sleep

pid = os.fork()

if pid < 0:
	print("Creat process failed")

elif pid == 0:
	sleep(3)
	print("Child process over")
	os._exit(3)
	
else:
	while True:
		sleep(1)
		#设置非阻塞状态
		pid,status = os.waitpid(-1,os.WNOHANG)
		print("*"*30)
		#print(os.WEXITSTATUS(status))#获取推出状态
		print(pid,status)
		while True:
			pass
fatpuffer@ubuntu:~/mysocket$ python3 fork.py
******************************
0
0 0
Child process over

  • waitpid(-1,0)=====wait():此时二者等价
import os
from time import sleep

pid = os.fork()

if pid < 0:
	print("Creat process failed")

elif pid == 0:
	sleep(3)
	print("Child process over")
	os._exit(3)
	
else:
	while True:
		sleep(1)
		#设置非阻塞状态
		pid,status = os.waitpid(-1,0)
		print("*"*30)
		#print(os.WEXITSTATUS(status))#获取推出状态
		print(pid,status)
		while True:
			pass
fatpuffer@ubuntu:~/mysocket$ python3 fork.py
Child process over
******************************
3
2985 768

(3)创建二级父子进程

  • 原理:子进程创建二级父子进程,然后让二级父进程直接退出,使得二级子进程成为孤儿进程,在执行完任务后自动被系统回收,这样一来就不会存在,子进程死掉后父进程没有处理,使其变为僵尸进程的情况。
#创建二级子进程处理僵尸
import os
from time import sleep

def fun1():
	sleep(3)
	print("第一件事情")

def fun2():
	sleep(4)
	print("第二件事情")

pid = os.fork()

if pid < 0:
	print("create process failed")

# 子进程
elif pid == 0:
	#创建二级子进程
	pid0 = os.fork()
	if pid0 < 0:
		print("create process failed")
	
	# 子进程
	elif pid0 == 0:
		fun2()
	
	# 父进程
	else:
		# 父进程直接退出,让子进程成为孤儿进程,执行完任务后自动被系统回收
		os._exit(0)

# 父进程
else:
	os.wait()
	fun1()#做第一件事情
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值