进程 是个资源分配单位
狭义定义: 进程是正在运行的程序的实例
广义定义: 进程是一个具有一定独立功能的程序关于某个数据集合的一次运行活动.它是操作系统动态执行的基本单元,在传统的操作系统中,进程即是基本的分配单元,也是基本的执行单元
进程概念:
第一,进程是一个实体。每一个进程都有它自己的地址空间,一般情况下,包括文本区域(text region)、数据区域(data region)和堆栈(stack region)。文本区域存储处理器执行的代码;数据区域存储变量和进程执行期间使用的动态分配的内存;堆栈区域存储着活动过程调用的指令和本地变量。
第二,进程是一个“执行中的程序”。程序是一个没有生命的实体,只有处理器赋予程序生命时(操作系统执行之),它才能成为一个活动的实体,我们称其为进程。
进程是操作系统中最基本、重要的概念。是多道程序系统出现后,为了刻画系统内部出现的动态情况,描述系统内部各道程序的活动规律引进的一个概念,所有多道程序设计操作系统都建立在进程的基础上。
进程调度 : 就是多个进程(运行中的程序) 在操作系统的控制下被CPU 执行,去享用计算机资源
先来先服务
短作业优先
时间片轮转
多级反馈队列
进程调度的过程是不能够随意被程序影响的
程序的并行与并发
并行更快
并发只是宏观上的同时执行
进程一共有三个状态:
就绪 运行 阻塞
同步: 就是 比如 洗衣和做饭 按顺序一个一个做 是同步走
异步: 一边洗衣 一边做饭, 这就是异步走
阻塞
非阻塞
进程
pid Process ID 进程ID
ppid parent process id 父进程 ID
父进程 负责回收一些子进程的资源
子进程
在python程序中的进程操作
multiprocess模块
multiprocess.process模块
不是一个模块 而是python中一个操作,管理进程的包
创建进程部分
进程同步部分
进程池部分
进程之间数据分享
process模块是一个创建进程的模块,借助这个模块,就可以完成进程的创建
Process([group [, target [, name [, args [, kwargs]]]]]),由该类实例化得到的对象,表示一个子进程中的任务(尚未启动) 强调: 1. 需要使用关键字的方式来指定参数 2. args指定的为传给target函数的位置参数,是一个元组形式,必须有逗号 参数介绍: 1 group参数未使用,值始终为None 2 target表示调用对象,即子进程要执行的任务 3 args表示调用对象的位置参数元组,args=(1,2,'egon',) 4 kwargs表示调用对象的字典,kwargs={'name':'egon','age':18} 5 name为子进程的名称
1 p.start():启动进程,并调用该子进程中的p.run() 2 p.run():进程启动时运行的方法,正是它去调用target指定的函数,我们自定义类的类中一定要实现该方法 3 p.terminate():强制终止进程p,不会进行任何清理操作,如果p创建了子进程,该子进程就成了僵尸进程,使用该方法需要特别小心这种情况。如果p还保存了一个锁那么也将不会被释放,进而导致死锁 4 p.is_alive():如果p仍然运行,返回True 5 p.join([timeout]):主线程等待p终止(强调:是主线程处于等的状态,而p是处于运行的状态)。timeout是可选的超时时间,需要强调的是,p.join只能join住start开启的进程,而不能join住run开启的进程
使用process模块创建进程
os.getpid 返回当前进程的id
os.getppid 返回当前父进程的id
import os import time from multiprocessing import Process ##进程模块 def func(): print('in func',os.getpid(),os.getppid()) if __name__ == '__main__': print('in main',os.getpid(),os.getppid()) p1 = Process(target = func ) ##进程对象 p1.start() #向操作系统提交了一个开启子进程的申请 p2 = Process(target = func) #进程对象 p2.start() #想操作系统提交了一个开启子进程的申请 print('主进程的代码执行结束了') 得到结果: in main 6604 12564 主进程 的 代码执行结束了 in func 3584 6604 in func 3036 6604 原理 if __name__ == '__main__' 使用python都是调用操作系统的命令来启动进程 同样视同python 不同的操作系统的操作是不同的 对于windows来说 必要要加 if __name__ == '__main__' 对于linux_ios 来说,不必要加 if __name__ == '__main__' 那怎么给子进程里面传参数呢? def func(num): time.sleep(2) print('in func',num,os.getpid(),os.getppid()) if __name__ == '__main__': print('in main',os.getpid(),os.getppid()) p1 = Process(target=func,args=(1,)) # 进程对象 p1.start() # 向操作系统提交了一个开启子进程的申请 p2 = Process(target=func,args=(2,)) # 进程对象 p2.start() # 向操作系统提交了一个开启子进程的申请 print('主进程 的 代码执行结束了')
其他方法和属性
1.开启多个子进程 def func(num): print('in func',num,os.getpid(),os.getppid()) if __name__ == '__main__': print('in main',os.getpid(),os.getppid()) for i in range(10): p = Process(target=func,args=(i,)) p.start() # start不是运行一个程序,而是调用操作系统的命令,要创建子进程 print('主进程 的 代码执行结束了') 2.join方法 def func(num): time.sleep(1) print('in func',num,os.getpid(),os.getppid()) if __name__ == '__main__': print('in main',os.getpid(),os.getppid()) p = Process(target=func,args=(1,)) p.start() # start不是运行一个程序,而是调用操作系统的命令,要创建子进程 p.join() # 阻塞,直到p这个子进程执行完毕之后再继续执行 print('主进程 的 代码执行结束了') 3.一批任务使用join def func(num): print('in func',num,os.getpid(),os.getppid()) if __name__ == '__main__': print('in main',os.getpid(),os.getppid()) p_l = [] for i in range(10): p = Process(target=func,args=(i,)) p.start() # start不是运行一个程序,而是调用操作系统的命令,要创建子进程,非阻塞 p_l.append(p) print(p_l) for p in p_l : p.join() # 阻塞,直到p这个子进程执行完毕之后再继续执行 print('主进程 的 代码执行结束了') 4.is_alive terminate def func(num): time.sleep(2) print('in func',num,os.getpid(),os.getppid()) if __name__ == '__main__': print('in main',os.getpid(),os.getppid()) p1 = Process(target=func,args=(1,)) # 进程对象 p1.start() # 向操作系统提交了一个开启子进程的申请 print(p1.is_alive()) # 检测进程是否在执行任务 p1.terminate() # 强制结束子进程 - 非阻塞 print(p1.is_alive()) # 检测进程是否在执行任务 print('主进程 的 代码执行结束了') 用面向对象的方式开启子进程 class MyProcess(Process): def __init__(self,num): super().__init__() self.num = num def run(self): print('in run ',self.num,os.getpid(),os.getppid()) if __name__ == '__main__': print('in main ', os.getpid(), os.getppid()) p = MyProcess(1) p.start()
进程之间的数据隔离问题
n= 100 def func(): global n n = n-1 return 111 if__name__ =='__main__': n_l = [] for i in range(100): p = Process(target=func) p.start() n_l.append(p) for p in n_l : p.join() print(n) 进程与进程之间的数据是隔离的 内存空间是不能共享的 所以要想进行通信,必须借助其他手段 且这两个进程都是自愿的
守护进程
是会随着主进程的结束而结束.
主进程创建守护进程.
其一 : 守护进程会在主进程代码执行结束后就终止
其二 : 守护进程内无法再开启子进程,否则抛出异常
注意:进程之间是互相独立的,主进程代码运行结束,守护进程随即停止
例一 (创建守护进程) import time
from multiprocessing import Process def func1(): print('begin') time.sleep(3) print('wahaha') if __name__ == '__main__':sad p = Process(target = func1) p.daemon = True ###守护进程的属性,默认是False,如果设置成True,就表示设置这个子进程为一个守护进程 ,,,设置守护进程的操作应该在开启子进程之前 p.start() time.sleep(1) print('主进程') 得到结果: begin 主进程
例二 import time from multiprocessing import Process def func1(): print('begin') time.sleep(3) print('wahaha') def func2(): while True: print('in func2') time.sleep(0.5) if __name__ == '__main__': Process(target = func1).start() p = Process(target = func2) p.daemon = True ##看清楚,是把p搞成了守护进程 p是func2 p.start() time.sleep(1) print('主进程') 设置成守护进程之后,会有什么效果呢? 守护进程会在主进程的代码执行完毕之后直接结束,无论守护进程是否执行完毕
应用
守护进程可以用来做报活
报活 报告你的主进程还活着
守护进程如何向检测机制报活???send/写数据库
为什么要用守护机制来报活呢?为什么不用主进程来工作呢?
守护进程报活几乎不占用CPU,也不需要操作系统去调度
主进程不能严格每60秒发送一条信息(时间上控制不了)
####所有的进程的基本使用
####进程 :同一时刻可以做多件事情,互相之间不受影响
####
多进程的 socket例子
服务器 import socket from multiprocessing import Process def talk(conn): try: while True: conn.send(b'hello') print(conn.recv(1024)) finally: conn.close() if __name__ =='__main__': sk = socket.socket() sk.bind(('127.0.0.1',9091)) sk.listen() try: while True: conn,addr = sk.accept() Process(target = talk,args= (conn,)).start() finally: sk.close() 客户端 import socket import os sk = socket.socket() sk.connect(('127.0.0.1',9091)) while True: print(sk.recv(1024)) sk.send(str(os.getpid()).encode('utf-8'))