进程(thread)

多任务编程

意义:充分利用计算机的资源提高程序的运行效率

定义:通过应用程序利用计算机多个核心,达到同时执行多个任务的目的

实施方案: 多进程  多线程

并行:多个计算机核心在同时处理多个任务,多个任务之间是并行关系。

并发:计算机同时处理多个任务,内核在多个任务间不断切换,达到好像在同时处理的运行效果。同时多个任务实际为并发关系。

进程:程序在计算机中运行一次的过程

程序:是一个可执行文件,是静态的,占有磁盘,不占有计算机运行资源。

进程:进程是一个动态的过程描述,占有cpu内存等计算机资源的,有一定的生命周期。

* 同一个程序的不同执行过程是不同的进程,因为分配的计算机资源等不同。

 

进程的创建流程:

1、用户空间运行一个程序,发起进程创建

2、操作系统接受用户请求,开启进程创建。

3、操作系统分配系统资源,确认进程状态。

4、将创建好的进程提供给应用层使用。

 

cpu时间片:

如果一个进程占有计算机核心,我们称为该进程在cpu时间片上。多个任务实际对cpu会进行争夺,一般由操作系统分配cpu时间片。

 

PCB(进程控制块)

在操作系统中,进程创建后会自动产生一个空间存放进程信息,称为进程控制块。

进程信息: 进程PID  进程占有的内存位置,创建时间,用户

进程PID:进程在操作系统中的唯一编号,大于0的整数,由系统自动分配。

进程信息查看命令:linux   ps  -aux   windows:netstat -ano

进程特征:

1、进程是操作系统分配计算机资源的最小单位

2、每个进程都有子集单独的虚拟内存空间

3、进程间的执行相互独立,互不影响。

 

进程的状态:

三态:

*就绪态:进程具备执行条件,等待系统分配cpu

*运行态:进程占有cpu处理器,处于运行状态

*等待态:进程暂时不具备运行条件,需要阻塞等待

五态:(增加了新建态和终止态)

*新建态: 创建一个新的进程,获取资源的过程

*终止态:进程结束释放资源的过程。

linux中:ps -aux  ---》stat查看进程状态

D  等待态       不可中断等待

S  等待态       可中断等待

T  等待态       暂停状态

R  运行态      就绪态  运行态

Z  僵尸态       进程已经结束,但是存在遗留问题。


+     前台进程

<     高优先级

N     低优先级

l      有进程链接

s     会话组组长

 

进程优先级

优先级决定了一个进程的执行权限和占有资源的优先程度。

查看进程优先级:

      top:动态的查看进程优先级

      取值范围:  -20   ——  19      -20 优先级最高。

      nice :指定优先级运行程序。

          eg:终端   nice  -9   程序.py

 

父子进程:

在系统中除了初始化进程之外,每个进程都有一个父进程,可能有0个或者多个子进程。由此形成父子进程关系,我们认为每个进程都是父进程发起请求创建的。LINUX

进程(process)

查看进程树: pstree(linux)

查看父进程PID: ps  -ajx

import os
from time import sleep

#fork之前的部分只有父进程执行
print("hello world!")

#创建一个新的进程,无参数,
#返回值:失败返回 -1,成功  在原有进程中返回新的进程PID
#      在新的进程中返回0
pid = os.fork()

if pid < 0:
    print("进程创建失败。")
elif pid == 0:
    print("新创建的进程。")
else:
    sleep(1)  #让父进程进入等待态,这样就可以让子进程先进行。
    print("原来的进程。")

print("程序执行完毕。")

运行结果:
创建失败: 进程创建失败
          程序执行完毕
创建成功:(执行的顺序不一定,谁先抢到谁先开始)
        原来的进程
        程序执行完成
         新创建的进程
         程序执行完毕

 

*子进程会复制父进程全部代码段,包括fork前的代码

*子进程从fork的下一句开始执行

*父子进程通常会根据fork返回值的差异选择执行不同的代码(使用if结构)

*父子进程在执行上互不干扰,执行顺序不确定。

*子进程虽然复制父进程内存空间,但是有子集的特性,比如PID号,PCB等。

*父子进程空间独立,各自修改各自的内容,互不影响。

 

进程相关函数使用:

 

os.getpid()

功能:获得当前进程的pid号

返回值: 返回PID号

 

os.getppid()

功能:获取父进程的进程号

返回值:返回PID号

import os

pid = os.fork()

#仔细看不同位置的ID是不同的参数。
if pid < 0:
    print("Create Process failed")
elif pid == 0:
    print("子进程PID",os.getpid())
    print("父进程PID",os.getppid())
else:
    print("父进程PID",os.getpid())
    print("子进程PID",pid())

os._exit(status)

功能:推出进程

参数:进程的推出状态  整数

import os

#进程结束
os._exit(0)

