美文网首页Java相关
网络相关 - Linux I/O模型

网络相关 - Linux I/O模型

作者: 万福来 | 来源:发表于2020-04-06 15:56 被阅读0次

    Linux内核将所有的外部设备都看作一个文件来操作,对一个文件的读写操作都会调用内核提供的一个系统命令,返回一个file descriptor (fd,文件描述符)。而对一个socket的读写也会有相应的描述符,称为socket描述符。

    UNIX提供了5种I/O模型

    • 阻塞型I/O:最常用的模型,默认情况下,所有文件操作都是阻塞的,套接字在进程空间中调用recvfrom函数,系统调用直到数据包到达且被复制到应用进程的缓冲区中或者发生错误时才返回,在此期间会一直等待。
    • 非阻塞型I/O:revcfrom用应用层到内核的时候,如果该缓冲区没有数据,就直接返回一个错误码,一般都对非阻塞I/O模型进行轮询检查这个状态,来判断内核是不是有数据到来。
    • I/O复用模型:linux提供select/poll,进程通过将一个或者多个文件描述符传递给select或poll系统调用,阻塞在select操作上,这样select/poll可以帮助我们监听多个文件描述符是否处于就绪状态,select/poll是顺序扫描文件描述符链表,而且支持的文件描述符数量有限。所以linux后期又提供了epoll系统调用,epoll使用基于事件驱动方式代替顺序遍历链表,时间复杂度由O(N)优化为O(1),因此性能更高。当有文件描述符就绪时,通过回调函数进行通知用户进程。
    • 信号驱动I/O模型:首先开启套接口信号驱动I/O功能,并通过系统调用执行信号处理函数,当数据就绪后,就为该进程生成一个sigio信号,通过信号回调通知应用程序。
    • 异步I/O模型:告知内核启动某个操作,并让内核在整个操作完成后通知我们。与信号驱动模型的区别是,信号驱动I/O由内核通知我们何时开始一个I/O操作;异步I/O模型由内核通知我们I/O操作何时已经完成。

    I/O多路复用技术原理

    I/O多路复用技术通过把多个I/O的阻塞复用到同一个select的阻塞上,从而使得系统在单线程的情况下可以同时处理多个客户端请求。
    目前支持I/O多路复用的系统调用有select、pselect、poll、epoll;

    select/poll 与 epoll 对比

    • select支持的socket描述符数量受限制,可以通过FD_SETSIZE设置,默认值1024;epoll没有这个FD的数量限制。
    • select/poll每次调用都会线性遍历扫描整个链表,时间复杂度是O(N); 而epoll使用基于事件驱动方式代替顺序遍历链表,时间复杂度由O(N)优化为O(1),因此性能更高。
    • epoll可以通过内核和用户空间mmap同一块内存实现,加速内核和用户空间的数据传递。
    • epoll的api更加简单,包括创建epoll描述符,添加监听事件,阻塞等待所监听的事件发生,关闭epoll描述符。

    epoll内部实现大概如下:

    • epoll初始化时,会向内核注册一个文件系统,用于存储被监控的句柄文件,调用epoll_create时,会在这个文件系统中创建一个file节点。同时epoll会开辟自己的内核高速缓存区,以红黑树的结构保存句柄,以支持快速的查找、插入、删除。还会再建立一个list链表,用于存储准备就绪的事件。
    • 当执行epoll_ctl时,除了把socket句柄放到epoll文件系统里file对象对应的红黑树上之外,还会给内核中断处理程序注册一个回调函数,告诉内核,如果这个句柄的中断到了,就把它放到准备就绪list链表里。所以,当一个socket上有数据到了,内核在把网卡上的数据copy到内核中后,就把socket插入到就绪链表里。
    • 当epoll_wait调用时,仅仅观察就绪链表里有没有数据,如果有数据就返回,否则就sleep,超时时立刻返回。

    相关文章

      网友评论

        本文标题:网络相关 - Linux I/O模型

        本文链接:https://www.haomeiwen.com/subject/medbphtx.html