本篇为转载,已经获得对方同意,原文出处
一、物理内存和虚拟内存
内存主要作用是在计算机运行时为操作系统和各种程序提供临时储存,操作系统的进程和进程之间是共享CPU和内存资源的。为了防止内存泄露需要一套完善且高效的内存管理机制。
一.什么是物理内存
可以理解为内存条中的空间
二.什么是虚拟内存
计算机可以将一部分硬盘空间作为虚拟内存使用,在需要的时候进行数据交换,加载到物理内存之中。
二、内核空间和用户空间
操作系统的核心是内核,可以访问受保护的内存空间,也有访问底层硬件设备的权限,为了避免用户进程直接操作内核,操作系统将虚拟内存划分为内核空间(Kernel-space)和 用户空间(User-space)
一.内核空间
内核空间总是驻留在内存中,它是为操作系统的内核保留的。应用程序是不允许直接在该区域进行读写或直接调用内核代码定义的函数的
二.用户空间
每个用户进程都有一个独立的用户空间,处于用户态的进程不能访问内核空间中的数据和调用内核函数 ,因此要进行系统调用的时候,就要将进程切换到内核态。
三、DMA传输原理和传统IO模式
一.DMA (Direct Memory Access,内存直接访问)
DMA (Direct Memory Access):DMA的意思是直接内存访问,它允许外围设备(硬件子系统)直接访问系统主内存。有了 DMA之后,系统主内存 与 硬盘或网卡之间的数据传输可以绕开 CPU 的全程调度,大大解放了CPU的劳动力
二.DMA IO流程
- 应用进程发起read命令, 调用CPU 读取数据,此时CPU会将用户进行从用户态切到内核态,程序线程一直阻塞等待数据的返回。
- CPU向 DMA 磁盘控制器发起调度指令。
- DMA 磁盘控制器向磁盘请求IO,将磁盘数据先放入磁盘控制器缓冲区,CPU 不参与此过程。
- 后续DMA收到完成指令, 将数据从磁盘控制器缓冲区拷贝到内核缓冲区。
- DMA 磁盘控制器向 CPU 发出数据读完的信号,由CPU 负责将数据从内核缓冲区拷贝到用户缓冲区。
- 最后切换回用户态,返回数据,解除阻塞, 程序继续往后执行。
DMA拷贝虽然一定程度解放了CPU,但是涉及到的内核切换次数和数据拷贝次数太多,依然不能让IO性能达到最优。
二.传统IO流程
- 用户进程向 发起 read操作,用户进程由用户态切换为内核态,然后一直阻塞等待数据的返回。
- CPU 在接收到指令以后对磁盘发起 I/O 请求,将磁盘数据先放入磁盘控制器缓冲区。
- 接下来由CPU将磁盘缓冲区中的数据拷贝到内核缓冲区,然后再从内核缓冲区拷贝到用户缓冲区。
- 用户进程由内核态切换回用户态,解除阻塞状态,程序继续执行。
四、零拷贝技术(降低CPU参与)
零拷贝(Zero-copy)技术指在计算机执行操作时,CPU 不需要先将数据从一个内存区域复制到另一个内存区域,从而可以减少上下文切换以及 CPU 的拷贝时间。
它的作用是在数据报从网络设备到用户程序空间传递的过程中,减少数据拷贝次数,减少系统调用,实现 CPU 的零参与,彻底消除 CPU 在这方面的负载
一.MMAP模式
使用 MMAP 的目的是将内核中缓冲区(read buffer)的地址与用户空间的缓冲区(user buffer)进行映射,
从而实现内核缓冲区与应用程序内存的共享,这样在进行网络传输时,就可以减少内核空间到用户空间的拷贝,大致流程如下:
内核读缓冲区(read buffer)仍需将数据拷贝到内核写缓冲区(socket buffer), 整个拷贝过程会发生 4 次内核切换,1 次 CPU 拷贝和 2 次 DMA 拷贝。
- 用户进程调用 mmap 函数,用户进程从用户态切到内核态
- 将用户进程的内核缓冲区与用户缓存区进行内存地址映射
- DMA 控制器将数据从主存或硬盘拷贝到内核缓冲区
- 上下文从内核态切回用户态mmap 系统调用结束
- 用户进程调用 write 函数,上下文从用户态切换为内核态
- CPU 将内核缓冲区的数据拷贝到网络缓冲区(SocketBuffer)
- CPU 利用 DMA 控制器将数据从网络缓冲区拷贝到网卡进行数据传输。
- 上下文从内核态切换回用户态,write 调用结束
MMAP的问题是 4次内核切换,3次数据拷贝,拷贝次数和切换次数依然很多。
二.Sendfile模式
Sendfile在Linux2.1被引入 ,Sendfile 系统调用的引入,不仅减少了 CPU 拷贝的次数,还减少了上下文切换的次数通。过 Sendfile 数据可以直接在内核空间内部进行 I/O 传输,也就是说数据直接通过内核缓冲区(Kernel Buffer)拷贝到Socket缓冲区(Socket Buffer), 数据根部不经过用户空间,对于用户来说数据是不可见的。