python进程(一)

文章目录

        • 多任务编程
        • 进程
        • 进程的优先级
        • 父子进程
        • 进程相关的函数
          • os.getpid()
          • os.getppid()
          • os._exit(status)
          • sys.exit([status])
        • 僵尸进程
        • 处理僵尸进程的方法
          • os.wait()
          • os.waitpid(pid, option)
          • 创建二级子进程处理
          • 在父进程中使用信号处理的方法,忽略子进程发来的信号
        • 孤儿进程

多任务编程

可以有效的利用计算机资源,同时执行多个任务

进程

进程就是程序在计算机中一次执行的过程
进程和程序的区别:
程序是一个静态文件的描述,不占计算机的系统资源
进程是一个动态的过程,占有CPU、内存等资源,有一定的生命周期
同一个程序的不同执行过程即为不同的进程

问题1:什么决定了进程的创建
1)用户通过应用层程序进行进程的创建申请
2)调用操作系统接口进行进程创建
3)告知系统内核创建新的进程提供给应用层使用
问题2:进程如何占有CPU
1)同一个内核同一时刻只能运行一个进程
2)多个进程对内核资源进行抢占,由操作系统内核进行分配
3)哪个进程占有计算机内核,我们称为该进程占有CPU的时间片
问题3:进程在运行过程中的形态和附带内容
1)PCB(进程控制块):在linux和unix操作系统中,进程创建后会在内存中开辟一块空间存放进程的相关信息,这个空间称之为PCB
2)PID:在操作系统中进程的唯一标识,是一个大于0的正整数,由系统自动分配
ps -aux 查看进程信息
虚拟内存:每个进程占有4G内存地址空间,这里的内存指的是虚拟内存
进程状态:
三态
就绪态: 进程具备运行条件,等待系统分配处理器以便运行
运行态:进程占有cpu处于运行状态
等待态:又称为阻塞态或者睡眠态,指进程不具备运行条件,正在等待某些条件的达成
五态
就绪态: 进程具备运行条件,等待系统分配处理器以便运行
运行态:进程占有cpu处于运行状态
等待态:又称为阻塞态或者睡眠态,指进程不具备运行条件,正在等待某些条件的达成
新建:创建一个进程的过程,直接表现为执行某个程序或者在程序中创建新的进程
终止:进程执行结束,完成回收的过程
D: 等待态,不可中断等待态
S: 等待态,可中断等待态
T: 等待态,暂停状态
R: 运行态
Z: 僵尸态

+: 前台进程
N: 低优先级的进程
<: 高优先级的进程
l: 有进程链接
s: 会话组

进程的优先级

优先级往往决定了一个进程的执行权限和占有系统资源的优先程度
top: 动态查看系统进程运行情况
linux系统中优先级范围为-20—19,其中-20优先级最高,19优先级最低,0为平均状态,用户创建进程默认优先级为0
nice: 以指定的优先级运行某一个进程

 nice -9 ./while.py 	 以9的优先级运行程序
 sudo nice --9 ./while.py 	 以-9的优先级运行程序

renice n PID: 修改一个正在运行的进程的优先级

renice 8 4277 	将4277号进程优先级修改为8

父子进程

在系统中除了初始化进程之外,每个进程都是由父进程创建的,每个进程有一个唯一的父进程,可能有多个子进程
需求:两间不相关事情希望同时来做

# test.py文件
import time

def fun1():
	time.sleep(6)
	print('做完第一件事情')


def fun2():
	time.sleep(4)
	print('做完第二件事情')

方案一:写两个进程,分别承担不同的事情,各自执行
分析:1. 两个程序比较麻烦
2. 无法确定两个程序应该在什么时间开始运行
方案二:写一个程序,在程序中指定位置调用接口来创建新的进程
实现方法: os.fork()函数实现
fork()
功能:创建一个新的进程
参数:无
返回值:
小于0 表示进程创建失败
等于0 表示在子进程中fork的返回值为0
大于0 在父进程中fork的返回值大于0

  • fork是os模块函数,只能在linux和unix下使用
    测试1:父进程中fork之前的内容,子进程同样也会复制,但是父子进程空间内容的修改不会相互影响
    测试2:父子进程在执行上互不影响,理论上不一定谁先执行
    测试3:子进程虽然复制父进程的空间,但也有自己独特的特性,比如自己的pid,进程控制块,进程栈等。父进程中fork的返回值即为创建的子进程的pid号
