支撑百万并发的“零拷贝”技术,你了解吗?( 三 )

  • 内存映射区域:例如将动态库,共享内存等虚拟空间的内存映射到物理空间的内存,一般是 mmap 函数所分配的虚拟内存空间 。
  • Linux 的内部层级结构
    内核态可以执行任意命令,调用系统的一切资源,而用户态只能执行简单的运算,不能直接调用系统资源 。用户态必须通过系统接口(System Call),才能向内核发出指令 。
     
     
    比如,当用户进程启动一个 bash 时,它会通过 getpid() 对内核的 pid 服务发起系统调用,获取当前用户进程的 ID 。
    当用户进程通过 cat 命令查看主机配置时,它会对内核的文件子系统发起系统调用:
    • 内核空间可以访问所有的 CPU 指令和所有的内存空间、I/O 空间和硬件设备 。
    • 用户空间只能访问受限的资源,如果需要特殊权限,可以通过系统调用获取相应的资源 。
    • 用户空间允许页面中断,而内核空间则不允许 。
    • 内核空间和用户空间是针对线性地址空间的 。
    • x86 CPU 中用户空间是 0-3G 的地址范围,内核空间是 3G-4G 的地址范围 。
    x86_64 CPU 用户空间地址范围为0x0000000000000000–0x00007fffffffffff,内核地址空间为 0xffff880000000000-最大地址 。
    • 所有内核进程(线程)共用一个地址空间,而用户进程都有各自的地址空间 。
    有了用户空间和内核空间的划分后,Linux 内部层级结构可以分为三部分,从最底层到最上层依次是硬件、内核空间和用户空间,如下图所示:
     
    支撑百万并发的“零拷贝”技术,你了解吗?

    文章插图
     
     
    Linux I/O 读写方式
    Linux 提供了轮询、I/O 中断以及 DMA 传输这 3 种磁盘与主存之间的数据传输机制 。其中轮询方式是基于死循环对 I/O 端口进行不断检测 。
    I/O 中断方式是指当数据到达时,磁盘主动向 CPU 发起中断请求,由 CPU 自身负责数据的传输过程 。
    DMA 传输则在 I/O 中断的基础上引入了 DMA 磁盘控制器,由 DMA 磁盘控制器负责数据的传输,降低了 I/O 中断操作对 CPU 资源的大量消耗 。
    I/O 中断原理
    在 DMA 技术出现之前,应用程序与磁盘之间的 I/O 操作都是通过 CPU 的中断完成的 。
     
     
    每次用户进程读取磁盘数据时,都需要 CPU 中断,然后发起 I/O 请求等待数据读取和拷贝完成,每次的 I/O 中断都导致 CPU 的上下文切换:
    • 用户进程向 CPU 发起 read 系统调用读取数据,由用户态切换为内核态,然后一直阻塞等待数据的返回 。
    • CPU 在接收到指令以后对磁盘发起 I/O 请求,将磁盘数据先放入磁盘控制器缓冲区 。
    • 数据准备完成以后,磁盘向 CPU 发起 I/O 中断 。
    • CPU 收到 I/O 中断以后将磁盘缓冲区中的数据拷贝到内核缓冲区,然后再从内核缓冲区拷贝到用户缓冲区 。
    • 用户进程由内核态切换回用户态,解除阻塞状态,然后等待 CPU 的下一个执行时间钟 。
    DMA 传输原理
    DMA 的全称叫直接内存存取(Direct Memory Access),是一种允许外围设备(硬件子系统)直接访问系统主内存的机制 。
    也就是说,基于 DMA 访问方式,系统主内存于硬盘或网卡之间的数据传输可以绕开 CPU 的全程调度 。
    目前大多数的硬件设备,包括磁盘控制器、网卡、显卡以及声卡等都支持 DMA 技术 。
     
     
    整个数据传输操作在一个 DMA 控制器的控制下进行的 。CPU 除了在数据传输开始和结束时做一点处理外(开始和结束时候要做中断处理),在传输过程中 CPU 可以继续进行其他的工作 。
    这样在大部分时间里,CPU 计算和 I/O 操作都处于并行操作,使整个计算机系统的效率大大提高 。
     
     
    有了 DMA 磁盘控制器接管数据读写请求以后,CPU 从繁重的 I/O 操作中解脱,数据读取操作的流程如下: