栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 系统运维 > 运维 > Linux

IO多路复用器

Linux 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

IO多路复用器

IO多路复用器
    • 解决问题
    • 基础中断
    • 分类
      • select
      • poll
      • epoll
    • java代码说明
      • 启动服务服务注册selector
      • select事件处理

解决问题

同步:应用自己进行IO读写
异步:内核完成IO读写,应用没有访问IO,回调程序只是读取访问Buffer而已
阻塞:BLOCKING 程序堵塞等待IO
非阻塞:NONBLOCKING 程序不堵塞,如果没有IO,会返回-1
组合:同步阻塞、同步非阻塞、异步非阻塞

多路IO通过一个系统调用,可以获得其中IO状态,然后有程序对自己敢兴趣的IO状态进程操作。

基础中断

分类 select

select函数需要遍历所有传入文件描述符的IO连接,只不过这个过程是由操作系统内核完成的,只会触发一次系统调用。

select的IO中断响应只是把网卡数据通过DMA拷贝到select函数传入文件描述符的Buffer中。

传统的NIO这个遍历过程需要每次调用操作系统内核完成查询IO状态,涉及到多次内核态用户态转换,系统执行效率底下。

Linux系统函数

poll

poll函数需要遍历所有传入文件描述符的IO连接,只不过这个过程是由操作系统内核完成的,只会触发一次系统调用。

参考select

epoll

epoll系统函数,会在操作中开辟一个系统空间,这个操作空间是红黑树结构,内部维护了传入文件描述符集合,当有IO事件发生的时候,内核会将有IO状态发生的文件描述符拷贝到一个链表,应用程序只需要遍历这个链表就可以,无需遍历所有文件描述符,极大提升系统效率。

linux系统函数

java代码说明 启动服务服务注册selector
        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
        serverSocketChannel.socket().bind(new InetSocketAddress(9090));
        serverSocketChannel.configureBlocking(false);
        //linux多路复用器 select poll epoll
        //打开Selector处理Channel
        Selector selector = Selector.open();
        //select,poll会在jvm里面开辟内存维护FD数组,epoll:elpoll_ctl添加到内核开辟的空间
        //把ServerSocketChannel注册到Selector上,并且selector监听accept连接事件
        serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
select事件处理
while(true){
            //它会阻塞等待需要处理的事件发生
            selector.select();
             //select,poll调用内核select(FDS),epoll调用epoll_wait
            //获取selector感知到的事件集合
            Set selectionKeys = selector.selectedKeys();
            Iterator iterator = selectionKeys.iterator();
		   //遍历SelectionKey,对事件进行处理
		    while(iterator.hasNext()){

          SelectionKey key = iterator.next();
        //如果是OP_ACCEPT连接事件。则进行连接获取和事件注册
        if(key.isAcceptable()){
            ServerSocketChannel server = (ServerSocketChannel) key.channel();
            SocketChannel socketChannel = server.accept();
            socketChannel.configureBlocking(false);
            //注册读事件
            socketChannel.register(selector, SelectionKey.OP_READ);
        }else if(key.isReadable()){
            //如果是OP_READ读事件。则进行读取
            SocketChannel server = (SocketChannel) key.channel();
            ByteBuffer byteBuffer = ByteBuffer.allocate(32);
            int read = server.read(byteBuffer);

            if(read > 0){
                System.out.println("接收到消息:" + new String( byteBuffer.array() ));

            } else if(read == -1){//如果客户端断开连接,关闭socket
                iterator.remove();
                server.close();
            }

            //从事件集合中删除本次处理的key,防止下次重复处理
            iterator.remove();
        }
    }
}
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/887132.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号