Linux中IO演变历程

39 阅读2分钟

BIO 时期内核的大致操作使用read命令读取文件描述符:

此时的文件描述符是blocking 的,也就是阻塞的

image.png

SOCKET_NONBLOCK 非阻塞的,对应的文件描述符是NONBLOCK的

NIO 同步非阻塞IO image.png

多路复用NIO(内核中增加了select系统调用)

image.png

epoll(异步非阻塞IO-NIO)

多路复用NIO存在的问题: 用户态、内核态,所有的文件描述符从用户空间通过select调用发送给内核,当fd有了数据之后,还需要将fd发送给用户空间,这一步的fd拷贝也成了影响性能的点。

mmap通过开辟一个用户和内核的共享空间,将文件描述符放到共享空间中,这样就不需要再进行fd的拷贝过程了。

共享空间中,将所有的文件描述符 红黑树, 进程通过epoll ctl将文件描述符放到共享空间中的红黑树数据结构中,然后内核再将有数据的fd放到链表中,用户线程只需要读取共享空间中的链表即可

通过epoll ctl系统调用将链接(fd 文件描述符)注册到共享空间的红黑树中,共享空间的增删改是内核来完成的,用户和内核都可以进行查询。 然后用户再去调一个系统调用 ctl add delete sfd 还有一个是wait()等待事件,事件驱动(当链表中有了数据就会回调用户空间),链接中谁的数据到了就会将这个链接的文件描述就放到链表中。然后用户再去调用read/write进行数据的读取或者写入。到现在还是NIO,因为只要读取和写入的还是由用户来完成的就不是AIO。

image.png

sendfile 调用,实现的零拷贝

image.png

kafka中实现的零拷贝

image.png