定义:程序在计算机中的一次运行.python
系统中如何产生一个进程面试
进程基本概念编程
Linux查看进程ID:ps - aux多线程
查看进程树: pstreeapp
五态(在三态基础上增长新建和终止)dom
状态查看命令: ps - aux --->STAT列async
S---等待态ide
R---执行态函数
Z---僵尸ui
+---前台进程
l---有多线程
进程的运行特征
面试要求:
什么是进程,进程和程序有什么区别?
进程有哪些状态,状态之间如何转化?
pdi = os.fork()
功能:建立新的进程
返回值:整数,若是建立进程失败返回一个负数,若是成功则在原有进程中返回新进程的PID,在新进程中返回0
注意:
fork进程代码示例:
1 import os 2 from time import sleep 3 4 # 建立子进程 5 pid = os.fork() 6 7 if pid < 0: 8 print("Create process failed") 9 elif pid == 0: 10 # 只有子进程执行 11 sleep(3) 12 print("The new process") 13 else: 14 # 只有父进程执行 15 sleep(4) 16 print("The old process") 17 18 # 父子进程都执行 19 print("process test over")
fork进程代码示例细节:
1 import os 2 from time import sleep 3 4 print("=========================") 5 a = 1 6 def fun(): 7 print("fun .... ") 8 9 pid = os.fork() 10 11 if pid < 0: 12 print("Create process failed") 13 elif pid == 0: 14 print("Child process") 15 print("a = ",a) # 从父进程空间拷贝了变量 16 fun() 17 a = 10000 # 只是修改了本身空间的a 18 else: 19 sleep(1) 20 print("Parent process") 21 print("a:",a) 22 23 print("All a ->",a)
os.getpid()
功能:获取一个进程的PID值
返回值:返回当前进程的PID
os.getppid()
功能:获取父进程的PID值
返回值:返回父进程PID
os._exit(status)
功能:结束一个进程
参数:进程的终止状态
sys.exit([status])
功能:退出进程
参数:整数 表示退出状态
字符串 表示退出时打印内容
获取进程pid号代码示例:
1 import os 2 from time import sleep 3 4 pid = os.fork() 5 6 if pid < 0: 7 print("Error") 8 elif pid == 0: 9 sleep(1) 10 print("Child PID:",os.getpid()) # 本身pid 11 print("Get parent PID:",os.getppid()) # 父pid 12 else: 13 print("Parent PID:", os.getpid()) # 本身pid 14 print("Get child PID:",pid)
进程退出代码示例:
1 import os,sys 2 3 pid = os.fork() 4 5 # 父子进程退出不会影响对方继续执行 6 if pid < 0: 7 print("Error") 8 elif pid == 0: 9 # os._exit(0) # 子进程退出 10 print("Child process") 11 else: 12 sys.exit("退出父进程") 13 print("Parent process")
特色:孤儿进程会被系统进程收养,此时系统进程就会成为孤儿进程新的父进程,孤儿进程退出该进程会自动处理
特色:僵尸进程虽然结束,可是会存留部分PCD在内存中,大量的僵尸进程会浪费系统的内存资源
模拟僵尸进程产生以及处理示例:
1 import os,sys 2 import signal 3 4 # 忽略子进程的退出行为,子进程退出自动由系统处理 5 signal.signal(signal.SIGCHLD,signal.SIG_IGN) 6 7 pid = os.fork() 8 if pid < 0: 9 print("Error") 10 elif pid == 0: 11 print("Child PID:",os.getpid()) 12 sys.exit(2) 13 else: 14 """ 15 os.wait() 处理僵尸 16 """ 17 # pid,status = os.wait() 18 # print("pid:",pid) 19 # print('status:',os.WEXITSTATUS(status)) 20 while True: # 让父进程不退出 21 pass
代码示例:
1 import os 2 from time import sleep 3 4 def f1(): 5 for i in range(3): 6 sleep(2) 7 print("写代码") 8 9 def f2(): 10 for i in range(2): 11 sleep(4) 12 print("测代码") 13 14 pid = os.fork() 15 if pid == 0: 16 p = os.fork() # 建立二级子进程 17 if p == 0: 18 f1() 19 else: 20 os._exit(0) # 一级子进程退出 21 else: 22 os.wait() # 等待回收一级子进程 23 f2()
经过信号处理子进程退出
原理:子进程退出时会发送信号给父进程,若是父进程忽略子进程信号,则系统就会自动处理子进程退出
方法:使用signal模块在父进程建立子进程前写以下语句:
import signal
signal.signal(signal.SIGCHLD,signal.SIG_IGN)
特色:非阻塞,不会影响父进程运行,能够处理全部子进程退出
Process()
功能 : 建立进程对象
参数 : target 绑定要执行的目标函数
args 元组,用于给target函数位置传参
kwargs 字典,给target函数键值传参
p.start()
功能 : 启动进程
注意:启动进程此时target绑定函数开始执行,该函数做为子进程执行内容,此时进程真正被建立
p.join([timeout]) 功能:阻塞等待回收进程 参数:超时时间
注意:
子进程只运行target绑定的函数部分,其他内容均是父进程执行内容。
multiprocessing中父进程每每只用来建立子进程回收子进程,具体事件由子进程完成。
multiprocessing建立的子进程中没法使用标准输入
p.name 进程名称
p.pid 对应子进程的PID号
p.is_alive() 查看子进程是否在生命周期
p.daemon 设置父子进程的退出关系
进程对象代码示例:
1 from multiprocessing import Process 2 import time 3 4 def tm(): 5 for i in range(3): 6 print(time.ctime()) 7 time.sleep(2) 8 9 p = Process(target = tm,name = 'Tarena') 10 11 # 父进程退出,其全部子进程也退出 12 p.daemon = True 13 14 p.start() # 进程真正产生 15 16 print("Name:",p.name) # 进程名 17 print("PID:",p.pid) # pid号 18 print("is alive:",p.is_alive()) # 是否在生命周期
自定义进程类代码示例:
1 from multiprocessing import Process 2 from time import * 3 4 # 自定义进程类 5 class MyProcess(Process): 6 def __init__(self,value): 7 self.value = value 8 super().__init__() # 加载父类init 9 10 def f1(self): 11 print("步骤1") 12 def f2(self): 13 print("步骤2") 14 15 # 做为流程启动函数 16 def run(self): 17 for i in range(self.value): 18 self.f1() 19 self.f2() 20 21 if __name__ == '__main__': 22 p = MyProcess(2) 23 p.start() 24 p.join()
建立必定数量的进程来处理事件,事件处理完进程不退出而是继续处理其余时间,直到全部事件全都处理完毕统一销毁.增长进程的重复利用,下降资源消耗.
1.建立进程池对象,放入适当的进程
from multiprocessing import Pool
Pool(processes)
功能: 建立进程池对象
参数: 指定进程数量,默认根据系统自动断定
2.将事件加入进程池队列执行
pool.apply_async(func,args,kwds)
功能: 使用进程池执行 func事件
参数: func 事件函数
args 元组 给func按位置传参
kwds 字典 给func按照键值传参
返回值: 返回函数事件对象
3.关闭进程池
pool.close()
功能: 关闭进程池
4.回收进程池中进程
pool.join()
功能: 回收进程池中进程
进程池代码示例:
1 from multiprocessing import Pool 2 from time import sleep,ctime 3 4 # 进程池事件 5 def worker(msg): 6 sleep(2) 7 print(ctime(),'--',msg) 8 9 # 建立进程池 10 pool = Pool(4) 11 12 # 向进程池队列中添加事件 13 for i in range(10): 14 msg = "Tedu %d"%i 15 pool.apply_async(func=worker,args=(msg,)) 16 17 # 关闭进程池 18 pool.close() 19 20 # 回收进程池 21 pool.join()
在内存中开辟管道空间,生成管道操做对象,多个进程使用同一管道对象,进行读写便可实现通讯
from multiprocessing import Pipe
fd1,fd2 = Pipe(duplex = True) 功能: 建立管道 参数:默认表示双向管道 若是为False 表示单向管道 返回值:表示管道两端的读写对象 若是是双向管道都可读写 若是是单向管道fd1只读 fd2只写 fd.recv() 功能 : 从管道获取内容 返回值:获取到的数据 fd.send(data) 能够是任何内容,如:整数,浮点数,字符串等 功能: 向管道写入内容 参数: 要写入的数据
管道操做
注意:
管道操做代码示例:
1 from multiprocessing import Process,Pipe 2 3 # 建立管道对象 4 # 参数False 表示fd1 只能 recv , fd2 只能 send 5 fd1,fd2 = Pipe() 6 7 # APP1可使用app2提供的信息登陆 8 def app1(): 9 print("启动app1,请登陆") 10 print("请求app2受权") 11 # 写管道 12 fd1.send("app1 能够用你的帐号登陆吗?") 13 data = fd1.recv() 14 if data: 15 print("登陆成功:",data) 16 17 def app2(): 18 request = fd2.recv() # 阻塞等待读取管道 19 print(request) 20 fd2.send(('Joy','123')) # 发送python数据类型 21 22 p1 = Process(target=app1) 23 p2 = Process(target=app2) 24 p1.start() 25 p2.start() 26 p1.join() 27 p2.join() 28 29 代码示例
在内存中创建队列模型,进程经过队列将消息存入,或者从队列取出完成进程间通讯.
from multiprocessing import Queue q = Queue(maxsize=0) 功能: 建立队列对象 参数:最多存放消息个数 返回值:队列对象 q.put(data,[block,timeout]) 功能:向队列存入消息 参数:data 要存入的内容 block 设置是否阻塞 False为非阻塞 timeout 超时检测 q.get([block,timeout]) 功能:从队列取出消息 参数:block 设置是否阻塞 False为非阻塞 timeout 超时检测 返回值: 返回获取到的内容 q.full() 判断队列是否为满 q.empty() 判断队列是否为空 q.qsize() 获取队列中消息个数 q.close() 关闭队列
消息队列代码示例:
1 from multiprocessing import Queue,Process 2 from time import sleep 3 from random import randint 4 5 # 建立队列 6 q = Queue(5) # 最大存储5个消息 7 8 def request(): 9 for i in range(10): 10 x = randint(1,100) 11 y = randint(1,100) 12 q.put((x,y)) # 写消息队列 13 print("=============") 14 15 def handle(): 16 while not q.empty(): 17 data = q.get() # 读消息队列 18 print("x + y = ",data[0]+data[1]) 19 sleep(2) 20 21 p1 = Process(target=request) 22 p2 = Process(target=handle) 23 p1.start() 24 p2.start() 25 p1.join() 26 p2.join() 27 28 代码示例
from multiprocessing import Value,Array obj = Value(ctype,data) 功能 : 开辟共享内存 参数 : ctype 表示共享内存空间类型 'i' 'f' 'c' data 共享内存空间初始数据 返回值:共享内存对象 obj.value 对该属性的修改查看即对共享内存读写 obj = Array(ctype,data) 功能: 开辟共享内存空间 参数: ctype 表示共享内存数据类型 data 整数则表示开辟空间的大小,其余数据类型表示开辟空间存放的初始化数据 返回值:共享内存对象 Array共享内存读写: 经过遍历obj能够获得每一个值,直接能够经过索引序号修改任意值。 * 可使用obj.value直接打印共享内存中的字节串
共享内存代码示例:
注意:共享内存中只能有一个值
1 from multiprocessing import Process,Value 2 import time 3 import random 4 5 # 建立共享内存 6 money = Value('i',5000) 7 8 def man(): 9 for i in range(30): 10 time.sleep(0.2) 11 # 修改共享内存 12 money.value += random.randint(1,1000) 13 14 def girl(): 15 for i in range(30): 16 time.sleep(0.15) 17 money.value -= random.randint(100,800) 18 19 p1 = Process(target=man) 20 p2 = Process(target=girl) 21 p1.start() 22 p2.start() 23 p1.join() 24 p2.join() 25 print("一个月余额:",money.value) #读取共享内存
共享内存存放列表,字节串:
1 from multiprocessing import Process,Array 2 3 # 建立共享内存,初始数据 [1,2,3,4] 4 # shm = Array('i',[1,2,3,4]) 5 # shm = Array('i',4) # 开辟4个整形的列表空间 6 shm = Array('c',b'hello') 7 8 def fun(): 9 # 共享内存对象能够迭代 10 for i in shm: 11 print(i) 12 shm[0] = b'H' # 修改共享内存 13 14 p = Process(target=fun) 15 p.start() 16 p.join() 17 for i in shm: 18 print(i) 19 print(shm.value) # 总体打印字节串
给定一个数量对多个进程可见.多个进程均可以操做改数量增减,并根据数量值决定本身的行为
from multiprocessing import Semaphore sem = Semaphore(num) 功能 : 建立信号量对象 参数 : 信号量的初始值 返回值 : 信号量对象 sem.acquire() 将信号量减1 当信号量为0时阻塞 sem.release() 将信号量加1 sem.get_value() 获取信号量数量
信号量代码示例:
注意: 信号量能够当作是一种资源,执行任务须要消耗信号量资源,
这样能够控制进程执行行为
1 from multiprocessing import Process,Semaphore 2 from time import sleep 3 import os 4 5 # 建立信号量资源 6 sem = Semaphore(3) 7 8 # 任务函数 (系统中最多可以同时运行三个该任务) 9 def handle(): 10 sem.acquire() # 消耗一个信号量 11 print("%s执行任务"%os.getpid()) 12 sleep(2) 13 print("%s 拯救了宇宙"%os.getpid()) 14 sem.release() # 增长一个信号量 15 16 jobs = [] 17 for i in range(10): 18 p = Process(target = handle) 19 jobs.append(p) 20 p.start() 21 22 for i in jobs: 23 i.join()