内核态可以执行任意命令,调用系统的一切资源,而用户态只能执行简单的运算,不能直接调用系统资源 。用户态必须通过系统接口(System Call),才能向内核发出指令 。
比如,当用户进程启动一个 bash 时,它会通过 getpid() 对内核的 pid 服务发起系统调用,获取当前用户进程的 ID 。
当用户进程通过 cat 命令查看主机配置时,它会对内核的文件子系统发起系统调用:
- 内核空间可以访问所有的 CPU 指令和所有的内存空间、I/O 空间和硬件设备 。
- 用户空间只能访问受限的资源,如果需要特殊权限,可以通过系统调用获取相应的资源 。
- 用户空间允许页面中断,而内核空间则不允许 。
- 内核空间和用户空间是针对线性地址空间的 。
- x86 CPU 中用户空间是 0-3G 的地址范围,内核空间是 3G-4G 的地址范围 。
- 所有内核进程(线程)共用一个地址空间,而用户进程都有各自的地址空间 。
文章插图
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 的全称叫直接内存存取(Direct Memory Access),是一种允许外围设备(硬件子系统)直接访问系统主内存的机制 。
也就是说,基于 DMA 访问方式,系统主内存于硬盘或网卡之间的数据传输可以绕开 CPU 的全程调度 。
目前大多数的硬件设备,包括磁盘控制器、网卡、显卡以及声卡等都支持 DMA 技术 。
整个数据传输操作在一个 DMA 控制器的控制下进行的 。CPU 除了在数据传输开始和结束时做一点处理外(开始和结束时候要做中断处理),在传输过程中 CPU 可以继续进行其他的工作 。
这样在大部分时间里,CPU 计算和 I/O 操作都处于并行操作,使整个计算机系统的效率大大提高 。
有了 DMA 磁盘控制器接管数据读写请求以后,CPU 从繁重的 I/O 操作中解脱,数据读取操作的流程如下:
- 用户进程向 CPU 发起 read 系统调用读取数据,由用户态切换为内核态,然后一直阻塞等待数据的返回 。
- CPU 在接收到指令以后对 DMA 磁盘控制器发起调度指令 。
- DMA 磁盘控制器对磁盘发起 I/O 请求,将磁盘数据先放入磁盘控制器缓冲区,CPU 全程不参与此过程 。
- 数据读取完成后,DMA 磁盘控制器会接受到磁盘的通知,将数据从磁盘控制器缓冲区拷贝到内核缓冲区 。
- DMA 磁盘控制器向 CPU 发出数据读完的信号,由 CPU 负责将数据从内核缓冲区拷贝到用户缓冲区 。
- 用户进程由内核态切换回用户态,解除阻塞状态,然后等待 CPU 的下一个执行时间钟 。
推荐阅读
- 淘宝从百万到千万级并发的14次服务端架构演进之路
- 几百万扔进水?买二手房千万避开这几类房源
- 分布式、高并发、多线程,这些概念还傻傻分不清吗?
- Java 并发编程:如何保证共享变量的原子性?
- 硬核!如何模拟 5w+ 的并发用户?
- 格鲁吉亚中国茶王刘峻周诞辰150周年之际获百万赔偿
- 安徽省科技厅强化科技支撑推进精准扶贫
- PHP导出百万条数据方法
- 重金寻人 , 你是我们要找的百万英雄吗 内含福利
- 带你深入了解高并发架构