news 2026/2/6 21:44:48

[Linux外设驱动详解]7. 内存管理与 I/O 访问

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
[Linux外设驱动详解]7. 内存管理与 I/O 访问

7. 内存管理与 I/O 访问

基于 Linux 内核源码分析 | 硬件平台:瑞芯微 RK3588 (ARM64)


目录

  • 7.1 ioremap / iounmap
  • 7.2 readl/writel 等寄存器访问宏
  • 7.3 DMA 缓冲区分配
  • 7.4 内存屏障简介

7.1 ioremap / iounmap

7.1.1 概述

在 Linux 驱动开发中,硬件设备的寄存器通常位于物理地址空间。内核代码使用的是虚拟地址,因此需要一种机制将物理地址映射到内核虚拟地址空间。ioremap就是为此而设计的接口。

核心源码位置:

  • ARM64 架构实现:kernel/arch/arm64/mm/ioremap.c
  • 通用页表映射:kernel/mm/ioremap.c
  • 接口定义:kernel/arch/arm64/include/asm/io.h

7.1.2 ioremap 映射流程

地址无效

有效

是 RAM

非 RAM

失败

成功

驱动调用 ioremap

ioremap phys_addr size

__ioremap_caller
设置 PROT_DEVICE_nGnRE 属性

参数检查

返回 NULL

页对齐处理

是否为 RAM 区域?

返回 NULL
禁止映射 RAM

get_vm_area_caller
分配虚拟地址空间

ioremap_page_range
建立页表映射

映射成功?

vunmap 释放资源

返回虚拟地址

7.1.3 核心实现分析

__ioremap_caller 函数

源码位置:kernel/arch/arm64/mm/ioremap.c:21-63

staticvoid__iomem*__ioremap_caller(phys_addr_tphys_addr,size_tsize,pgprot_tprot,void*caller){unsignedlonglast_addr;unsignedlongoffset=phys_addr&~PAGE_MASK;interr;unsignedlongaddr;structvm_struct*area;/* 1. 页对齐处理 */phys_addr&=PAGE_MASK;size=PAGE_ALIGN(size+offset);/* 2. 检查地址范围有效性 */last_addr=phys_addr+size-1;if(!size||last_addr<phys_addr||(last_addr&~PHYS_MASK))returnNULL;/* 3. 禁止映射 RAM 区域 */if(WARN_ON(pfn_valid(__phys_to_pfn(phys_addr))))returnNULL;/* 4. 分配内核虚拟地址空间 */area=get_vm_area_caller(size,VM_IOREMAP,caller);if(!area)returnNULL;addr=(unsignedlong)area->addr;area->phys_addr=phys_addr;/* 5. 建立页表映射 */err=ioremap_page_range(addr,addr+size,phys_addr,prot);if(err){vunmap((void*)addr);returnNULL;}/* 6. 返回带偏移的虚拟地址 */return(void__iomem*)(offset+addr);}
ioremap_page_range 页表建立

源码位置:kernel/mm/ioremap.c:222-250

页表层级遍历:

PGD (Page Global Directory) ↓ P4D (Page 4th Directory) ↓ PUD (Page Upper Directory) ↓ PMD (Page Middle Directory) ↓ PTE (Page Table Entry) → 物理页面

支持巨页映射优化:

页表级别映射粒度条件
P4D 级别512GB地址和大小都要 512GB 对齐
PUD 级别1GB地址和大小都要 1GB 对齐
PMD 级别2MB地址和大小都要 2MB 对齐
PTE 级别4KB常规页面映射

7.1.4 内存类型属性

源码位置:kernel/arch/arm64/include/asm/pgtable-prot.h:55-60

ARM64 定义了多种设备内存属性:

/* 设备内存属性 - 不可缓存 */#definePROT_DEVICE_nGnRnE/* non-Gathering, non-Reordering, No Early acknowledge */#definePROT_DEVICE_nGnRE/* non-Gathering, non-Reordering, Early acknowledge *//* 正常内存属性 */#definePROT_NORMAL_NC/* Normal Non-Cacheable */#definePROT_NORMAL/* Normal Cacheable */
属性缩写含义说明
nGnon-Gathering读写操作不会合并
nRnon-Reordering读写操作不会重排序
RnERead No Early读操作不提前返回
REEarly写操作可提前返回确认
NCNon-Cacheable不使用缓存

常用 ioremap 变体:

