[转帖]Linux 6种网络IO模型

linux,网络,io,模型 · 浏览次数 : 0

小编点评

**I/O 模型** I/O 模型是一种缓存 IO 的机制,它将 IO 的数据缓存在文件中系统的页缓存中。数据从页缓存中读出后,才会从操作系统内核的缓冲区中读出。 **同步 IO** * 同步 IO 是一种阻塞的模型,它等待数据准备完毕才能从内核拷贝到应用程序的地址空间。 * 当数据准备好了时,内核会通知应用程序。 **非同步 IO** * 非同步 IO 是异步的模型,它不阻塞地等待数据准备完毕。 * 当数据准备好了时,内核会通知应用程序,应用程序可以继续处理其他任务。 **多路复用 IO** * 多路复用 IO 是一个异步模型,它利用多个线程或进程进行 IO 操作。 * 它可以处理多个客户端连接的请求,而无需创建新的进程或线程。 **信号驱动 IO** * 信号驱动 IO 是一个异步模型,它使用信号来通知应用程序数据准备好。 * 当数据准备好时,进程会收到一个 SIGIO 信号,并在信号处理函数中调用 I/O 操作函数处理数据。

正文

https://www.jianshu.com/p/c5aa9197ecf4

 

背景

大多数文件系统的默认 IO 操作都是缓存 IO,又被称作标准IO。在 Linux 的缓存 IO 机制中,操作系统会将 IO 的数据缓存在文件系统的页缓存(page cache )中,也就是说,数据会先被拷贝到操作系统内核的缓冲区中,然后才会从操作系统内核的缓冲区拷贝到应用程序的地址空间。

缓存 IO 的缺点:数据在传输过程中需要在应用程序地址空间和内核进行多次数据拷贝操作,这些数据拷贝操作所带来的 CPU 以及内存开销是非常大的。

网络IO的本质是socket的读取,socket在linux系统被抽象为流,IO可以理解为对流的操作。对于一次IO访问(以read举例),数据会先被拷贝到操作系统内核的缓冲区中,然后从操作系统内核的缓冲区拷贝到应用程序的地址空间。

当一个read操作发生时,经历两个阶段:

第一阶段:等待数据准备 (Waiting for  the data to be ready)。

第二阶段:将数据从内核拷贝到进程中  (Copying the data from the kernel to the process)。

对于socket流而言,

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

第二步:把数据从内核缓冲区复制到应用进程缓冲区。

网络应用需要处理的无非就是两大类问题,网络IO和数据计算。相对于后者,网络IO的延迟,给应用带来的性能瓶颈大于后者,我们重点关注前者。

网络IO的模型

网络IO的模型大致分为6种:

· 同步IO(synchronous IO)

· 阻塞IO(bloking IO)

· 非阻塞IO(non-blocking IO)

· 多路复用IO(multiplexing IO)

· 信号驱动IO(signal-driven IO)

· 异步IO(asynchronous IO)

相关概念介绍:

同步是一个任务的完成需要依赖另外一个任务时,只有等待被依赖的任务完成后,依赖的任务才能算完成,这是一种可靠的任务序列。要么都成功,要么都失败,两个任务的状态可以保持一致。

异步是不需要等待被依赖的任务完成,只是通知被依赖的任务要完成什么工作,依赖的任务也立即执行,只要自己完成了整个任务就算完成了。至于被依赖的任务最终是否真正完成,依赖它的任务无法确定,所以它是不可靠的任务序列。

阻塞调用指调用结果返回之前,当前线程会被挂起,一直处于等待消息通知,不能够执行其他业务。函数只有在得到结果之后才会返回。

非阻塞调用指在不能立刻得到结果之前,该函数不会阻塞当前线程,而会立刻返回。虽然表面上看非阻塞的方式可以明显的提高CPU的利用率,但是也带了另外一种后果就是系统的线程切换增加。增加的CPU执行时间能不能补偿系统的切换成本需要好好评估。

(a) 如果这个线程在等待当前函数返回时,仍在执行其他消息处理,那这种情况就叫做同步非阻塞;

(b) 如果这个线程在等待当前函数返回时,没有执行其他消息处理,而是处于挂起等待状态,那这种情况就叫做同步阻塞;

