初学python之路-day34

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的父进程

3.并发与并行,阻塞与非阻塞

并发:多个任务看起来同时在处理 ,本质上是切换执行 速度非常快

并行: 多个任务真正的同时执行 必须具备多核CPU 才可能并行

阻塞:阻塞状态是因为程序遇到了IO操作,或是sleep,导致后续的代码不能被CPU执行

本地IO input print sleep read write

网络IO recv send

非阻塞:非阻塞与之相反,表示程序正在正常被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在开启子进程时会重新加载所有的代码造成递归创建进程

2.第二种方式中,必须将要执行的代码放到run方法中,子进程只会执行run方法其他的一概不管

7.进程间内存相互隔离

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.孤儿进程:指的是,父进程先结束 ,而子进程还在运行着

 孤儿进程无害,有 其存在的必要性

 例如:qq开启了浏览器,qq先退出了 浏览器应该继续运行

 孤儿进程会被操作系统接管

 2.僵尸进程:僵尸进程指的是,当子进程比父进程先结束,而父进程又没有回收子进程,释放子进程占用的资源,此时子进程将成为一个僵尸进程。

  子进程已经结束了,但是操作系统会保存一些进程信息,如PID,运行时间等,僵尸进程如果太多将会占用大量的资源,造成系统无法开启新新进程

 linux 中有一个wai/waitpid 用于父进程回收子进程资源,python会自动回收僵尸进程

 

猜你喜欢

转载自www.cnblogs.com/wangwei5979/p/10957515.html
今日推荐