Linux 驱动内存子系统核心知识精要(纯干货版)
2026/8/4 15:31:59 网站建设 项目流程

Linux 驱动内存子系统核心知识精要(纯干货版)

一、 内存分配策略标志:GFP_KERNEL vs GFP_ATOMIC

核心区别:是否允许睡眠(Can Block)。

标志行为使用场景内存来源
GFP_KERNEL允许睡眠。分配器会主动回收内存或交换页,进程阻塞直到分配成功。进程上下文proberead/writeioctl、工作队列(workqueue)。常规内存池 + Swap 交换区。
GFP_ATOMIC绝不睡眠。若内存不足,立即返回NULL原子上下文:中断顶/底半部(Tasklet)、自旋锁临界区、定时器回调。系统预留的紧急内存池(Emergency Pool),容量极小。

致命错误:在持有自旋锁或中断上下文中使用GFP_KERNEL,会触发BUG: scheduling while atomic,导致内核 Panic。


二、 内存分配函数:kmalloc vs vmalloc

核心区别:物理内存的连续性及虚拟地址映射方式(依赖 MMU)。

特性kmalloc (kzalloc)vmalloc
物理地址连续(伙伴系统分配)。不连续(离散物理页框拼接)。
虚拟地址直接映射区(线性偏移),转换快。动态映射区(非线性),需更新多级页表,TLB 命中率低,开销大。
最大分配量较小(受限于伙伴系统,单次通常 < 4MB)。较大(可达数百 MB)。
硬件 DMA适合(外设需要物理连续地址)。不适合(物理地址分散,DMA 无法寻址)。

实战原则:自定义结构体(如ds18b20)用kzalloc;加载大模块或帧缓冲(Framebuffer)用vmalloc


三、 硬件基石:MMU(内存管理单元)

核心使命:将程序使用的虚拟地址(VA)实时翻译为物理内存条的物理地址(PA)

  1. 页表翻译:以 4KB 为页粒度查找页表。若页表无映射,触发Unable to handle kernel paging request崩溃。
  2. 权限隔离(Ring 0 / Ring 3):页表中包含 R/W 和 User/Supervisor 权限位。用户态访问内核空间地址,MMU 直接触发权限异常。
  3. TLB 与 Cache 一致性陷阱
    • 现象:CPU 从 Cache 取旧数据,而 DMA 外设已更新物理内存。
    • 对策:操作 DMA 缓冲区前后必须调用dma_map_singledma_sync_single_for_cpu刷新 Cache/MMU 缓存。

四、 权限隔离:内核空间 vs 用户空间

CPU 特权级:内核空间(Ring 0,执行所有指令) vs 用户空间(Ring 3,禁止特权指令)。

地址视野(32位系统示例)

  • 用户空间0x0000 0000 ~ 0xC000 0000(3GB),每个进程独立
  • 内核空间0xC000 0000 ~ 0xFFFFFFFF(1GB),所有进程共享

数据交互绝对法则(摆渡函数)
驱动禁止直接memcpy用户态指针,必须使用专用 API:

  • copy_from_user(void *to, const void __user *from, unsigned long n)
  • copy_to_user(void __user *to, const void *from, unsigned long n)

中断上下文禁令copy_from_user内部可能因缺页异常而睡眠(等待磁盘 IO),绝不允许在中断上下文调用


五、 零拷贝进阶:mmap 内存映射

核心机制:在用户态虚拟地址和内核态物理内存之间建立直接映射,零拷贝(Zero-Copy),适合传输 >4KB 的大数据。

驱动侧实现模板

staticintmy_mmap(structfile*filp,structvm_area_struct*vma){// 1. 获取物理页框号(PFN)unsignedlongpfn=virt_to_phys(ds18b20->buffer)>>PAGE_SHIFT;// 2. 设置 Cache 属性(必须明确指定)vma->vm_page_prot=pgprot_noncached(vma->vm_page_prot);// 3. 核心映射 API(修改 MMU 页表)if(remap_pfn_range(vma,vma->vm_start,pfn,vma->vm_end-vma->vm_start,vma->vm_page_prot)){return-EAGAIN;}return0;}

Cache 属性抉择(面试高频)

  • pgprot_noncached:直达物理内存。适合硬件寄存器、DMA 共享内存(保证实时一致性,速度最慢)。
  • pgprot_writecombine:读直达,写合并。适合 Framebuffer 显存
  • 默认(缓存):适合纯软件数据传输。

copy_from_user的对决

维度copy_from_usermmap
拷贝次数2 次(硬件→内核→用户)0 次
适用数据量< 1KB(控制指令、配置参数)> 4KB(视频流、大量采样数据)
风险等级低(内核全程校验)高(用户直接操作物理内存)

mmap 两大致命陷阱

  1. 越界映射:APP 传入的len大于驱动实际分配的内存,remap_pfn_range会映射到非法物理内存。解法:检查vma->vm_end - vma->vm_start,超出返回-EINVAL
  2. 释放后访问(Use-After-Free):驱动removekfree了内存,但 APP 未调用munmap。APP 再次读写时触发Unable to handle kernel paging request解法:在驱动的release函数中遍历 VMA 强制解除映射(zap_vma_ptes)。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询