IT袋

当前位置:主页 > 经验教程 > 系统教程 >

Linux

Linux I/O模型详解(2)

时间:2024-01-14 17:25:08 来源:IT袋 作者:马勇
导读:Linux,非阻塞调用: 程序可以使用非阻塞的系统调用来执行 I/O 操作,这些调用不会阻塞程序的执行,即使数据尚未准备好。 轮询: 程序会周期性地轮询或检查

Linux

  • 非阻塞调用:程序可以使用非阻塞的系统调用来执行 I/O 操作,这些调用不会阻塞程序的执行,即使数据尚未准备好。
  • 轮询:程序会周期性地轮询或检查 I/O 操作的状态,以确定它们是否已经完成。这可以通过使用系统调用如 select、poll、epoll(Linux系统)或异步事件处理来实现。
  • 回调函数:另一种方法是使用回调函数,程序发起一个 I/O 操作,然后指定一个回调函数,以便在操作完成时被调用。这样,程序可以继续执行其他任务,而无需轮询。

NIO 具有多种优势和应用场景:

  • 高并发处理:在服务器应用中,NIO 可以帮助服务器同时处理大量并发连接,而不会因等待 I/O 操作而陷入停滞状态。
  • 实时应用:对于需要快速响应的实时应用,如在线游戏或聊天应用,非阻塞 I/O 可以确保系统不会因等待 I/O 操作而引起延迟。
  • 节约资源:NIO 可以节省系统资源,因为程序不需要创建大量的线程或进程来处理并发连接。
  • 异步编程:NIO 是异步编程的核心,允许程序执行其他任务而不必等待 I/O 完成。这在事件驱动编程中非常有用。

非阻塞调用

早期的NIO 只是 read、write、recv 和 send 的调用不会阻塞,每次调用可以通过返回值来判断是否有数据下面是非阻塞调用的实现:

public void serverStartNIO() {
  // list 用户维护所有的 Client 连接
  LinkedList<SocketChannel> clients = new LinkedList<>();
  // 创建服务端
  ServerSocketChannel ss = ServerSocketChannel.open();  //服务端开启监听:接受客户端
  ss.bind(new InetSocketAddress(8080));
  // 客服务端监听 connect 请求为非阻塞, 注意: 仅仅是服务端监听客户端连接请求非阻塞
  ss.configureBlocking(false); 
  while (true) {
    // 因为接受客户端连接 accept 是非阻塞, 为了避免没有连接时死循环, CPU跑满需要 sleep 一下
    Thread.sleep(1000);
    // 接受客户端的连接
    // accept  调用内核了:
    //   1,没有客户端连接进来,在BIO 的时候一直卡着,但是在NIO不卡着,返回-1,NULL
    //   2. 如果来客户端的连接,accept 返回的是这个客户端的fd
    SocketChannel client = ss.accept(); 
    // NON BLOCKING 就是代码能往下走了,只不过有不同的情况
    if (client == null) {
      //  没有客户端连接进来,在BIO 的时候一直卡着,但是在NIO不卡着,返回-1,NULL
    } else {
      // 设置该连接 read, write 为非阻塞
      client.configureBlocking(false);
      // 把连接加入列表, 统一管理, 循环遍历
      clients.add(client);
    }
    // 遍历已经链接进来的客户端能不能读写数据
    for (SocketChannel c : clients) {
      // client.configureBlocking(false) 设置的效果就是 下面 read 操作不会阻塞 
      int num = c.read(buffer);
      if (num > 0) {
         // num > 0 表示读取到了数据
      }
    }
  }
}

相关阅读