IO多路复用

面对高并发场景,I/O多路复用成为解决之道,包括select、poll和epoll等系统调用。select存在最大文件描述符限制,poll虽无限制但仍有遍历开销,而epoll利用回调机制实现高效事件通知,且通过mmap减少fd拷贝。
摘要由CSDN通过智能技术生成

I/O多路复用(事件驱动模型)

       多进程、多进程模型会因为开销巨大和调度困难而导致并不能承受高并发量。但不适用这种模型的话,无论是阻塞还是非阻塞方式都会导致整个服务器停滞。所以对于大并发量,我们需要一种代理模型可以帮助我们集中去管理所有的socket连接,一旦某个socket数据到达了就执行其对应的用户进程,I/O多路复用就是这么一种模型。Linux下I/O多路复用的系统调用有select,poll和epoll,但从本质上来讲他们都是同步I/O范畴。

  1. select

    • 相关接口:

      int select (int maxfd, fd_set *readfds, fd_set *writefds, fd_set *errorfds, struct timeval *timeout);

      FD_ZERO(int fd, fd_set* fds) //清空集合

      FD_SET(int fd, fd_set* fds) //将给定的描述符加入集合

      FD_ISSET(int fd, fd_set* fds) //将给定的描述符从文件中删除

      FD_CLR(int fd, fd_set* fds) //判断指定描述符是否在集合中

    • 参数: maxfd:当前最大文件描述符的值+1(≠ MAX_CONN)。

      readfds:指向读文件队列集合(fd_set)的指针。

      writefds:同上,指向读集合的指针。

      writefds:同上,指向错误集合的指针。

      timeout:指向timeval结构指针,用于设置超时。

    • 其他:

      判断和操作对象为set_fd集合,集合大小为单个进程可打开的最大文件数1024或2048(可重新编译内核修改但不建议)。

  2. poll

    • 相关接口: int poll(struct pollfd *fds, unsigned int nfds, int timeout);

    • 结构体定义: struct pollfd{ int fd; // 文件描述符 short events; // 等到的事件 short revents; // 实际发生的事件 }

    • 参数: fds:指向pollfd结构体数组的指针。

      nfds:pollfd数组当前已被使用的最大下标。

      timeout:等待毫秒数。

    • 其他:

      判断和操作对象是元素为pollfd类型的数组,数组大小自己设定,即为最大连接数。

  3. epoll

    • 相关接口: int epoll_create(int size); // 创建epoll句柄 int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event); // 事件注册函数 int epoll_wait(int epfd, struct epoll_event * events, int maxevents, int timeout);

    • 结构体定义: struct epoll_event{ __uint32_t events; epoll_data_t data; }; typedef union epoll_data{ void *ptr; int fd; __uint32_t u32; __uint64_t u64; }epoll_data_t;

    • 参数:

      size:用来告诉内核要监听的数目。

      epfd:epoll函数的返回值。

      op:表示动作(EPOLL_CTL_ADD/EPOLL_CTL_FD/EPOLL_CTL_DEL)。

      fd:需要监听的fd。

      events:指向epoll_event的指针,该结构记录监听的事件。

      maxevents:告诉内核events的大小。

      timeout:超时时间(ms为单位,0表示立即返回,-1将不确定)。

  4. select、poll和epoll区别

    • 操作方式及效率:

      select是遍历,需要遍历fd_set每一个比特位(= MAX_CONN),O(n);poll是遍历,但只遍历到pollfd数组当前已使用的最大下标(≠ MAX_CONN),O(n);epoll是回调,O(1)。

    • 最大连接数:

      select为1024/2048(一个进程打开的文件数是有限制的);poll无上限;epoll无上限。

    • fd拷贝:

      select每次都需要把fd集合从用户态拷贝到内核态;poll每次都需要把fd集合从用户态拷贝到内核态;epoll调用epoll_ctl时拷贝进内核并放到事件表中,但用户进程和内核通过mmap映射共享同一块存储,避免了fd从内核赋值到用户空间。

    • 其他:

      select每次内核仅仅是通知有消息到了需要处理,具体是哪一个需要遍历所有的描述符才能找到。epoll不仅通知有I/O到来还可通过callback函数具体定位到活跃的socket,实现伪AIO。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值