非阻塞IO(NIO)
一、前言
1.1、阻塞IO,BIO
BIO(Blocking I/O)
也称作同步阻塞IO。
1.2、非阻塞IO,NIO
NIO(Non-blocking I/O)
也称作同步非阻塞IO;
现在常用的NIO,是NIO+IO多路复用的结合体,epoll 还是会阻塞线程,不是真正的非阻塞IO。
1.3、异步IO,AIO
AIO(Asynchronous I/O)
二、同步/异步 和 阻塞/非阻塞
2.1 概念
- 同步
调用方发起一个功能调用时,在没有得到功能的结果之前,该调用不会返回。也就是调用方会等待被调用方返回功能的结果。 - 异步
调用方发起一个功能调用时,没有得到功能的结果立即返回,后续被调用方再通过回调等手段,把功能的结果通知调用方。也就调用方立即得到返回,但是返回中不包含功能结果。
Linux 的 AIO 中,异步的结果是通过内核的回调拿到的
- 阻塞
线程发起一个调用时,在调用返回之前,线程会被阻塞,在这个状态下会交出当前CPU的使用权限而暂停。也就是调用方会等待调用结果,调用阻塞了调用方的线程,线程不在运行处理中。 - 非阻塞
线程发起一个调用时,调用会立即返回,避免线程被阻塞。但是返回结果只是被调用方当前状态的值,实际使用时,调用方需要轮询,走到返回结果符合预期(直到数据准备好)
2.2 区别
- 同步和异步的区别
区别是,调用方是否能够直接得到功能结果。
同步会一直等待,直接到得到功能结果。
异步会立即得到一个不包含结果的返回,功能的结果要由被调用方通知。 - 阻塞和非阻塞的区别
区别是,调用是否公立即返回,进而是否阻塞调用方线程,在网络IO中,是指在数据未准备好的情况下,是否会阻塞线程走到数据准备好。
阻塞会阻塞线程,调用方只能等待。
非阻塞由于调用立即返回,而不阻塞线程,调用方可以继续做别的事情。 - 同步和阻塞区别
区别是,是否会阻塞调用方线程。
同步不会阻塞调用方线程,线程在运行处理中,中是逻辑上调用未返回而已。
阻塞会阻塞调用方线程,线程不在运行处理中。 - 同步异步和阻塞非阻塞的区别
区别是,讨论点不同。
同步异步,讨论的是被调用方返回结果的通知机制。
阻塞非阻塞,讨论的是,调用方的线程状态。
三、NIO 的演变
3.1 NIO 的诞生
- 前置知识
假设在 Linux 上运行应用,该应用监听了某个端口,通过网络获取外部数据。应用(application)是运行在Linux 的用户空间的,而外部数据是在Linux的内核空间中接收到的。
- 外部数据先到网卡、现保存到内核缓冲区、最后进入应用缓冲区。
- 应用调用 read 方法读取外部数据,Linux 的内核操作分为 2 步:
- 等待数据就绪
- 把内核缓存区的数据复制到用户缓存区
1. BIO
- Linux 的IO模型最初的是BIO
BIO一次 read(),触发了内核的两步操作,全程都阻塞。 - 优点:线程阻塞时,消耗的CPU资源小。
- 缺点:高并发时容易耗尽线程资源,且大量线程会引起线程切换的巨大开销,造成响应不及时。
2. NIO
NIO,靠着Linux 提供的可以立即返回的read(),在第一步中是不阻塞的,在第二步中仍然是阻塞的。
- 优点:把应用线程的read调用,分割出了第一步和第二步,应用线程可以做更多实时的控制。
- 缺点:第一步中的轮询,大量点用CPU时间,降低系统资源利用率,所以一般web服务器也不使用这样的NIO
为了解决NIO轮询的缺点,引入了IO多路复用,用操作系统的IO多路复用,来替代轮询。
3. IO多路复用
IO多路复用是一种同步IO模型,是操作系统提供的能力,使用少量线程监听Linux的多个IO文件描述符,也就是线程复用于多个IO请求。
如果有任意IO文件描述符就绪,就会告知应用进行读取;如果没IO文件描述符就绪,就会阻塞应用线程。
Linux 中,IO多路复用的实现是 select/poll/epoll
IO多路复用的作用: 线程复用于多个请求,用较小的线程开销来支持更多的并发请求
NIO结合IO多路复用后,select/poll/epoll替代了轮询
- Linux 上的 IO 多路复用演变经历了3个阶段:
一、select
二、poll
三、epoll
目前使用的是 epoll,默认是 epoll的水平触发模式(LT),还有一个边缘触发模式(ET),应用一般是用LT。
-
select
轮询遍历IO文件描述符,O(n)的线性时间复杂度,因此随着IO文件描述符的增多,性能下降。
单进各能够打开的文件描述符有数量限制,导致应用的最大连接数是1024.
调用select时,还需要文件描述符在用户空间和内核空间的拷贝,影响性能。 -
poll
同样是轮询遍历IO文件描述符,O(n)的线性时间复杂度,因此随着IO文件描述符的增多,性能下降。
无文件描述符的数量限制。
调用poll时,还需要文件描述符在用户空间和内核的拷贝,影响性能。 -
epoll
解决了select和poll的全部缺点,采用注册回调机制,替代了轮询遍历,无文件描述符的数量限制。
利用mmap减少了文件描述符在用户空间和内核空间的拷贝,因此性能高。
原文链接:https://blog.csdn.net/lic721/article/details/126842761
若有凝问或错误,请指出,我好及时改正,让我们一起进步!
email : binary_space@126.com
qq : 103 586 2795
敲门砖: 代码谱写人生