根据pid 退出进程_并发网络编程学习笔记(2)进程

本文详细介绍了多任务的概念,包括并发与并行的区别,以及CPU在多任务执行中的角色。重点讲解了进程的概念,包括进程的状态、生命周期、父子进程关系以及进程树结构。在多进程编程方面,提到了Python的multiprocessing模块,如何创建和管理进程,并强调了进程间通信的重要性,介绍了消息队列作为通信手段的原理和使用方法。最后,文章给出了一个群聊聊天室的示例,展示了进程通信在实际应用中的场景。
摘要由CSDN通过智能技术生成

eae0c238b72c52e8ac5db99ef977c970.png

1. 多任务概述

  1. 多任务 即操作系统中可以同时运行多个任务。

  2. 计算机原理

  1. 并发:多个任务如果被分配给了一个CPU内核,多任务之间是并发关系,多个任务之间并不是真正的“同时”

  2. 并行:多个任务如果被分配给了不同的CPU内核,多任务之间执行就是并行关系

  3. CPU:计算机硬件的核心部件,用于对任务进行执行运算。

  4. 操作系统用CPU执行任务

    • CPU轮询机制:CPU都在多个任务之间快速的切换执行,切换速度在微少级别

    • 多核CPU

3. 多任务编程

    • 提高任务之间的配合,根据运行情况进行任务创建

    • 充分利用计算机资源,提高任务执行效率

    • 在任务中有阻塞时并行并发都能提高效率

    • 在任务中无阻塞时只有并行状态才能提高效率

      • 多进程编程

      • 多线程编程

    • 即一个程序中编写多个任务,在程序运行时让这多个任务一起运行。

      • 实现多任务编程的方法

      • 多任务意义

2. 进程(Process)

1. 进程概述

  • 定义:程序在计算中的一次执行过程

    • 程序是一个可执行的文件,是静态的占有磁盘。

    • 进程是一个动态的过程描述,占有计算机运算资源 ,有一定的生命周期

    • 查看进程信息

      ps -aux

USER: 进程的创建者PID: 操作系统分配给进程的编号,大于0的整数,系统中每个进程的PID都不重复。PID也是重要的区分进程的标志。%CPU,%MEM: 占有的CPU和内存STAT: 进程状态信息,S I 表示阻塞状态  ,R 表示就绪状态或者运行状态START: 进程启动时间COMMAND: 通过什么程序启动的进程
  • 进程树结构

    pstree

    • 父子进程:在Linux操作系统中,进程形成树形关系,任务上一级进程是下一级的父进程,下一级进程是上一级的子进程。

  • 三态

    • 就绪态:进程具备执行条件,等待系统调度分配CPU资源

    • 运行态:进程占有CPU正在运行

    • 等待态:进程阻塞等待,此时会让出CPU

  • 五态(增加新建和终止)

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

    • 终止:进程结束,释放资源的过程    

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值返回值:返回当前进程的PID
      os.getppid()功能:获取父进程的PID号返回值:返回父进程PID
      sys.exit(info)功能:退出进程参数:字符串 表示退出时打印内容

6. 孤儿进程和僵尸进程

    • 孤儿进程:父进程先于子进程退出时,子进程会成为孤儿进程,孤儿进程会被系统自动收养,成为孤儿进程新的父进程,并在孤儿进程退出时释放其资源

    • 僵尸进程:子进程先于父进程退出,父进程又没有处理子进程的退出状态,此时子进程就会成为僵尸进程

    • 特点:僵尸进程虽然结束,但会存留部分进程资源在内存中,大量的僵尸进程会浪费系统资源。

    • Python模块中建立自动僵尸处理机制,每次创建新进程都进行检查,将之前的僵尸处理掉,而父进程退出前,僵尸也会被自动处理。

4. 创建进程类

进程的基本创建方法将子进程执行的内容封装为函数。

  • 创建步骤

    【1】继承Process类

    【2】重写init方法添加自己的属性,使用super()加载父类属性

    【3】重写run()方法

  • 使用方法

    【1】实例化对象

    【2】调用start自动执行run方法