# os模块提供了大量和系统相关的功能函数接口
# os模块的使用是系统相关的,在不同的系统中可能使用方法不同
import os
import time

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

if pid < 0:
	print('create process failed')
elif pid == 0:
	print('pid:')
	print(pid)
	while True:
		time.sleep(0.8)
		print('This is the new process')
else:
	# 父进程中pid为子进程的PID号
	print('parent pid:')
	print(pid)
	while True:
		time.sleep(1)
		print('This is the parent process')

print('The process end')

需求解决:

import os
import time
# 导入test中的函数
from test import *

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

if pid < 0:
	print('create process failed')
elif pid == 0:
	fun1()
else:
	fun2()

进程相关的函数

os.getpid()

功能:获取当前进程的PID号

import os

pid = os.fork()

if pid < 0:
	print('create process failed')
elif pid == 0:
	print('Child process:')
	print('当前进程的PID:', os.getpid())
else:
	print('Parent process')
	print('pid:', pid)
os.getppid()

功能:获取当前进程父进程的PID号

os._exit(status)

功能:用来结束一个进程
参数:一个数字,表示进程的退出状态,通常0表示正常退出进程,其他数字表示非正常退出

sys.exit([status])

功能:用来结束一个进程, 如果处理了抛出的异常,则不结束进程
参数:一个数字,表示进程的退出状态,同上
还可以是一个字符串,则在进程退出时会打印这个字符串

import os
import sys

# 抛出异常进程不结束
try:
	sys.exit('over')
except SystemExit as e:
	print(e)

print('process over')

僵尸进程

子进程先于父进程退出,父进程没有对子进程的退出做相应的处理,此时子进程就会变为僵尸进程
影响:进程退出后,仍有部分信息残留在内存中占用空间,大量的僵尸进程会影响系统运行,所以应该尽量避免僵尸进程的产生。

处理僵尸进程的方法

  1. 让父进程先退出(不好控制)
  2. 父进程处理子进程的退出(阻塞父进程的运行)
os.wait()

功能:等待子进程退出进行处理
参数:无
返回值:返回一个包含两个元素的元组,第一个是退出的子进程的PID号,第二个是子进程的退出状态

  • wait是一个阻塞函数,即进程处于等待状态,等待某种条件的达成才会继续运行
import os
import sys
from time import sleep

pid = os.fork()

if pid < 0:
	print('create process failed')
elif pid == 0:
	print('child process...')
	sleep(2)
	sys.exit(6) # 子进程退出
else:
	# wait 阻塞等待子进程的退出
	p, status = os.wait()
	print('parent process...')
	print('p, status:', p, status)
os.waitpid(pid, option)

功能:同wait, 处理子进程退出,使其不会成为僵尸
参数:
pid=-1表示等待任意子进程退出
pid大于0表示等待指定进程号的子进程退出
option=0 表示阻塞等待
option=WNOHANG 表示非阻塞状态
返回值:同wait

创建二级子进程处理
# 创建二级子进程解决僵尸进程
import os

# 创建一级子进程
pid = os.fork()

if pid < 0:
	print('create process failed')
elif pid == 0:
	# 创建二级子进程
	p = os.fork()
	if p < 0:
		print('process failed')
	elif p == 0:
		print('做二级子进程任务')
	else:
		# 一级子进程退出,使二级子进程成为孤儿
		os._exit(0)
else:
	# 等待一级子进程退出
	os.wait()
	print('做父进程任务')
在父进程中使用信号处理的方法,忽略子进程发来的信号

signal(SIGCHLD, SIG_IGN)

孤儿进程

父进程先于子进程退出,此时子进程就会变为孤儿进程
影响:当一个进程变为孤儿进程,系统会自动的使用一个进程成为孤儿进程的父进程。当孤儿进程退出时,该系统进程会自动回收孤儿,使他不会成为僵尸。所以孤儿进程对系统资源没有什么影响。

你可能感兴趣的:(Python)