1.进程和程序的区别
程序:就是一堆计算机可以识别文件,程序在没有被运行就是躺在硬盘上的一堆二进制
进程:一个正在被运行的程序就称之为进程,是程序具体执行过程,一种抽象概念
运行程序时,要从硬盘读取数据到内存中,CPU从内存读取指令并执行 ,一旦运行就产生了进程
注意:一个程序可以多次执行 产生多个进程,但是进程之间相互独立
2.PID和PPID
PID:系统会给每一个进程分配一个进程编号即PID,如同人需要一个身份证号来区分。
#tasklist 用于查看所有的进程信息
#taskkill /f /pid pid 该命令可以用于结束指定进程
import os
print(os.getpid())
#得到的是当前运行的pid
PPID:父进程的进程编号
当一个进程a开启了另一个进程b时,a称为b的父进程,b称为a的子进程。
# 在python中可以使用os模块来获取ppid
import os
print("self",os.getpid()) # 当前进程自己的pid
print("parent",os.getppid()) # 当前进程的父进程的pid
如果是在pycharm中运行的py文件,那pycahrm就是这个python.exe的父进程,当然你可以从cmd中来运行py文件,那此时cmd就是python.exe的父进程
并发:多个任务看起来同时在处理 ,本质上是切换执行 速度非常快
并行: 多个任务真正的同时执行 必须具备多核CPU 才可能并行
阻塞:阻塞状态是因为程序遇到了IO操作,或是sleep,导致后续的代码不能被CPU执行
本地IO input print sleep read write
非阻塞:非阻塞与之相反,表示程序正在正常被CPU执行
注意:
1.阻塞 非阻塞 说的是程序的运行状态
2.并发 并行 说的是 任务的处理方式
4.进程三种状态的切换:就绪态,运行态,和阻塞态
多道技术会在进程执行时间过长或遇到IO时自动切换其他进程,意味着IO操作与进程被剥夺CPU执行权都会造成进程无法继续执行
注意:
在编程过程中,提高效率根本就是让程序尽可能处于运行状态,减少IO操作,尽可能多占用CPU时间
5.
创建:
1. 系统初始化(查看进程linux中用ps命令,windows中用任务管理器,前台进程负责与用户交互,后台运行的进程与用户无关,运行在后台并且只在需要时才唤醒的进程,称为守护进程,如电子邮件、web页面、新闻、打印)
2. 一个进程在运行过程中开启了子进程(如nginx开启多进程,os.fork,subprocess.Popen等)
3. 用户的交互式请求,而创建一个新进程(如用户双击暴风影音)
4. 一个批处理作业的初始化(只在大型机的批处理系统中应用)
销毁:
1. 正常退出(自愿,如用户点击交互式页面的叉号,或程序执行完毕调用发起系统调用正常退出,在linux中用exit,在windows中用ExitProcess)
2. 出错退出(自愿,python a.py中a.py不存在)
3. 严重错误(非自愿,执行非法指令,如引用不存在的内存,1/0等,可以捕捉异常,try...except...)
4. 被其他进程杀死(非自愿,如kill -9)
6.开启子进程的两种方式
1.实例化Process类,将要执行任务用target传入
from multiprocessing import Process
import time
def task(name):
print('%s is running' %name)
time.sleep(3)
print('%s is done' %name)
if __name__ == '__main__':
# 在windows系统之上,开启子进程的操作一定要放到这下面
# Process(target=task,kwargs={'name':'egon'})
p=Process(target=task,args=('jack',))
p.start() # 向操作系统发送请求,操作系统会申请内存空间,然后把父进程的数据拷贝给子进程,作为子进程的初始状态
print('======主')
2.继承Process类 ,覆盖run方法 将任务放入run方法中
import os
from multiprocessing import Process
class MyProcess(Process):
def __init__(self,name):
super().__init__()
self.name = name
# 继承Procee覆盖run方法将要执行任务发到run中
def run(self):
print(self.name)
print("子进程 %s running!" % os.getpid())
print("子进程 %s over!" % os.getpid())
if __name__ == '__main__':
# 创建时 不用再指定target参数了
p = MyProcess("rose")
p.start()
print("父进程over!")
注意:
1.在windows下 开启子进程必须放到__main__
下面,自启动,因为windows在开启子进程时会重新加载所有的代码造成递归创建进程
from multiprocessing import Process
import time
name = "青椒"
def task():
global name
name = "rose"
print("改完了!")
print("子进程的%s" % name)
if __name__ == '__main__':
p = Process(target=task)
p.start()
time.sleep(2)
print(name)
8.join函数
import time,os
from multiprocessing import Process
# def task(i):
# # print(" %s 买烟去了" % i)
# time.sleep(3)
# print("%s 买完了!" % i)
#
# if __name__ == '__main__':
# # p = Process(target=task)
# # p.start()
# # # time.sleep(5)
# # p.join() # 等待子进程执行完毕 将子进程的优先级提高
# #
#
#
#
# for i in range(10):
# p = Process(target=task,args=(i,))
# p.start() # 进程启动顺序 与start无关 主要看操作系统先切换谁
# # p.join()
#
# p.join() # 最后一个
#
#
# print("over!")
import time,os
from multiprocessing import Process
def task(i):
# print(" %s 买烟去了" % i)
time.sleep(i)
print("%s 买完了!" % i)
if __name__ == '__main__':
strat_time = time.time()
p1 = Process(target=task,args=(1,))
p2 = Process(target=task,args=(2,))
p3 = Process(target=task,args=(3,))
p1.start()
p2.start()
p3.start()
p3.join() #3
p2.join()
p1.join()
end_time = time.time()
print(end_time - strat_time)
print("over!")
9.Process常用方法属性
from multiprocessing import Process
import time,os
def task():
print("121121")
# time.sleep(10)
# print("over")
# print(os.getppid())
exit(1000)
if __name__ == '__main__':
p = Process(target=task,name="rose")
p.start() # 懒加载优化机制 如果没有调用start 那么该对象将不会被创建
time.sleep(1)
# p.join() # 等待子进程结束
# p.terminate() # 终止进程
# print(p.name) # 进程的名称
# print(p.is_alive()) #是否存活
# p.terminate() # 与start一样 都是给操作系统发送指令 所以会有延迟
# print(p.is_alive())
# print(p.pid)
# print(p.exitcode) # 获取退出码
10.
1.孤儿进程:指的是,父进程先结束 ,而子进程还在运行着
孤儿进程无害,有 其存在的必要性
孤儿进程会被操作系统接管
2.僵尸进程:僵尸进程指的是,当子进程比父进程先结束,而父进程又没有回收子进程,释放子进程占用的资源,此时子进程将成为一个僵尸进程。
子进程已经结束了,但是操作系统会保存一些进程信息,如PID,运行时间等,僵尸进程如果太多将会占用大量的资源,造成系统无法开启新新进程
linux 中有一个wai/waitpid 用于父进程回收子进程资源,python会自动回收僵尸进程