并发网络编程学习笔记(2)-进程 - 海筒研习社.SeaSilo.CN

/ 0评 / 0

1. 多任务概述

  1. 多任务 即操作系统中可以同时运行多个任务。
  2. 计算机原理
    • CPU:计算机硬件的核心部件,用于对任务进行执行运算。
    • 操作系统用CPU执行任务
    • CPU轮询机制:CPU都在多个任务之间快速的切换执行,切换速度在微少级别
    • 多核CPU
      • 并发:多个任务如果被分配给了一个CPU内核,多任务之间是并发关系,多个任务之间并不是真正的“同时”
      • 并行:多个任务如果被分配给了不同的CPU内核,多任务之间执行就是并行关系

2. 进程(Process)

  1. 进程概述
    • 定义:程序在计算中的一次执行过程
      • 程序是一个可执行的文件,是静态的占有磁盘。
      • 进程是一个动态的过程描述,占有计算机运算资源 ,有一定的生命周期
    • 进程状态
      • 三态
        • 就绪态:进程具备执行条件,等待系统调度分配CPU资源
        • 运行态:进程占有CPU正在运行
        • 等待态:进程阻塞等待,此时会让出CPU
      • 五态(增加新建和终止)
        • 新建:创建一个进程,获取资源的过程
        • 终止:进程结束,释放资源的过程
    • 进程命令
      • 查看进程信息ps -aux
        • USER : 进程的创建者
        • PID : 操作系统分配给进程的编号,大于0的整数,系统中每个进程的PID都不重复。PID也是重要的区分进程的标志。
        • %CPU,%MEM : 占有的CPU和内存
        • STAT : 进程状态信息,S I 表示阻塞状态 ,R 表示就绪状态或者运行状态
        • START : 进程启动时间
        • COMMAND : 通过什么程序启动的进程
      • 进程树结构pstree
        • 父子进程:在Linux操作系统中,进程形成树形关系,任务上一级进程是下一级的父进程,下一级进程是上一级的子进程。
  2. 多进程编程
    • 使用模块:multiprocessing
    • 创建流程
      • 【1】 将需要新进程执行的事件封装为函数
      • 【2】 通过模块的Process类创建进程对象,关联函数
      • 【3】 通过进程对象调用start启动进程
  3. 新版windows MACOS进程创建(防止无穷尽的创建进程)
if __name__ = "__main__":
    process = mp.Process(target = fun)
    process.start()
    process.join()

3. 多进程编程

  1. 使用模块:multiprocessing
  2. 创建流程【1】将需新进程执行的事件封装为函数【2】通过模块的Process类创建进程对象,关联函数【3】通过进程对象调用start启动进程
  3. 主要类和函数使用Process()
    功能:创建进程对象
    参数:target绑定要执行的目标函数
    args 元组,用于给target函数位置传参
    kwargs 字典,给target函数键值传参
    daemon bool值,让子进程随父进程退出p.start()
    功能:启动进程注意:启动进程此时target绑定函数开始执行,该函数作为新进程执行内容,此时进程真正被创建p.join([timeout])
    功能:阻塞等待子进程退出
    参数:最长等待时间
  4. 进程执行现象理解
    • 新的进程是原有子进程,子进程复制父进程全部内存空间代码段,一个进程可以创建多个子进程。
    • 子进程只执行指定函数,其余内容均是父进程执行内容,但是子进程也拥有其他父进程资源。
    • 各个进程在执行上互不影响,也没有先后顺序关系。
    • 进程创建后,各个进程空间独立,相互没有影响
    • multiprocessing创建的子进程中无法使用标准输入(无法使用input)
  5. 进程处理细节
    • 进程相关函数os.getpid()
      功能:获取一个进程的PID值
      返回值:返回当前进程的PIDos.getppid()
      功能:获取父进程的PID号
      返回值:返回父进程PIDsys.exit(info)
      功能:退出进程
      参数:字符串 表示退出时打印内容
  6. 孤儿进程和僵尸进程
    • 孤儿进程:父进程先于子进程退出时,子进程会成为孤儿进程,孤儿进程会被系统自动收养,成为孤儿进程新的父进程,并在孤儿进程退出时释放其资源
    • 僵尸进程:子进程先于父进程退出,父进程又没有处理子进程的退出状态,此时子进程就会成为僵尸进程
    • 特点:僵尸进程虽然结束,但会存留部分进程资源在内存中,大量的僵尸进程会浪费系统资源。
    • Python模块中建立自动僵尸处理机制,每次创建新进程都进行检查,将之前的僵尸处理掉,而父进程退出前,僵尸也会被自动处理。

示例代码:

"""
    编写一个程序,将一个大文件拆分为2个小文件
    上半部分拆为一个,下半部分一个,按照字节大小划分

    要求: 拆分过程需要同时执行,分别用两个子进程完成
          查分完成后,打印提示 "拆分完毕"

    提示: os.path.getsize()
          file.seek()

    难点: 不允许一次读取一半
"""
import multiprocessing
import os

file_source = "./20210111.jpg"
fsize = os.path.getsize(file_source)

# 如果父进程打开文件,子进程直接使用fr,那么
# 父子进程用的是同一个文件偏移量会相互影响
# fr = open(filename,'rb')

# 拆出上半部分
def split_top():
    fr = open(file_source, "rb")
    fw = open("split_top.jpg", "wb")
    fsize01 = fsize // 2  # 要复制n个字节
    while fsize01>1024:
        fw.write(fr.read(1024))
        fsize01 -= 1024
    else:
        fw.write(fr.read(fsize01))
    fr.close()
    fw.close()

# 拆出下半部分
def split_bot():
    fr = open(file_source, "rb")
    fw = open("split_bot.jpg", "wb")
    fr.seek(fsize // 2, 0)# 文件偏移量到中间
    while True:
        data = fr.read(1024)
        if not data:
            break
        fw.write(data)
    fr.close()
    fw.close()

# 启动函数 创建进程
def main():
    jobs = []
    for th in [split_top, split_bot]:
        p = multiprocessing.Process(target=th)
        jobs.append(p)
        p.start()
    [i.join() for i in jobs] # 等待拆分结束
    print("拆分完毕!")


if __name__ == '__main__':
    main()

发表评论

邮箱地址不会被公开。 必填项已用*标注