print("hello")

什么也不会打印,因为直接退出了。

sys.exit([status])

功能:退出进程

参数:默认为0   如果是整数则表示退出状态,如果是字符串字退出时打印字符串。

sys.exit   可以通过捕获异常SystemExit 阻止退出

 

孤儿进程: 父进程先于子进程退出,此时子进程就会成为孤儿进程。

*孤儿进程会被系统指定的进程收养,即系统进程会成为该孤儿进程新的父进程。

*孤儿进程退出时该父进程会处理退出状态。

import os 
from time import sleep 

pid = fork()

if pid < 0:
    print("create process failed")
elif pid == 0:
    print("父进程pid:",os.getppid())
    sleep(2)
    print("父进程pid:",os.getppid())
else:
    sleep(1)
    print("parent PID:",os.getpid())
    sys.exit("父进程退出")

运行结果:
父进程pid: 10965
Parent PID:10965
父进程退出
父进程PID:1778    #重新找父进程
    


僵尸进程:  子进程先于父进程退出,父进程没有处理子进程退出状态,此时子进程称为僵尸进程。

*僵尸进程已经结束,但是会滞留部分PCB信息在内存,大量的僵尸会消耗系统资源,应该尽量避免。

#僵尸进程演示
import os,sys
from time import sleep

pid = os.fork()

if pid < 0:
    print("create process failed")
elif pid == 0:
    print("子进程PID:",os.getpid())
    sys.exit("子进程退出")
else:
    sleep(1)
    while True:
        pass

如何避免僵尸进程产生

* 让父进程先退出

创建二级子进程:

        1、父进程创建子进程等待子进程退出

        2、子进程创建二级子进程,然后马上退出

        3、二级子进程成为孤儿,处理具体事件

#创建二级子进程防止僵尸。
import os
from time import sleep

def fun1():
    sleep(3)
    print("第一件事情")

def fun2():
    sleep(4)
    print("第二件事情")
    
pid = os.fork()

if pid < 0:
    print("Create process error")
elif pid == 0:
    #创建二级进程
    pid0 = os.fork()
    if pid0 < 0:
        print("创建二级进程失败")
    elif pid0 == 0:
        fun2() #一级子进程创建的二级子进程,一级退出后,会成为孤儿。
    else:
        os._exit(0) #一级子进程退出,会有父进程等待处理。
else:
    os.wait() #父进程等待处理。
    fun1()

运行结果:
第一家事情
第二件事情
第一件事情
第二件事情

 

*父进程处理子进程退出状态

pid,status = os.wait()

功能:在父进程中阻塞等待处理子进程的退出

返回值: pid   退出的子进程的PID号

               status  子进程的退出状态

pid,status = os.waitpid(pid,option)

功能:同wait

参数:pid     -1  表示任意子进程退出

                      >0  整数   指定PID号的子进程退出

           option     0  表示阻塞等待

                       WNOHONG 表示非阻塞

返回值:同wait

waitpid(-1,0)等价于  wait()

#如何防止僵尸进程产生。
import os,sys
from time import sleep

pid = os.fork()

if pid < 0:
    print("create process failed")
elif pid == 0:
    sleep(3)
    print("子进程PID:",os.getpid())
    sys.exit("子进程退出")
else:
    #等待子进程退出
    while True:
        sleep(1)
        pid,status = os.waitpid(-1,os.WNOHONG)
        print(pid,status)#status会乘以256
        if os.WEXITSTATUS(status):#获取未乘以256的退出状态
            break
        print("do something others")

multiprocessing 模块创建进程

1、需要将要做的事情封装为函数。

2、使用lultiprocessing中提供的process类创建进程对象

3、通过进程兑现格合Process初始化函数 对进程进行设置,并且绑定要执行的事件。

4、启动进程,会自动执行先关联函数。

5、事件完成后回收进程

 

创建进程对象

Process()

功能:创建进程对象

参数: name: 给创建的进程起一个名字  默认Process-1 Process-2 等等

            target:绑定的函数

            args: 元组 给target函数按照位置传参

            kwargs: 字典  给target函数按照键值传参

p.strat()

功能:启动进程,此时进程被创建。自动运行进程函数。

p.join([timeout])

功能:阻塞等待挥手响应的进程。

参数:超时时间(不传参数的话一直等待)

*multiprocessing 创建进程是原来进程的子进程,创建后父子进程各自执行互不影响。

*子进程同样是复制父进程的空间,子进程对内容的修改不会影响父进程空间。

*join回收子进程,会有效的组织僵尸进程的产生。

*通常使用multiprocessing创建进程,父进程只要作进程的创建和回收,不做其它工作。

import multiprocessing as mp
from time import sleep

#进程事件
def fun():
    sleep(3)
    print("子进程事件")

