python 进程线程 day04

2018.8.9

day04

目录

本地套接字

网络基础总结:

多任务编程


epoll

  1. 使用方法 : 代码基本与poll相同
    1. 将生成对象的 poll() 函数 变为p = epoll()
    2. 将register注册IO事件时 关注的事件类别改为epoll类别
  2. 区别:
    1. epoll 效率要高于select 和 poll
    2. epoll 的关注触发机制更多 -->EPOLLET(边缘触发)
      
      from socket import * 
      from select import *
      
      s = socket()
      s.setsockopt(SOL_SOCKET,SO_REUSEADDR,1)
      s.bind(('0.0.0.0',8888))
      s.listen(5)
      
      #创建epoll对象
      p = epoll()
      
      #创建地图
      fdmap = {s.fileno():s}
      
      #添加关注
      p.register(s,EPOLLIN | EPOLLERR)
      
      while True:
          #进行IO监控
          #[(fileno,evnet),...]
          events = p.poll()
          for fd,event in events:
              if fd == s.fileno():
                  #从地图中找到fd对应的对象
                  c,addr = fdmap[fd].accept()
                  print("Connect from",addr)
                  #注册新的IO 维护地图
                  p.register(c,EPOLLIN)
                  fdmap[c.fileno()] = c 
              else:
                  data = fdmap[fd].recv(1024)
                  if not data:
                      p.unregister(fd) #从关注移除
                      fdmap[fd].close()
                      del fdmap[fd]  #从地图删除
                  else:
                      print(data.decode())
                      fdmap[fd].send('收到了'.encode())
      
      #和poll相比就是把poll改成epoll,把POLLIN,POLLERR改成EPOLLIN,EPOLLERR

本地套接字

cookie.

  1. linux下文件类型: 
    b(块设备文件) c(字符设备文件) d(目录) 
    -(普通文件) l(链接文件) s(套接字文件) p(管道文件)
  2. 作用:用于本地不同程序间进行数据传输
  3. 本地套接字传输流程
    1. 创建套接字对象
      sockfd = socket(AF_UNIX,SOCK_STREAM)
    2. 绑定套接字文件,如果文件不存在则自动创建
      sockfd.bind(file)  绑定一个文件
    3. 监听
    4. 消息收发  recv  send

cookie

  • os.path.exists(file) 
  • 功能: 判断一个文件是否存在 
  • 参数: 文件位置 
  • 返回值: 存在返回True 否则返回False
  • os.unlink()
  • os.remove() 
  • 功能:删除一个文件 
  • 参数:要删除的文件

    示例:
     
    In [1]: import os
    
    In [2]: os.path.exists('./day02.txt')
    Out[2]: True
    
    In [3]: os.remove('./day02.txt')
    
    In [4]: os.path.exists('./day02.txt')
    Out[4]: False
    本地套接字示例:
     
    #unix_recv.py
    from socket import * 
    import os 
    
    #确定使用哪个套接字文件
    sock_file = "./sock"
    
    #判断文件是否已经存在,存在删除
    if os.path.exists(sock_file):
        os.unlink(sock_file)
    
    #创建本地套接字
    sockfd = socket(AF_UNIX,SOCK_STREAM)
    
    #绑定套接字文件
    sockfd.bind(sock_file)
    
    #监听
    sockfd.listen(3)
    
    #消息收发 
    while True:
        c,addr = sockfd.accept()
        while True:
            data = c.recv(1024)
            if data:
                print(data.decode())
            else:
                break
        c.close()
        
    sockfd.close()
    #unix_send.py
    from socket import * 
    
    sock_file = "./sock"
    
    # 创建套接字
    sockfd = socket(AF_UNIX,SOCK_STREAM)
    #连接另外一端
    sockfd.connect(sock_file)
    
    #发送消息
    while True:
        msg = input(">>")
        if msg:
            sockfd.send(msg.encode())
        else:
            break
    sockfd.close()


     

网络基础总结:

理论:

  1. OSI七层模型 tcp/ip模型
  2. tcp和udp的区别和特征
  3. 三次握手和四次握手的过程和每一次作用
  4. 什么是IO多路复用,IO的基本形态
  5. 套接字的种类,套接字类型的区别

程序实践:

  1. TCP套接字传输的基本模型
  2. UDP套接字传输基本模型
  3. IO多路复用select poll的使用
  4. HTTP协议基本原理的实现

多任务编程

多任务编程

  1. 意义:充分利用计算机资源,同时运行多个任务,提高程序整体的运行效率
  2. 定义:通过程序利用计算机的多个核心达到同时执行多个任务的目的,以此达到提升程序运行效率的目的
  3. 实施方案:多进程编程   多线程编程
  4. 并行:多个计算机核心在同时处理多个任务,这时多个任务之间并行关系
  5. 并发:同时运行多个任务,内核在多个任务间不断切换,达到多个任务都会被执行的处理效果,此时多个任务间是并发关系
  6. 进程:程序在计算机中的一次执行过程
  7. 程序:是一个可执行文件,是静态的,占有磁盘,不占计算机的运行资源
  8. 进程:进程是一个动态的过程,占有计算机资源,有一定的生命周期
    同一个程序不同的运行过程是不同的进程,因为分配的资源和生命周期都不相同

进程的创建流程

  1. 用户启动一个程序或者调用接口发起进程创建
  2. 操作系统接收用户请求分配计算机资源创建资源
  3. 操作系统将一定状态的进程提供给用户使用
  4. 用户利用操作系统提供的进程完成任务

进程相关概念

cpu时间片

  • 如果一个进程占有cpu此时我们称为该进程占有cpu时间片。
    多个进程任务会轮流占有cpu时间片形成并发效果。