5. 进程间通信

  • 必要性:进程间空间独立 ,资源不共享,此时在需要进程间数据传输时就需要特定的手段进行数据通信。

  • 常用进程间通信方法:消息队列,套接字等。

  • 消息队列使用

    • 通信原理:在内存中开辟空间,建立队列模型,进程通过队列将消息存入,或者从队列取出完成进程间通信。

  • 实现方法

    from multiprocessing import Queue  q = Queue(maxsize=0)功能:创建队列对象参数:最多存放消息个数返回值:队列对象q.put(data)功能:向队列存入消息参数:data 要存入的内容q.get()功能:从队列取出消息返回值:返回获取到的内容q.full() 判断队列是否为满q.empty() 判断队列是否为空q.qszie()  获取队列中消息个数q.close()  关闭队列

    ## 示例练习代码

  • 需求:

    群聊聊天室程序

    • 需求分析

      •     ‍有人进入聊天室需要输入姓名,姓名不能重复

      •     有人进入聊天室时,其他人会收到通知:Lucy 进入了聊天室

      •     一个人发消息,其他人会收到:   Lucy :一起出去玩啊。

      •     有人退出聊天室,则其他人也会收到通知 :  Lucy 退出了聊天室

"""  服务端"""from socket import *from multiprocessing import Process# 服务器地址HOST = "0.0.0.0"PORT = 3333ADDR = (HOST, PORT)user = {}def login(sock, name, address):    if name in user or "管理" in name:        sock.sendto(b"fail", address)    else:        sock.sendto(b"ok", address)        msg = "欢迎 %s 进入聊天室" % name        for key, value in user.items():            sock.sendto(msg.encode(), value)        user[name] = address        print(user)def chat(sock, name, content):    msg = "%s : %s " % (name, content)    for key, value in user.items():        if key != name:            sock.sendto(msg.encode(), value)def exit(sock, name):    del user[name]    msg = "%s 退出聊天室。" % name    for key, value in user.items():        sock.sendto(msg.encode(), value)def handle(sock):    while True:        request, addr = sock.recvfrom(1024)        tmp = request.decode().split(" ", 2)        if tmp[0] == "LOGIN":            login(sock, tmp[1], addr)        elif tmp[0] == "CHAT":            chat(sock, tmp[1], tmp[2])        elif tmp[0] == "EXIT":            exit(sock, tmp[1])def main():    sock = socket(AF_INET, SOCK_DGRAM)    sock.bind(ADDR)    p = Process(target=handle, args=(sock,), daemon=True)    p.start()    while True:        content = input("管理员消息:")        if content == "exit":            break        # msg = "CHAT 管理员消息 " + content        msg = "CHAT 管理员消息: %s" % content        sock.sendto(msg.encode(), ADDR)if __name__ == '__main__':    main()
"""    群聊聊天室客户端"""import sysfrom socket import *from multiprocessing import ProcessSERVER_ADDR = ("127.0.0.1", 3333)def login(sock):    while True:        name = input("请输入您的昵称:")        msg = "LOGIN " + name        sock.sendto(msg.encode(), SERVER_ADDR)        result, addr = sock.recvfrom(1024)        if result == b"ok":            print("欢迎进入聊天室\n")            return name        else:            print("该用户已存在\n")def recv_msg(sock):    while True:        data, addr = sock.recvfrom(1024 * 10)        content = "\n" + data.decode() + "\n请发言:"        print(content, end="")def send_msg(sock, name):    while True:        try:            content = input("请发言:")        except KeyboardInterrupt:            content = "exit"        if content == "exit":            msg = "EXIT " + name            sock.sendto(msg.encode(), SERVER_ADDR)            sys.exit("您已退出聊天室")        msg = "CHAT %s %s" % (name, content)        sock.sendto(msg.encode(), SERVER_ADDR)def main():    sock = socket(AF_INET, SOCK_DGRAM)    name = login(sock)    p = Process(target=recv_msg, args=(sock,), daemon=True)    p.start()    send_msg(sock, name)if __name__ == '__main__':    main()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值