#创建进程对象
p = mp.Process(target = fun)

#启动进程
p.start()

sleep(2)
print("这是父进程")

#回收进程
p.join()

print("=========")
#利用multiprocessing创建多个子进程
from multiprocessing import Process
from time import sleep
import os

def th1():
    sleep(3)
    print("吃饭")
    print(os.getppid(),"-----",os.getpid())

def th2():
    sleep(2)
    print("睡觉")
    print(os.getppid(),"-----",os.getpid())

def th3():
    sleep(4)
    print("打豆豆")
    print(os.getppid(),"-----",os.getpid())


things = [th1,th2,th3]
process = []

for th in things:
    p = Process(target = th) #每次创建新的进程,P会被覆盖掉。
    process.append(p) #保存进程对象
    p.start()

for p in process:
    p.join()
    
运行结果:
睡觉
7414 ----- 7416
吃饭
7414 ----- 7415
打豆豆
7414 ----- 7417




 

multiprocessing对象的属性:

p.is_alive() 判断进程声明周期状态。返回值True False

p.name 进程名称  默认为Process-1 如果起名字则为自定义名称

p.pid 创建的进程的PID

p.daemon 

必须在start前设置,如果设置daemon为True就不再使用join

默认值为False 父进程退出不会影响子进程运行。

如果设置为True 则父进程退出子进程也会退出。

from multiprocessing import Process
from time import sleep

def worker(sec,name):
    for i in range(3):
        sleep(sec)
        print("I'm %s"%name)
        print("I'm working!")

#通过args给函数传参。
#通过kwargs给函数传参。两个方式可以同时使用。
p = Process(target = worker,args = (2,'Levi'))
p.start()

#判断进程状态
print(p.is_alive())

p.join()

 

创建自己的进程类:
1、继承Process类

2、重写 __init__ 并且调用父类的__inint__

3、重写run方法,此时生成对象后,调用start就会自动运行run

from multiprocessing import process
import time

class ClockProcess(Process):
    def __init__(self,value):
        #调用父类的__init__,保证父类的属性也在。
        super().__init__()
        self.value = value
    
    #重写run方法
    def run(self):
        for i in range(5):
            print("The time is {}".\
                  format(time.ctime()))

#用自己的类创建进程对象
p = ClockProcess(2)
#调用父类的start,自动执行run
#自动执行run
p.start()


 

 

多进程

优点:能并行执行多个任务,提高效率

           创建方便,运行独立, 不受其他进程影响。

缺点:进程的创建和删除都需要消耗计算机的资源。

进程池技术:
原因:如果有大量的任务需要多进程完成,且可能现需要频繁的创建和删除进程,给计算机带来大量的资源消耗。

原理:在进程池内运行一定数量进程,通过这些进程完成进程队列中的事件,直到事件执行完毕,减少进程不必要的创建删除过程。

1、实时操作方法:
1、创建进程池,在进程池中放入适当进程。

2、将事件加入到进程池队列。

3、事件不断运行,直到所有的事件运行完毕。

4、关闭进程池,回收进程。

#创建进程池对象
#参数:表示进程池中有多少进程
pool = Pool(processes)

#功能:将事件放入进程池队列。事件放入后,自动启动。
#参数:func  要执行的事件
#     args  给func用元组传参
#     kwds  给func用字典传参
#返回值:返回事件对象 通过get()方法获取事件函数返回值
pool.appy_async(func,args,kwds)

#功能:关闭进程池,不能在添加新的事件。
pool.close()

#功能:阻塞等待回收进程池,没有参数。
pool.join()

#功能:将要完成的事件放入进程池
#参数:func  要完成的事件函数
#      iter 可得迭代对象给func传参
#返回值:事件函数的返回值列表
pool.map(func,iter)

 

from multiprocessing import Pool
from time import sleep,ctime

#事件函数
def worker(msg):
    sleep(2)
    print(msg)
    
#创建进程池,放4个进程
pool = Pool(processes = 4)

result = []
#将事件放入进程池
for i in range(10):
    msg = "hello %d"%i
    r = pool.apply_async(func = worker,args = (msg,))
    result.append(r)#保存进程事件的返回值。

#关闭进程池
pool.close()

#回收进程池
pool.join()   
    
    
#返回事件函数的返回值
for i in result:
    print(i.get())
    
    
    
    
    
    
    
    
    
    
#使用map方法    
from multiprocessing import Pool
from time import sleep

def fun(num):
    sleep(2)
    print(num)
    return num**2

if __name__ == "__main__":
    #创建进程池
    pl = Pool(4)
    #使用map将事件放入进程池。
    r = pl.map(fun,range(10))
    print(r)
    pl.close()
    pl.join()    
    
    
    
    
    
    
    
    
    

os.path.getsize(path)

功能:获取一个文件的大小

参数:文件

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值