同步/异步关注的是消息通知的机制,而阻塞/非阻塞关注的是程序(线程)等待消息通知时的状态:等待消息的同时是否处理其他消息。

正在执行的进程,由于期待的某些事件未发生,如请求系统资源失败、等待某种操作的完成、新数据尚未到达或无新工作做等,则由系统自动执行阻塞原语(Block),使自己由运行状态变为阻塞状态。可见,进程的阻塞是进程自身的一种主动行为,也因此只有处于运行态的进程(获得CPU),才可能将其转为阻塞状态。当进程进入阻塞状态,是不占用CPU资源的。

为了控制进程的执行,内核必须有能力挂起正在CPU上运行的进程,并恢复以前挂起的某个进程的执行。这种行为被称为进程切换。从一个进程的运行转到另一个进程上运行,这个过程很消耗资源,经过下面这些变化:

1、保存处理机上下文,包括程序计数器和其他寄存器。

2、更新PCB信息。

3、把进程的PCB移入相应的队列,如就绪、在某事件阻塞等队列。

4、选择另一个进程执行,并更新其PCB。

5、更新内存管理的数据结构。

6、恢复处理机上下文。

注:总而言之就是很耗资源

网络IO模型介绍

1、阻塞IO模型

应用程序调用一个 IO 函数,导致应用程序阻塞,等待数据准备好。 如果数据没有准备好,一直等待…数据准备好了,从内核拷贝到用户空间,IO 函数返回成功指示。

 

2. 非阻塞IO模型

把一个 SOCKET 接口设置为非阻塞就是告诉内核,当所请求的 I/O 操作无法完成时,不要将进程睡眠,而是返回一个错误。这样我们的 I/O 操作函数将不断的检查数据是否已经准备好,直到准备好为止。在这个不断检查的过程中,会大量的占用 CPU 的时间。上述模型绝不被推荐。

 

3. 异步IO模型

相对于同步IO,异步IO不是顺序执行。用户进程进行aio_read系统调用之后,无论内核数据是否准备好,都会直接返回给用户进程,然后用户态进程可以去做别的事情。等到socket数据准备好了,内核直接复制数据给进程,然后从内核向进程发送通知。IO两个阶段,进程都是非阻塞的。

Linux提供了AIO库函数实现异步,但是用的很少。目前有很多开源的异步IO库,例如libevent、libev、libuv。

 

4. 多路复用IO

由于同步非阻塞方式需要不断主动轮询,轮询占据了很大一部分过程,轮询会消耗大量的CPU时间,而 “后台” 可能有多个任务在同时进行,如果能将循环查询的多个任务只留任何一个任务来做这个事情就好了,这就是所谓的 “IO 多路复用”。

IO多路复用有两个特别的系统调用select、poll、epoll函数。select调用是内核级别的,select轮询相对非阻塞的轮询的区别在于---前者可以等待多个socket,能实现同时对多个IO端口进行监听,当其中任何一个socket的数据准好了,就能返回进行可读,然后进程再进行recvform系统调用,将数据由内核拷贝到用户进程,当然这个过程是阻塞的。select或poll调用之后,会阻塞进程,与blocking IO阻塞不同在于,此时的select不是等到socket数据全部到达再处理, 而是有了一部分数据就会调用用户进程来处理。如何知道有一部分数据到达了呢?监视的事情交给了内核,内核负责数据到达的处理。也可以理解为"非阻塞"吧。

对于多路复用,也就是轮询多个socket。多路复用既然可以处理多个IO,也就带来了新的问题,多个IO之间的顺序变得不确定了,当然也可以针对不同的编号。

在I/O编程过程中,当需要同时处理多个客户端接入请求时,可以利用多线程或者I/O多路复用技术进行处理。I/O多路复用技术通过把多个I/O的阻塞复用到同一个select的阻塞上,从而使得系统在单线程的情况下可以同时处理多个客户端请求。与传统的多线程/多进程模型比,I/O多路复用的最大优势是系统开销小,系统不需要创建新的额外进程或者线程,也不需要维护这些进程和线程的运行,降底了系统的维护工作量,节省了系统资源,I/O多路复用的主要应用场景如下:

