概述
IO总结
所谓的I/O就是输入(Input)和输出(Output),也可以理解为读(Read)和写(Write);
1.用户空间和内核空间
目的:为了保证内核的安全
由操作系统将虚拟地址空间划分为两部分,一部分为内核空间,另一部分为用户空间。针对 Linux 操作系统而言,最高的 1G 字节(从虚拟地址 0xC0000000 到 0xFFFFFFFF)由内核使用,称为内核空间。而较低的 3G 字节(从虚拟地址 0x00000000 到 0xBFFFFFFF)由各个进程使用,称为用户空间
如图:
当进程运行在内核空间时,它就处于内核态;当进程运行在用户空间时,它就处于用户态。
当我们需要进行 IO 操作时,如读写硬盘文件、读写网卡数据等,进程需要切换到内核态,否则无法进行这样的操作,无论是从内核态切换到用户态,还是从用户态切换到内核态,都需要进行一次上下文的切换。一般情况下,应用不能直接操作内核空间的数据,需要把内核态的数据拷贝到用户空间才能操作。
IO 示例
假如有一个网络请求想访问服务器上的某个静态文件,我们来看一下在这个示例中服务器的具体 IO 流程。
整个过程如下:
- 进程发起一个系统调用 sys_read,读取磁盘的文件;
- DMA 将磁盘文件数据拷贝到内核空间的 read 缓冲区;
- CPU 把内核空间 read 缓冲区数据拷贝到用户空间的缓冲区;
- 进程发起一个系统调用 socket_write,向网卡写数据;
- CPU 把用户空间缓冲区的数据拷贝到内核空间的 socket 缓冲区;
- 最后 DMA 把内核空间的 socket 缓冲区数据拷贝到网卡;
可以看到,在整个过程中进行了四次的数据拷贝,而且也进行了四次的上下文切换。这种 IO 操作的效率是比较低的,因为进行了多次数据拷贝,如果希望提高 IO 效率,可以减少其中的数据拷贝,零拷贝技术就是为了减少 IO 操作过程中的数据拷贝次数。
2.PIO和MDA
-
PIO的英文拼写是“Programming Input/Output Model”,PIO模式是一种通过CPU执行I/O端口指令来进行数据的读写的数据交换模式。是最早先的硬盘数据传输模式,数据传输速率低下,CPU占有率也很高,大量传输数据时会因为占用过多的CPU资源而导致系统停顿,无法进行其它的操作。
-
DMA的英文拼写是“Direct Memory Access”,汉语的意思就是直接内存访问,是一种不经过CPU而直接从内存了存取数据的数据交换模式。PIO模式下硬盘和内存之间的数据传输是由CPU来控制的;而在DMA模式下,CPU只须向DMA控制器下达指令,让DMA控制器来处理数的传送,数据传送完毕再把信息反馈给CPU,这样就很大程度上减轻了CPU资源占有率。
3.缓存io和直接io
缓存IO:数据从磁盘先通过DMA模式拷贝到内核空间高速缓存页,再从高速缓存页通过cpu拷贝到用户空间应用缓存
直接IO:数据从磁盘通过DMA模式拷贝到用户空间应用缓存
缓存io:
应用:nginx、tomcat、redis等
缓存I/O被称作为标准I/O,大多数文件系统的默认I/O操作都是缓存I/O
- 读操作:
操作系统检查内核空间的高速缓存页是否命中,命中直接返回;否则从物理磁盘中读取,然后load到内核缓存中
- 写操作:
进程调用SystemCall函数将用户空间应用缓存数据通过DMA的方式拷贝到内核空间高速页缓存
update系统守护进程会周期性地(一般每隔30秒)调用sync函数,定期冲洗内核块缓冲区数据写入磁盘。
同时调用系统提供write函数立刻返回,等待flusher内核线程空闲时将数据写入磁盘。
进程调用systemCall函数将用户空间应用缓存数据通过dma的方式拷贝到内核空间高速页缓存,同时掉用系统提供fsync函数将用户空间缓存的数据写入磁盘。
- 缓存I/O的优点:
分离了内核空间和用户空间,保护系统本身的运行安全,避免应用程序异常导致系统崩溃
减少缓存与磁盘的I/O磁盘,提升数据读取和写入的性能
- 缓存I/O的缺点:
数据传输过程中需要在应用程序地址空间(用户空间)和缓存(内核空间)之间进行多次数据拷贝操作,这些拷贝操作会给CPU以及内存带来一
直接io:
应用代表:mysql
直接IO就是应用程序直接访问磁盘数据,而不经过内核缓冲区,也就是绕过内核缓冲区,自己管理I/O缓存区,这样做的目的是减少一次从内核缓冲区到用户程序缓存的数据复制,Linux系统提供open()函数在调用时增加O_DIRECT参数选项,用它打开的文件便可以绕过内核缓冲区完成直接访问,这样便有效避免了CPU和内存的多余时间开销
- 引入内核缓冲区的目的在于提高磁盘文件的访问性能,因为当进程需要读取磁盘文件时,如果文件内容已经在内核缓冲区中,那么就不需要再次访问磁盘;而当进程需要向文件中写入数据时,实际上只是写到了内核缓冲区便告诉进程已经写成功,而真正写入磁盘是通过一定的策略进行延迟的。然而,对于一些较复杂的应用,比如数据库服务器,它们为了充分提高性能,希望绕过内核缓冲区,由自己在用户态空间实现并管理I/O缓冲区,包括缓存机制和写延迟机制等,以支持独特的查询机制,比如数据库可以根据更加合理的策略来提高查询缓存命中率。另一方面,绕过内核缓冲区也可以减少系统内存的开销,因为内核缓冲区本身就在使用系统内存。
- 应用程序直接访问磁盘数据,不经过操作系统内核数据缓冲区,这样做的目的是减少一次从内核缓冲区到用户程序缓存的数据复制。这种方式通常是在对数据的缓存管理由应用程序实现的数据库管理系统中。
直接I/O的缺点就是如果访问的数据不在应用程序缓存中,那么每次数据都会直接从磁盘进行加载,这种直接加载会非常缓慢。通常直接I/O跟异步I/O结合使用会得到较好的性能。
4.网络io 和磁盘io
磁盘io:
具体步骤:
当应用程序调用read接口时,操作系统检查内核缓冲区中是否存在需要的数据,如果存在,就直接从内核缓存中直接返回,否则从磁盘中读取,然后缓存至操作系统的缓存中。
当应用程序调用write接口时,将数据直接从用户地址空间复制到内核地址空间的缓存中,这时对用户程序来说,写操作已经完成了,至于什么时候写入磁盘中,由操作系统决定,除非显示调用sync同步命令。
网络io:
1、当调用系统read接口时,通过DMA(Direct Memory Access)将数据拷贝到内核缓冲区;
2、然后由CPU控制,将内核缓冲区的数据拷贝到用户模式的buffer中;
3、当调用系统write接口时,会把用户模式下buffer数据拷贝到内核缓冲区的Socket Buffer中;
4、最后通过DMA copy将内核模式下的socket buffer中数据拷贝到网卡设备中传输。
从上面整个read、write过程来看,数据白白从内核模式到用户模式走了一圈,浪费了两次copy,而这两次有需要CPU copy,即占用CPU资源。
这位大佬总结得比较详细:https://blog.csdn.net/qq_37555071/article/details/113932533
最后
以上就是缓慢酸奶为你收集整理的IO简单总结的全部内容,希望文章能够帮你解决IO简单总结所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复