进程信息(process)

  • PCB(进程控制块):进程创建后会自动在内存生产一个空间存放进程信息。
  • 进程信息:进程的ID,进程占有内存的位置,创建时间,创建用户。。。
  • 查看系统该进程信息:ps  -aux
  • PID(process ID):在操作系统中每个进程都有唯一的PID值是由系统分配的

进程特征:

  • 进程是操作系统分配资源的最小单元
  • 每个进程拥有自己独立的运行空间(虚拟内存空间)
  • 进程之间运行相互独立互不影响

进程的状态:

  • 三态
    • 就绪态:进程具备执行条件,等待系统分配处理器。资源进入运行状态
    • 运行态:进程占有cpu处于运行状态
    • 等待态:进程暂时不具备运行条件,需要阻塞等待
  • 五态(三态基础上增加新建和终止)
    • 新建:创建一个新的进程,获取系统资源的过程
    • 终止:进程执行结束,释放资源的过程
  • ps -aux  ---> STAT表示进程状态
    • D  等待态   阻塞(不可中断等待)
    • S  等待态   睡眠(可中断等待)
    • T  等待态   暂停(暂停状态)
    • R  运行态   (就绪态  运行态)
    • Z  僵尸态
    • +  前台进程(在终端运行)
    • <  有较高优先级的进程
    • N  较低优先级的进程
    • l  有进程链接
    • s  会话组

进程的优先级

  • top :动态查看进程优先级
  • < > 进行翻页  q退出
  • 优先级取值范围:-20 --- 19    -20最高
  • nice:以指定的优先级运行一个程序
  • nice -9 ./while.py
  • sudo --9 ./while.py     -9优先级
    #!/usr/bin/python3 
    表示用/usr/bin/python3 这个目录所代表的程序解释该python程序,放第一行
    
    from time import ctime,sleep
    while True:
        sleep(2)
        print(ctime())
    
    
    
    #(用这运行,程序必须要有可执行权限,可执行权限用chmod 775 while.py)
    #./while.py
    #nice -9 ./while.py
    #另一程序打开top查看

cookie:

  • 首行添加
    #! /usr/bin/python3
  • 修改程序权限添加可执行权限
    chmod 775 while.py
  • 可以直接指明路径执行
    ./while.py

父子进程

  • 在系统中除了初始化进程,每个进程都有一个父进程,可能有0个或多个子进程,由此形成进程间的父子关系
  • 便于进程管理,父进程发起创建子进程请求
  • 查看进程数:pstree
  • 查看父子进程PID:ps -ajx

要求:

  1. 什么是进程,进程和程序的区别
  2. 了解进程的特征和基本概念
  3. 理解并发和并行的区别
  4. 清楚进程的状态及转换

os.fork 创建进程

  • pid = os.fork() 
  • 功能:创建进程
  • 返回值:
    • 失败返回一个负数
    • 成功:在原有进程中返回新进程的PID号
      在新进程中返回0
  • 子进程会复制父进程全部内存空间包括代码段
  • 子进程会从fork的下一句开始执行
  • 父进程中fork返回值即为新创建子进程的PID号
  • 父子进程不一定谁先执行,执行上互不干扰抢占时间片
  • 使用if语句结构使父子进程执行不同的代码几乎是fork创建进程的固定结构
  • 在子进程中对变量等其他内容的修改,不会影响父进程中的内容
  • 子进程虽然复制父进程内容,但是也有自己的特有属性特征,比如PID号,PCB,内存区间等
    示例1:
     
    import os 
    from time import sleep 
    
    print("******************")
    a = 1
    
    pid = os.fork()
    
    if pid < 0:
        print("Create process failed")
    elif pid == 0:
        print("This is Child process")
        print("a = ",a)
        a = 10000
    else:
        sleep(1)
        print("This is parent process")
        print("parent a :",a)

    示例2:

     
    import os 
    from time import sleep
    
    pid = os.fork()
    
    if pid < 0:
        print("create process failed")
    elif pid == 0:
        print("Child PID:",os.getpid())
        print("Get parent PID",os.getppid())
    else:
        sleep(0.5)
        print("Parent PID:",os.getpid())
        print("Get child PID:",pid)
    

     

获取进程PID

  • os.getpid()
  • 功能:获取进程的PID号
  • 返回值:返回进程的PID号

     
  • os.getppid()
  • 功能:获取父进程的PID号
  • 返回值:返回父进程的PID号
    import os 
    from time import sleep
    
    pid = os.fork()
    
    if pid < 0:
        print("create process failed")
    elif pid == 0:
        print("Child PID:",os.getpid())
        print("Get parent PID",os.getppid())
    else:
        sleep(0.5)
        print("Parent PID:",os.getpid())
        print("Get child PID:",pid)
    
    
    #Child PID: 13911
    #Get parent PID 13910
    #Parent PID: 13910
    #Get child PID: 13911
    

     

程序退出

  • os._exit(status)
  • 功能:退出一个进程
  • 参数:进程的退出状态(整数)

     
  • sys.exit([status])
  • 功能:退出一个进程
  • 参数:默认为0
    如果传入一个整数则同_exit()
    传入一个字符串,退出时打印该字符串
  • sys.exit() 可以通过捕获SystemExit异常阻止退出
    import os,sys
    
    # os._exit(0)
    try:
        sys.exit("退出")
    except SystemExit as e:
        print("退出原因:",e)
    
    print("Process end")
    
    #退出原因: 退出
    #Process end
    #sys.exit()可以通过捕获SystemExit异常阻止退出
    

作业

  1. 进程fork理解
  2. 熟悉进程的理论

猜你喜欢

转载自blog.csdn.net/qq_42584444/article/details/81531112