【计算机网络】高并发业务必备的Linux网络IO模型

简介: 【计算机网络】高并发业务必备的Linux网络IO模型

IO的操作也就是应用程序从TCP缓冲区中读取数据的时候。

网络I/O的本质是socket的读取,socket在linux中被抽象为流,I/O可以理解为对流的操作。对于一次I/O访问,数据会先被拷贝到操作系统的内核的缓冲区中,然后才会从操作系统内核的缓冲区拷贝到应用程序的地址空间。所以说当一个read操作发生时,他会经历两个阶段:

第一阶段:等待数据准备(Waiting for the data to be ready)
第二阶段:将数据从内核拷贝到进程中(Copy the data from the kernel to the process)

对于socket流而言:

第一步:通常涉及等待网络上的数据分组到达,然后被复制到内核的某个缓冲区
第二步:把数据从内核缓冲区复制到进程缓冲区

1.阻塞IO(BIO)

(1)什么是阻塞I/O

阻塞IO就是当应用程序向TCP缓冲区发起读取数据申请时,在内核数据没有准备好之前,应用程序会一致处于等待数据的状态,直到内核把数据准备好交给应用程序才结束。

术语描述:在应用程序调用recvfrom读取数据时,其系统调用直到数据包到达别并且被复制到应用缓冲区中或者发生错误时才返回,此期间一致处于等待,进程从调用直到返回这段时间被阻塞的成为阻塞IO。

(2)阻塞I/O流程


4cc8614744d84715839e9a09f0364513.jpg

  • 第一步:应用程序向内核发起recvfrom读取数据
  • 第二步:准备数据报(应用进程阻塞)
  • 第三步:将数据从内核复制到应用空间
  • 第四步:复制完成后,返回成功提示

2.非阻塞I/O(NIO)

(1)什么是非阻塞I/O

非阻塞I/O就是当应用程序发起读取数据时,如果内核没有准备好数据报,会返回给应用程序,不会让应用程序一致等待,但是应用程序要时不时去尝试调用,当数据包准备好时,将数据从内核复制到用户空间,这个过程也是同步的,阻塞的。

术语描述:非阻塞I/O是在应用调用recvfrom读取数据时,如果缓冲区中没有数据的话,就会直接返回一个EWOULDBLOCK错误,不会让应用一致等待。在没有数据时会即刻返回错误标识,那也意味着如果应用要读取数据就需要不断的调用recvfrom请求,直到读取到它要的数据为止。

(2)非阻塞I/O流程

d8fb5ca73b4a4e69ba488e970fe3f8f6.jpg

  • 第一步:应用进程向内核发起recvfrom读取数据
  • 第二步:没有数据报准备好,即刻返回EWOULDBLOCK错误码
  • 第三步:应用程序向内核再次发起recvfrom读取数据
  • 第四步:已有数据报就从内核拷贝到用户空间,否则还是返回错误码

3.I/O多路复用

(1)什么时I/O多路复用

I/O多路复用的思路就是系统提供了一种函数可以同时监控多个网络请求的操作,这个函数就是我们常说的select、poll、epoll函数,有了这个函数后,

应用线程通过调用select函数就可以同时监控多个网络请求,select函数监控的网络请求中只要有任何一个数据状态准备就绪了,select函数就会返回可读状态,这时询问线程再去通知处理数据的线程,对应线程此时再发起recvfrom请求去读取数据。

术语描述:进程通过将一个或者多个网络请求传递给select,阻塞在select操作之上,select帮我们侦测多个网络请求是否准备就绪,当有网络请求准备就绪时,select返回数据可读状态,应用程序在调用recvfrom读取数据。

(2)I/O多路复用流程

2d20c3bed7eb49d395237133164ade20.jpg

  • 第一步:进程发起网络请求到select函数调用进行阻塞
  • 第二步:select函数调用内核获取数据报
  • 第三步:select函数监控的网络请求中只要有任何一个数据状态准备就绪了,select函数就会返回可读状态
  • 第四步:询问线程再去通知处理数据的线程,对应线程在次发起recvfrom请求去读取数据

4.信号驱动I/O

(1)什么是信号驱动I/O

信号驱动I/O不是循环请求询问的方式去监控数据就绪状态,而是调用sigaction时候建立一个SIGIO的信号联系,当内核数据准备好之后在通过SISGIO信号通知线程数据准备好后的可读状态,当线程收到可读状态的信号后,此时在向内核发起recvfrom读取数据的请求,因为信号驱动I/O的模型下应用线程在发出信号监控后即可返回,不会阻塞,所以这样的方式下,一个应用线程也可以控制多个网络请求。


