zoukankan      html  css  js  c++  java
  • Python IO模型

    之前学到gevent 遇到IO操作,自动切换

    对于一个network IO (这里我们以read举例),它会涉及到两个系统对象,一个是调用这个IO的process (or thread),另一个就是系统内核(kernel)。当一个read操作发生时,它会经历两个阶段:

    • 1 等待数据准备 (Waiting for the data to be ready)
    • 2 将数据从内核拷贝到进程中 (Copying the data from the kernel to the process)

    记住这两点很重要,因为这些IO Model的区别就是在两个阶段上各有不同的情况。

    IO模型

    • 阻塞IO
    • 非阻塞IO
    • IO多路复用(监听多个连接)
    • 异步IO
    • 驱动信号

    1 阻塞IO blocking

    默认的socket是阻塞的,任务是串行执行的

    一个典型的读操作流程:
    wait data和copy data的过程中都是在等待的,也就是阻塞的。

    内核态--用户态

    操作系统操作的
    数据存放在内核空间(数据缓冲区),操作系统把内核空间中的数据传到用户空间

    数据准备阶段

    accept发起系统调用,用户态转换成内核态
    等待数据wait for data、copy data from kernal to user
    都是阻塞,就是全程阻塞,在没有到达用户态的时候,都是阻塞

    2 非阻塞IO nonblocking

    可以通过设置socket的编程unblocking,sock.setblocking(True)

    sock.setblocking(False) 这个没有连接,立刻报错

    会立即返回是否已经连接了

    wait data 不是阻塞的
    从内核态拷贝数据 copy data到用户态的时候是阻塞的

    • 优点:不用等待数据 ,在发起系统调用的过程中是自己的时间
    • 缺点:一直发起系统调用,拿到的数据不是实时的

    3 IO多路复用 select

    IO 多路复用的本质就是非阻塞IO,它的基本原理就是select/epoll这个function会不断的轮询所负责的所有socket,当某个socket有数据到达了,就通知用户进程

    面试中的比较多

    把等待数据的过程分成了两部分:

    • select 替代看wait for data return readable代表收到数据
    • recv已经获得了数据

    select 可以连接多个套接字对象,

    r,w,e = select.select([socket,],[],[])

    socketserver是threading和select共同实现的,利用了多线程和IO多路复用

    select是在监听,监听的是有变化的套机子

    第一次监听的是sock对象,第二次连接的是conn

    socket是一个文件描述符,fd是一个整数

    select是基于IO操作,节省时间

    基于IO多路复用的socket 多并发聊天

    客户端select机制

    import socket
    import select
    import time
    
    sock = socket.socket()
    sock.bind(("127.0.0.1",8810))
    
    sock.listen(5)
    
    sock.setblocking(False)
    
    inputs = [sock,]  # 监听的列表
    while 1:
        r,w,e = select.select(inputs,[],[])  # 监听有变化的套接字,inputs  = [socket,conn1,conn2...]
        for obj in r:
            if obj==sock:  # 第一次用[socket],第二次[conn]
                conn,addr = obj.accept()
                print("conn",conn)
                inputs.append(conn) #
            else:
                data = obj.recv(1024)
                print(data.decode("utf-8"))
                send_data = input(">>>")
                obj.send(send_data.encode("utf-8"))
    

    客户端

    import socket
    
    sock = socket.socket()
    
    sock.connect(("127.0.0.1", 8810))
    
    while 1:
        data = input(">>>")
        sock.send(data.encode("utf-8"))
        recv_data = sock.recv(1024)
        print(recv_data.decode("utf-8"))
    sock.close()
    
    

    测试结果:

    有两个通道,socket是建立连接的,conn是进行通信的管道。sock对象是不变的。

    关于文件描述符(套接字对象):

    • 是非零整数,不会变(fd=xxx,xxx是一个整数,filedescription)
    • 收发数据的时候,对于接收端而言,数据先到内核空间,然后copy到用户空间,同时内核空间的数据清空(内核空间和数据空间都是内存中分配的)
    • 发送端的时候,TCP的三次握手没有应答,数据不清空

    IO多路复用总结

    IO多路复用的特性:(监听多个连接)

    • 全程阻塞 wait for data copy data
    • 监听多个文件描述符

    4 异步IO

    全程无阻塞
    实现起来复杂的

    最后总结:

    阻塞IO,进程一直等待
    非阻塞IO,copy data 的过程是阻塞的
    IO多路复用,全程阻塞

    • 有阻塞的就是同步IO
      (阻塞IO 、非阻塞IO(copy data),IO多路复用)

    • 没有阻塞的是异步IO

    [^1]http://anjianshi.net/post/yan-jiu-bi-ji/python-blocking

    [^2]http://www.cnblogs.com/yuanchenqi/articles/6755717.html

  • 相关阅读:
    [ Algorithm ] N次方算法 N Square 动态规划解决
    [ Algorithm ] LCS 算法 动态规划解决
    sql server全文索引使用中的小坑
    关于join时显示no join predicate的那点事
    使用scvmm 2012的动态优化管理群集资源
    附加数据库后无法创建发布,error 2812 解决
    浅谈Virtual Machine Manager(SCVMM 2012) cluster 过载状态检测算法
    windows 2012 r2下安装sharepoint 2013错误解决
    sql server 2012 数据引擎任务调度算法解析(下)
    sql server 2012 数据引擎任务调度算法解析(上)
  • 原文地址:https://www.cnblogs.com/Python666/p/6835885.html
Copyright © 2011-2022 走看看