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多路复用是什么意思

  • 相关阅读:
    HttpServletRequest字符集问题
    原码反码补码
    无符号1byte转int
    初识spark的MLP模型
    冗余系统必要性
    shiro的rememberMe不生效
    阅读笔记-异常
    优雅的处理异常
    使用Maven搭建SpringMVC
    Jmeter发送soap请求
  • 原文地址:https://www.cnblogs.com/EIMadrigal/p/13558310.html
Copyright © 2011-2022 走看看