术语描述:首先开启套接字信号驱动I/O功能,并通过系统调用sigaction执行一个信号处理函数,此时请求即可返回,当数据准备就绪时,就生成对应进程的SIGIO信号,通过信号回调通知应用线程调用recvfrom来读取数据。

(2)信号驱动I/O流程


f442bc19f1544c12b1ee4bf1381f3ed0.jpg

  • 第一步:进程建立SIGIO的信号处理程序调用sigaction,然后返回
  • 第二步:内核准备好数据递交SIGIO给信号处理程序
  • 第三步:应用程序收到信号后,调用数据拷贝,复制完成返回数据报

5.异步I/O(AIO)

(1)什么是异步I/O

异步I/O应用只需要向内核发送一个read请求,告诉内核他要读取数据后即刻返回,内核收到请求后会建立一个信号联系,但数据准备就绪,内核会主动把数据从内核复制到用户空间,等所有操作都完成之后,内核会发起一个通知告诉应用,处理数据报完成。

术语描述:应用告知内核启动某个操作,并让内核在整个操作完成之后,通知应用,这种模型与信号驱动的主要区别在于信号驱动I/O是由内核通知我们何时开始下一个I/O,而异步I/O模型是由内核通知我们操作什么时候完成。

(2)异步I/O流程


dc410fc310c143af94da8aad54a05195.jpg

  • 第一步:异步I/O应用只需要向内核发送一个read请求,告诉内核他要读取数据后即刻返回
  • 第二步:内核收到请求后会建立一个信号联系,但数据准备就绪
  • 第三步:内核会主动把数据从内核复制到用户空间,等所有操作都完成之后,内核会发起一个通知告诉应用,处理数据报完成

6.IO多路复用的select-poll-epoll区别

select poll epoll
查找模式 遍历 遍历 回调
底层结构 bitmap 链表 红黑树
最大值 x86架构32位系统最大1024 x64架构64位系统最大2048 无限制 无限制,1G内存大概支持10万个句柄fd
IO效率 每次调用,线性遍历,时间复杂度O(n) 每次调用,线性遍历,时间复杂度O(n) 当fd就绪,系统注册的回调函数就会被调用,将就绪fd放到列表里,时间复杂度O(1)

image.png

相关文章
|
2月前
|
缓存 安全 Linux
Linux 五种IO模型
Linux 五种IO模型
|
7天前
|
存储 关系型数据库 MySQL
查询服务器CPU、内存、磁盘、网络IO、队列、数据库占用空间等等信息
查询服务器CPU、内存、磁盘、网络IO、队列、数据库占用空间等等信息
53 5
|
10天前
|
存储 机器人 Linux
Netty(二)-服务端网络编程常见网络IO模型讲解
Netty(二)-服务端网络编程常见网络IO模型讲解
基于套接字的IO模型
基于套接字的IO模型
|
2月前
|
消息中间件 网络协议 Java
你不得不了解的网络IO模型知识
该文章主要讲述了网络I/O模型的相关知识,包括不同的I/O模型以及它们的特点和应用场景。
你不得不了解的网络IO模型知识
|
2月前
|
数据采集 资源调度 JavaScript
Node.js 适合做高并发、I/O密集型项目、轻量级实时应用、前端构建工具、命令行工具以及网络爬虫和数据处理等项目
【8月更文挑战第4天】Node.js 适合做高并发、I/O密集型项目、轻量级实时应用、前端构建工具、命令行工具以及网络爬虫和数据处理等项目
38 5
|
2月前
五种IO模型基本概念
正确选择与应用适合的I/O模型是提升程序性能,保证响应时间和处理能力的关键。选择时需要综合考虑程序的实际应用场景、性能要求以及开发和维护的复杂性。
31 1
|
2月前
|
小程序 Linux 开发者
Linux之缓冲区与C库IO函数简单模拟
通过上述编程实例,可以对Linux系统中缓冲区和C库IO函数如何提高文件读写效率有了一个基本的了解。开发者需要根据应用程序的具体需求来选择合适的IO策略。
26 0
|
2月前
|
存储 IDE Linux
Linux源码阅读笔记14-IO体系结构与访问设备
Linux源码阅读笔记14-IO体系结构与访问设备
|
3月前
|
存储 Java Unix
(八)Java网络编程之IO模型篇-内核Select、Poll、Epoll多路复用函数源码深度历险!
select/poll、epoll这些词汇相信诸位都不陌生,因为在Redis/Nginx/Netty等一些高性能技术栈的底层原理中,大家应该都见过它们的身影,接下来重点讲解这块内容。
下一篇
无影云桌面