Python之路PythonThread,第一篇,进程1
python3 进程1
多任务编程: 可以有效的利用计算机资源,同时执行多个任务,
进程:进程就是程序在计算机中一次执行的结果;
进程和程序的区别:
程序是一个静态文件的描述,不占用计算机的系统资源;
进程是一个动态的过程,占有cpu内存等资源,有一定的生命周期;
* 同一个程序的不同执行过程即为不同的进程;
问题1 ,什么决定了进程的创建;
用户通过应用层程序进行进程的创建申请 ----》》
调用操作系统接口进行程序创建--》》
告知系统内核创建新的进程提供给应用层使用
问题2,进程如何占用CPU
1,同一个内核同一时刻只能运行一个进程
2, 多个进程对内核资源进行抢占,由操作系统内核进行分配
3,哪个进程占有计算机内核我们称之为该进程占有CPU的时间片;
问题3, 进程在运行过程中的形态和附带内容;
PCB(进程控制块):在linux和unix操作系统中,进程创建后会在内存中开辟一块空间存放进程的相关信息,这个空间称之为PCB;
PID : 在操作系统中进程的唯一标识,是一个大于0的正整数,由系统自动分配
ps -aux 查看进程信息
虚拟内存:每个进程占用4G内存地址空间,这里的内存指虚拟空间;
进程状态:
三态: 就绪态、 运行态 、 等待态
就绪态: 进程具备运行条件,等待系统分派处理器以便运行;
运行态:进程占有cpu处于运行状态
等待态: 又称为阻塞态或睡眠态, 指进程不具备运行条件,正在等待某些条件的达成
五态: 就绪态、 运行态 、 等待态 、 新建态、 终止态
新建态:创建一个进程的过程,直接表现为执行某个程序或在程序中创建新的进程;
终止态:进程执行结束,完成回收的过程;
D 等待态(不可中断)
S 等待态(可中断)
T 等待态(暂停状态)
R 运行态
Z 僵尸态
+ 前台进行
N 低优先级的进程
< 高优先级的进程
l 有进程连接
s 会话组
进程的优先级:
优先级往往决定了一个进程的执行权限和占有系统资源的优先程度;
top : 动态查看系统进程运行的情况;
< > 进行翻页查找
linux 系统优先级范围 (-20 ~ 19),其中(-20)优先级最高;
用户创建进程默认优先级为0
nice : 以指定的优先级运行某个进程;
例: nice -9 ./xxx.py #以9为优先级运行程序
sudo nice - - 9 ./xxx #以-9为优先级运行程序
renice n PID : 修改一个正在运行的进程的优先级;
例: renice 8 6277 将6277号进程优先级修改为8
父子进程:在系统中除了初始化进程之外每个进程都是由父进程创建的,每个进程有一个唯一的父进程,可能有多个子进程;
pstree
总结:
1,什么是进程
2,进程和程序的区别
3,进程的几种状态及相互间的转换
4,什么是PCB PID CPU时间片
需求:两件不相关事情希望同时来做
方案1: 写两个进程,分别承担不同的事情,各自执行;
分析:1,两个程序比较麻烦; 2,无法确定两个程序应该在什么时间开始运行;
方案2: 写一个程序,在程序中指定位置调用接口来创建新的进程;
实现方法:
通过 os.fork() 函数实现
fork()
功能:创建一个新的进程
参数:无
返回值: < 0 #表示进程创建失败;
==0 #在子进程中fork的返回值为0;
> 0 #在父进程中fork的返回值大于0;
(fork是os模块函数,只能在linux和unix下使用)
测试1: 在父进程中fork之前的内容,子进程同样也会复制; 但是父子进程空间内容的修改不会互相影响;
测试2:父子进程在执行上互不影响,理论上不一定谁先执行;
测试3: 子进程虽然复制父进程的空间,但是也有自己的独特的特性,比如自己的PID,进程控制块,进程栈等。父进程中fork的返回值即为创建的子进程的PID号;
进程相关函数:
os.getpid()
功能: 获取当前进程的PID号;
os.getppid()
功能:获取当前进程父进程的PID号;
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #os 模块提供大量和系统相关的功能函数接口 2 #os模块的使用是系统相关的 在不同的系统中 3 #可能使用方法不同 4 import os 5 6 print('before create process') 7 a = 10 8 9 #创建新的进程 10 pid = os.fork() 11 12 if pid < 0: 13 print('create process failed') 14 elif pid == 0: 15 print('This is the new process') 16 print(a) 17 a = 1000 18 else: 19 print('This is the parent process') 20 21 print("The process end") 22 print(a) 23 24 ##############fork1# 25 import os 26 import time 27 28 #创建新的进程 29 pid = os.fork() 30 31 if pid < 0: 32 print('create process failed') 33 elif pid == 0: 34 print('pid:',pid) 35 while True: 36 time.sleep(0.8) 37 print('This is the new process') 38 #子进程的退出不会影响父进程 39 os._exit(0) 40 else: 41 #父进程中pid为子进程的PID号 42 print('parent pid:',pid) 43 while True: 44 time.sleep(1) 45 print('This is the parent process') 46 47 print("The process end") 48 ############fork2# 49 import time 50 51 def fun1(): 52 time.sleep(6) 53 print('做完第一件事情') 54 55 def fun2(): 56 time.sleep(4) 57 print('做完第二件事情') 58 59 # fun1() 60 # fun2() 61 ### 62 import os 63 import time 64 from test import * 65 66 #创建新的进程 67 pid = os.fork() 68 69 if pid < 0: 70 print('create process failed') 71 elif pid == 0: 72 fun1() 73 else: 74 fun2() 75 #############fork3## 76 77 import os 78 79 pid = os.fork() 80 81 if pid < 0: 82 print('create process failed') 83 elif pid == 0: 84 print("Child process:") 85 print("当前进程的PID:",os.getpid()) 86 print("当前进程父进程的PID:",os.getppid()) 87 else: 88 print("Parent process:") 89 print("pid:",pid) 90 print("当前进程的PID号:",os.getpid())
结束一个进程
os._exit(status)
功能:结束一个进程
参数:一个数字表示进程的退出状态,通常0表示正常退出进程其他数字表示非正常退出
sys.exit([status])
功能:结束一个进程,如果处理了抛出的异常则不结束进程
参数:一个数字表示进程的退出状态,通常0表示正常退出进程其他数字表示非正常退出;
还可以是一个字符串, 则在进程退出时会打印这个字符串;
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 ##### 2 #!/usr/bin/python3 3 4 import os 5 import sys 6 7 os._exit(0) #结束进程,不执行后面的语句; 8 9 print('process over') 10 ~ 11 ###### 12 #!/usr/bin/python3 13 14 import os 15 import sys 16 17 #os._exit(0) 18 sys.exit() #结束进程,不执行后面的语句; 19 20 21 print('process over') 22 ######## 23 24 #!/usr/bin/python3 25 26 import os 27 import sys 28 29 #os._exit(0) 30 #sys.exit() 31 try: 32 sys.exit('结束了。') #当它进行处理了异常,则执行下面的语句 33 except SystemExit as e: 34 print('++++'e) 35 36 37 print('process over') 38 39 ###结果: 40 $ ./exit.py 41 ++++ 结束了。 42 process over 43 44 45
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 import os 2 import time 3 4 #创建新的进程 5 pid = os.fork() 6 7 if pid < 0: 8 print('create process failed') 9 elif pid == 0: 10 print('pid:',pid) 11 while True: 12 time.sleep(0.8) 13 print('This is the new process') 14 #子进程的退出不会影响父进程 15 os._exit(0) 16 else: 17 #父进程中pid为子进程的PID号 18 print('parent pid:',pid) 19 while True: 20 time.sleep(1) 21 print('This is the parent process') 22 23 print("The process end")
僵尸进程:子进程先于父进程退出,父进程没有对子进程的退出做相应的处理,此时子进程就会变为僵尸进程;
影响:进程退出后,仍有部分信息残留在内存中占用空间,大量的僵尸进程会影响系统运行。所以应该尽量避免僵尸进程的产生;
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 cat zombie.py 2 #!/usr/bin/python3 3 4 import os 5 import time 6 7 pid = os.fork() 8 9 if pid < 0: 10 print('create new process failed.') 11 elif pid == 0: 12 print('子进程退出了') 13 os._exit(0) 14 else: 15 time.sleep(1) 16 print('Child PID:',pid) 17 while True: 18 pass 19 ## 20 python3 zombie.py 21 子进程退出了 22 Child PID: 3710 23 ## 24 tarena 3710 0.0 0.0 0 0 pts/2 Z+ 21:18 0:00 [python3] <defunct> 25 tarena 3711 0.0 0.3 39104 3224 pts/6 R+ 21:18 0:00 ps -aux
孤儿进程:父进程先于子进程退出,此时子进程就会变成孤儿进程;
影响:当一个进程变为孤儿进程,系统就会自动的使用一个进程称为孤儿进程的父进程。当孤儿进程退出时,该系统进程会自动回收孤儿,使他不会称为僵尸;所以孤儿进程对系统资源没有什么影响;
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #!/usr/bin/python3 2 3 import os 4 import time 5 6 pid = os.fork() 7 8 if pid < 0: 9 print('create new process failed.') 10 elif pid == 0: 11 print('父进程的PID:',os.getppid()) 12 time.sleep(3) 13 print('父进程的PID',os.getppid()) 14 print('子进程退出了') 15 os._exit(0) 16 else: 17 #time.sleep(1) 18 print('Child PID:',pid) 19 #while True: 20 # pass 21 ### 22 Child PID: 3778 23 父进程的PID: 3777 24 #:~/process$ 父进程的PID 2073 25 子进程退出了
处理僵尸进程的方法:
1,让父进程先退出;(缺点:不好控制)
2,父进程处理子进程的退出;(阻塞父进程的运行)
os.wait()
功能:等待子进程退出进行处理;
参数:无
返回值:返回一个包含两个元素的元组,第一个是退出的子进程的PID号,第二个是子进程的退出状态;
(wait是一个阻塞函数,即 进程处于等待态,等待某种条件的达成才会继续运行;)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 import os 2 import sys 3 from time import sleep 4 5 pid = os.fork() 6 7 if pid < 0: 8 print('create process failed.') 9 elif pid == 0: 10 print('Child process...') 11 sleep(2) 12 sys.exit(6) #子进程退出(6x256=1536) 13 else: 14 p,status = os.wait()##wait阻塞等待子进程的退出 15 print('pid:',p,'status:',status) 16 print('Parent process...') 17 #### 18 Child process... 19 pid: 3838 status: 1536 20 Parent process...
os.waitpid(pid,option)
功能:处理子进程的退出使其不会变成僵尸进程;
参数:pid -1 等待任意子进程退出;
pid > 0 表示等待指定进程号的子进程退出;
option 0 表示阻塞等待
option WNOHANG 表示非阻塞状态;
返回值 : 同wait
wait() ====> waitpid(-1,0)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 import os 2 import sys 3 from time import sleep 4 5 pid = os.fork() 6 7 if pid < 0: 8 print('create process failed.') 9 elif pid == 0: 10 print('Child process...') 11 sleep(2) 12 sys.exit(6) #子进程退出 13 else: 14 #waitpid非阻塞等待子进程的退出 15 p,status = os.waitpid(-1,os.WNOHANG) 16 print('p:',p,'status:',status) 17 print(os.WEXITSTATUS(status)) 18 print('Parent process...') 19 ### 20 $ python3 waitpid.py 21 p: 0 status: 0 22 0 23 Parent process... 24 Child process...
使用open拷贝一个文件,要求将文件拷贝为两份
第一份为前半部分,第二份为后半部分
分别用父子进程拷贝
总结:
1.函数的使用 fork getpid getppid _exit exit wait
waitpid
2. 理解什么是僵尸进程什么是孤儿进程即两者产生的过程
3. 知道僵尸进程的危害和两种处理方法
4. 理解进程的创建流程