zoukankan      html  css  js  c++  java
  • I/O Multiplexing

    当多个独立的I/O事件同时发生时,I/O多路复用是一种解决方式。
    为了提高服务器的吞吐量,单个线程通过记录跟踪每个I/O流的状态同时管理多个I/O流,非常类似时分复用技术。
    在这里插入图片描述
    I/O多路复用的具体实现方式有3种:select()poll()epoll()

    select

    select()系统调用:int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);
    select()会一直阻塞直到至少一个文件描述符就绪,可以读写,或者出现异常。
    中间3个参数会被修改,表示哪个FD准备好了,最后一个表示等待时间,NULL表示无限等待。
    返回就绪的FD数目,有错-1。只知道有就绪,不知道哪个FD就绪了。

    int s = socket();
    bind();
    listen();
    
    int fd[];  // 需要监听的socket集合
    while (1) {
    	int n = select();
    	for (int i = 0; i < fd.size(); ++i) {
    		if (FD_ISSET()) {  // 判断哪个socket接收到数据
    			// 处理数据
    		}
    	}
    }
    

    select()是阻塞方法,只有某个socket接收到数据才会继续执行,唤醒进程。
    直接的方式缺点就比较多:

    • 时间开销大,所以规定最多监听1024个socket;
    • 每次调用都要把fd集合从用户态拷贝到内核态。
    • 线程不安全:

    If a file descriptor being monitored by select() is closed in another thread, the result is unspecified.

    poll

    去掉了1024的限制,线程不安全。

    epoll

    线程安全,知道哪个FD就绪,只有Linux支持。
    相比于select()epoll()不会无差别轮询,只处理接收到数据的socket,这样复杂度就降低为(O(k))

    Reference

    I/O多路复用是什么意思

  • 相关阅读:
    03.友盟项目--原始日志数据生成(改进版)---redis存储 用户设备的信息
    Java中的字符集
    时间复杂度
    Hive建模
    08、Spark常用RDD变换
    06、部署Spark程序到集群上运行
    05、Spark
    04、Spark Standalone集群搭建
    02、体验Spark shell下RDD编程
    03、IDEA下Spark API编程
  • 原文地址:https://www.cnblogs.com/EIMadrigal/p/13558310.html
Copyright © 2011-2022 走看看