1、服务器需要同时处理多个处于监听状态或者多个连接状态的套接字。

2、服务器需要同时处理多种网络协议的套接字。

此时你是不是想到的了redis如何做的啊,redis用的就是多路复用。

5. 信号驱动IO

简介:两次调用,两次返回;

首先我们允许套接口进行信号驱动 I/O,并安装一个信号处理函数,进程继续运行并不阻塞。当数据准备好时,进程会收到一个 SIGIO 信号,可以在信号处理函数中调用 I/O 操作函数处理数据。

 
 
1人点赞
 
Linux
 
 

与[转帖]Linux 6种网络IO模型相似的内容:

[转帖]Linux 6种网络IO模型

https://www.jianshu.com/p/c5aa9197ecf4 背景 大多数文件系统的默认 IO 操作都是缓存 IO,又被称作标准IO。在 Linux 的缓存 IO 机制中,操作系统会将 IO 的数据缓存在文件系统的页缓存(page cache )中,也就是说,数据会先被拷贝到操作系统

[转帖]Linux下的I/O复用与epoll详解

https://blog.csdn.net/weixin_39094034/article/details/110393127 前言 I/O多路复用有很多种实现。在linux上,2.4内核前主要是select和poll,自Linux 2.6内核正式引入epoll以来,epoll已经成为了目前实现高性

[转帖]sar -Linux 上全面的系统性能分析工具(2)

https://zhuanlan.zhihu.com/p/554619823 sar -b[ <时间间隔> [ <次数> ] ] 示例: sar -b 1 3 Linux 2.6.32-696.13.2.el6.x86_64 (upfor163) 2018年04月25日 _x86_64_ (2 CP

[转帖]Linux查看raid1和raid10分别由哪些盘组成,在哪个槽位

查找有问题的盘 MegaCli64 -PDList -aALL |grep "Firmware state" 6个盘,2个坏了 查看raid级别和硬盘的状态 MegaCli64 -ShowSummary -aALL|grep -i -E "RAID Level| State"|sort raid1,

[转帖]linux服务之tuned

https://www.cnblogs.com/createyuan/p/5701650.html RHEL/CentOS 在 6.3 版本以后引入了一套新的系统调优工具 tuned/tuned-adm,其中 tuned 是服务端程序,用来监控和收集系统各个组件的数据,并依据数据提供的信息动态调整系

[转帖]TNS-12535 TNS-00505的处理方法

硬件说明: 操作系统版本:ORACLE LINUX 6.3 64位 数据库版本:11.2.0.3 64位 问题说明: 在检查数据库的alert日志的时候,发现大量的12170和TNS-12535的错误; Fatal NI connect error 12170. VERSION INFORMATIO

[转帖]linux中内核的一个不错的参数somaxconn

最近发现很多内核优化参数都记不住了,写下文章来备记,方便以后查看. 编辑 /etc/sysctl.conf 文件,在里面加入如下内容:(有注释) #设置系统对最大跟踪的TCP连接数的限制(CentOS 5.6无此参数) net.ipv4.ip_conntrack_max = 25000000 #最大

[转帖]Linux命令之systemctl命令

一、systemctl命令简介 CentOS 5使用SysV init;CentOS 6使用Upstart,CentOS 7使用Systemd管理守护进程。centos7采用 systemd管理,服务独立的运行在内存中,服务响应速度快,但占用更多内存。独立服务的服务启动脚本都在目录 /usr/lib

[转帖]《Linux性能优化实战》笔记(二)—— CPU 上下文切换(上)

上一篇的最后一个例子,在多个进程竞争CPU时,我们看到每个进程实际上%usr部分只有20%多,70%多是在wait,但是load远远高于单个进程使用CPU达到100%。 这让我想到之前看的RWP公开课,里面有一篇连接池管理。为什么相同的业务量,起6千个连接(进程)远远要慢于200个连接,因为绝大多数

[转帖]arm linux下编译xtrabackup-2.4.5

环境:aarch64/centos7.6 glibc-2.17 编译器:gcc version 5.5.0 (GCC) 官方参考文档:https://www.percona.com/doc/percona-xtrabackup/2.4/installation/compiling_xtrabacku