zoukankan      html  css  js  c++  java
  • select和poll

    select模型:

    说的通俗一点就是各个客户端连接的文件描述符也就是套接字,

    都被放到了一个集合中,

    调用select函数之后会一直监视这些文件描述符中有哪些可读,

    如果有可读的描述符那么我们的工作进程就去读取资源。 

    select

    基本原理:select 函数监视的文件描述符分3类,分别是writefds、readfds、和exceptfds。
    调用后select函数会阻塞,直到有描述符就绪(有数据 可读、可写、或者有except),
    或者超时(timeout指定等待时间,如果立即返回设为null即可),函数返回。当select函数返回后,可以通过遍历fdset,来找到就绪的描述符。
     

    刚才说了,对于一次IO访问(以read举例),数据会先被拷贝到操作系统内核的缓冲区中,然后才会从操作系统内核的缓冲区拷贝到应用程序的地址空间。所以说,当一个read操作发生时,它会经历两个阶段:
    1. 等待数据准备 (Waiting for the data to be ready)
    2. 将数据从内核拷贝到进程中 (Copying the data from the kernel to the process)

    正式因为这两个阶段,linux系统产生了下面五种网络模式的方案。
    - 阻塞 I/O(blocking IO)
    - 非阻塞 I/O(nonblocking IO)
    - I/O 多路复用( IO multiplexing)
    - 信号驱动 I/O( signal driven IO)
    - 异步 I/O(asynchronous IO)

    注:由于signal driven IO在实际中并不常用,所以我这只提及剩下的四种IO Model。

     

    函数原型:

    int socket_select (array &$read ,array &$write ,array &$except ,int $tv_sec [,int $tv_usec= 0 ])

    作用说明:用于确定一个或多个套接字的状态,对每一个套接字,调用者可查询它的可读性、可写性及错误状态信息

    参数说明:

    read: 指向一组等待可读性检查的套接字

    write: 指向一组等待可写性检查的套接字

    except: 指向一组等待错误检查的套接字

    tv_sec: 用来设置 select() 的等待时间,秒

    tv_usec: 用来设置 select() 的等待时间,微妙

     

    这里注意一下,如果 tv_sec 设置为0,则 socket_select 立即返回,也就是非阻塞的。如果 tv_sec 设置为 null ,则 socket_select 将一直阻塞到有套接字满足条件。

    下面通过代码代码来简单举例:

    poll模型:

    poll 和 select 的实现非常类似,本质上的区别就是存放 fd 集合的数据结构不一样。select 在一个进程内可以维持最多 1024 个连接,poll 在此基础上做了加强,可以维持任意数量的连接。

    但 select 和 poll 方式有一个很大的问题就是,我们不难看出来 select 是通过轮训的方式来查找是否可读或者可写,打个比方,如果同时有100万个连接都没有断开,而只有一个客户端发送了数据,所以这里它还是需要循环这么多次,造成资源浪费。

     

    所以后来出现了 epoll系统调用。

     

    epoll模型:

    epoll 是 select 和 poll 的增强版,epoll 同 poll 一样,文件描述符数量无限制。

    epoll是基于内核的反射机制,在有活跃的 socket 时,系统会调用我们提前设置的回调函数。而 poll 和 select 都是遍历。

    但是也并不是所有情况下 epoll 都比 select/poll 好,比如在如下场景:

    在大多数客户端都很活跃的情况下,系统会把所有的回调函数都唤醒,所以会导致负载较高。既然要处理这么多的连接,那倒不如 select 遍历简单有效。

     

    在 PHP 中我们可以使用 libevet 拓展来实现 epoll。

    libevent 是一个用C语言写的,基于事件驱动的高性能网络库。支持多种 I/O 多路复用技术,epoll、 poll、 dev/poll、 select 和 kqueue 等。 libevent 同时为文件描述符、信号、超时设定等事件提供了监听回调。所以这种编程方式也可以说是事件编程。

  • 相关阅读:
    分布式算法(一致性Hash算法)
    浅析Postgres中的并发控制(Concurrency Control)与事务特性(上)
    PostgreSQL内核分析——BTree索引
    源码安装postgresql数据库
    QEMU漏洞挖掘
    mysql远程连接数据库
    C++学习之路(十一):C++的初始化列表
    搭建本地git服务器
    C++面试常见问题
    SkipList 跳表
  • 原文地址:https://www.cnblogs.com/handsome1013/p/14853440.html
Copyright © 2011-2022 走看看