/* 标准 ioremap - 设备内存,不可缓存 */void__iomem*ioremap(phys_addr_taddr,size_tsize);/* 写合并模式 - 正常非缓存内存 */void__iomem*ioremap_wc(phys_addr_taddr,size_tsize);/* 可缓存模式 - 用于正常 RAM 区域 */void__iomem*ioremap_cache(phys_addr_taddr,size_tsize);/* PCI 配置空间 - nGnRnE 属性 */void__iomem*pci_remap_cfgspace(phys_addr_taddr,size_tsize);

7.1.5 iounmap 解除映射

源码位置:kernel/arch/arm64/mm/ioremap.c:72-83

voidiounmap(volatilevoid__iomem*io_addr){unsignedlongaddr=(unsignedlong)io_addr&PAGE_MASK;/* * 某些情况下(如 ioremap_cache 复用 RAM 映射), * 地址可能不在 vmalloc 范围内,需要检查。 */if(is_vmalloc_addr((void*)addr))vunmap((void*)addr);}

7.1.6 使用示例

/* 假设 RK3588 GPIO 控制器物理基址为 0xFD820000 */#defineGPIO_BASE_PHYS0xFD820000void__iomem*gpio_base;/* 1. 映射设备寄存器 */gpio_base=ioremap(GPIO_BASE_PHYS,0x1000);if(!gpio_base){pr_err("Failed to ioremap GPIO registers\n");return-ENOMEM;}/* 2. 访问寄存器 */u32 value=
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/2/4 7:13:20

小米运动智能刷步神器:轻松同步微信支付宝步数全攻略

小米运动智能刷步神器&#xff1a;轻松同步微信支付宝步数全攻略 【免费下载链接】mimotion 小米运动刷步数&#xff08;微信支付宝&#xff09;支持邮箱登录 项目地址: https://gitcode.com/gh_mirrors/mimo/mimotion 还在为每天运动步数太少而发愁吗&#xff1f;想不想…

作者头像 李华
网站建设 2026/2/5 6:43:16

揭秘n8n自动化工作流:从效率瓶颈到智能决策的思维跃迁

揭秘n8n自动化工作流&#xff1a;从效率瓶颈到智能决策的思维跃迁 【免费下载链接】n8n n8n 是一个工作流自动化平台&#xff0c;它结合了代码的灵活性和无代码的高效性。支持 400 集成、原生 AI 功能以及公平开源许可&#xff0c;n8n 能让你在完全掌控数据和部署的前提下&…

作者头像 李华
网站建设 2026/2/6 14:30:02

终极指南:WenQuanYi Micro Hei轻量级中文字体的完整配置方案

终极指南&#xff1a;WenQuanYi Micro Hei轻量级中文字体的完整配置方案 【免费下载链接】fonts-wqy-microhei Debian package for WenQuanYi Micro Hei (mirror of https://anonscm.debian.org/git/pkg-fonts/fonts-wqy-microhei.git) 项目地址: https://gitcode.com/gh_mir…

作者头像 李华
网站建设 2026/2/4 8:15:03

AO3镜像站完整部署方案:如何构建稳定的访问通道

AO3镜像站完整部署方案&#xff1a;如何构建稳定的访问通道 【免费下载链接】AO3-Mirror-Site 项目地址: https://gitcode.com/gh_mirrors/ao/AO3-Mirror-Site 当你发现AO3原站无法访问时&#xff0c;这个开源镜像站项目提供了完整的技术解决方案。通过智能同步机制&am…

作者头像 李华
网站建设 2026/2/6 17:06:18

51单片机串口通信程序详解

51单片机串口通信程序源码&#xff0c;注释详细&#xff0c;包含接收和传输代码&#xff0c;以及文档说明在51单片机的应用中&#xff0c;串口通信是非常重要的功能&#xff0c;它可以实现单片机与其他设备的数据交互。今天就来详细剖析一下51单片机串口通信的程序源码&#xf…

作者头像 李华
网站建设 2026/2/4 8:03:18

开发基于大模型的金融专业教学案例动态生成器

开发基于大模型的金融专业教学案例动态生成器关键词&#xff1a;大模型、金融专业教学案例、动态生成器、自然语言处理、人工智能教育应用摘要&#xff1a;本文聚焦于开发基于大模型的金融专业教学案例动态生成器。首先介绍了该项目的背景&#xff0c;包括目的、预期读者、文档…

作者头像 李华