今天是母亲节,首先祝各位读者的母亲节日快乐,祝你们的母亲年轻健康。母亲节是一个亘古的话题,我本来想写个文章,但是想起来这周就一个周末,要花点时间陪下家人,昨天我们老大开会,特别说了,有时间多陪陪家人,我脑子一转,今天就一直陪着楠哥各种玩。

晚上回来看看笔记,写了这个技术文章,ioremap是一个属于被遗忘的技术知识点,可能我做Android 驱动没用上,也就疏忽了,像内核通知链一些冷门的技术,还偶尔用一下。


内存管理是一个经久不衰的话题,从段式管理到页式管理已经过去很久了,页式管理也已经有了好长好长时间了,使用Linux内核的操作系统已经从更新了很多不同的版本。

不同的CPU体系对外设IO端口物理地址的编址方式也不同,分为I/O映射方式(I/O-mapped)和内存映射方式(Memory-mapped)。

以X86为例:X86为外设专门实现有单独的地址空间,可以称为「I/O地址空间」或「I/O端口空间」,这个是独立与CPU和RAM物理地址空间,所有外设的IO端口均在这一空间。CPU通过设立专门的IN和OUT指令来访问这一空间中的地址单元(即I/O端口),这就是所谓的“I/O映射方式”(I/O-mapped)。和RAM物理地址空间相比,I/O地址空间通常都比较小,如x86 CPU的I/O空间就只有64KB(0-0xffff)。这是「I/O映射方式」的一个主要缺点,你可以通过cat /proc/ioports去查看,IO port空间的地址资源分配情况是以树状结构显示。这个源于x86平台的设计思想,目前基本不用了,获取这些资源的函数接口如request_region和ioremap。

像用户空间一样,内核也是通过页表访问内存,很多人对页表理解不是很透彻,你要是说他复杂也是非常复杂,但是你说要是简单也很简单,可以理解成一个图书的目录,有了这个目录,就可以知道什么内存地址存放了什么东西,以后要是想存新的东西进去,就在原来的目录表里面进行更新。

但是我们使用的外设,比如是一个光感传感器,我们需要控制这个光感传感器,那就需要读写这个光感传感器的I2C寄存器,如果内核代码需要像访问内存一样来访问这个光感设备呢?我们这时候就需要首先设置一个适当的内核页表映射

这时候我们就需要使用 ioremap()这个函数,经过这个函数还衍生了其他很多变种函数,我不知道为什么要用变种这个词,如果有其他词语可以留言一起讨论下,毕竟一次好的词语可以加深我们的印象。

具体可以看代码arch/arm/mm/ioremap.c 里面有很多相近似的函数。函数参数含义

// 功能:将物理地址映射为虚拟地址
// 参数1:需要映射的物理地址
// 参数2:需要映射的地址长度
// 返回值:该函数返回映射后的内核虚拟地址(3G-4G). 接着便可以通过读写该返回的内核虚拟地址去访问之这段I/O内存资源。

简单的实例代码

void led_on(void)
{void *reg_base;unsigned int temp; reg_base = ioremap(0x1212, 4);temp = __raw_readl(reg_base); temp &= ~(0xff<<12);temp |= (0x11<<12);__raw_writel(temp, reg_base);
}

#但是内核没几个地方用这个函数

我在内核里面搜了下,这个函数在内核里面并没有几个地方用到的。特别是我们最近做MTK方案和RK方案,里面的触摸屏驱动下面没使用到。但是音频platform部分却还有使用的地方。

用了一个新的转换方式

 /* ioremap to BT HW register base address */BTSYS_PKV_BASE_ADDRESS = (void *)btsys_pkv_physical_base;BTSYS_SRAM_BANK2_BASE_ADDRESS = (void *)btsys_sram_bank2_physical_base;bt_hw_REG_PACKET_R = BTSYS_PKV_BASE_ADDRESS + cvsd_mcu_read_offset;bt_hw_REG_PACKET_W = BTSYS_PKV_BASE_ADDRESS + cvsd_mcu_write_offset;bt_hw_REG_CONTROL = BTSYS_PKV_BASE_ADDRESS + cvsd_packet_indicator;pr_debug("[BTCVSD probe] BTSYS_PKV_BASE_ADDRESS = %p BTSYS_SRAM_BANK2_BASE_ADDRESS = %p\n",BTSYS_PKV_BASE_ADDRESS, BTSYS_SRAM_BANK2_BASE_ADDRESS);return snd_soc_register_platform(&pdev->dev, &mtk_btcvsd_rx_soc_platform);/*使用*/kal_int32 i;kal_uint16 pv;kal_uint8 *pSrc;kal_uint8 *pPacketBuf;unsigned long flags;unsigned long connsys_addr_rx, ap_addr_rx;LOGBT("%s(+) btsco.pRX->iPacket_w=%d\n", __func__, btsco.pRX->iPacket_w);connsys_addr_rx = *bt_hw_REG_PACKET_R;ap_addr_rx = (unsigned long)BTSYS_SRAM_BANK2_BASE_ADDRESS + (connsys_addr_rx & 0xFFFF);LOGBT("%s connsys_addr_rx=0x%lx,ap_addr_rx=0x%lx\n",__func__, connsys_addr_rx, ap_addr_rx);pSrc = (kal_uint8 *)ap_addr_rx;LOGBT("%s uPacketLength=%d,uPacketNumber=%d, btsco.uRXState=%d\n",__func__, uPacketLength, uPacketNumber, btsco.uRXState);AudDrv_BTCVSD_DataTransfer(BT_SCO_DIRECT_BT2ARM, pSrc, btsco.pRX->TempPacketBuf,uPacketLength, uPacketNumber, btsco.uRXState);LOGBT("%s AudDrv_BTCVSD_DataTransfer DONE!!!,uControl=0x%x,uLen=%d\n", __func__, uControl, uLen);

#查看系统当前的内存映射

/proc/iomem这个文件记录的是物理地址的分配情况,记得要查看需要使用root权限。这些地址范围是通过 requset_mem_region 函数申请得到的。

weiqifa0@weiqifa-System-Product-Name:~$ sudo cat /proc/iomem
[sudo] password for weiqifa0:
00000000-00000fff : Reserved
00001000-00057fff : System RAM
00058000-00058fff : Reserved
00059000-0009efff : System RAM
0009f000-000fffff : Reserved000a0000-000bffff : PCI Bus 0000:00000c0000-000cffff : Video ROM000f0000-000fffff : System ROM
00100000-b77eefff : System RAM
b77ef000-b7828fff : ACPI Tables
b7829000-b7bc9fff : System RAM
b7bca000-b7bcafff : ACPI Non-volatile Storage
b7bcb000-b7bcbfff : Reserved
b7bcc000-c492efff : System RAM
c492f000-c61b9fff : Reserved
c61ba000-c61cefff : ACPI Tables
c61cf000-c62ccfff : System RAM
c62cd000-c65f4fff : ACPI Non-volatile Storage
c65f5000-c7795fff : Reserved
c7796000-c77fefff : Unknown E820 type
c77ff000-c77fffff : System RAM
c7800000-c7ffffff : Reserved
c8000000-f7ffffff : PCI Bus 0000:00c8000000-c81fffff : PCI Bus 0000:05c8200000-c83fffff : PCI Bus 0000:05e0000000-efffffff : PCI Bus 0000:01e0000000-efffffff : 0000:01:00.0

ioports主要显示IO端口的地址范围,使用request_region( )分配I/O端口地址范围会显示在这里。

weiqifa0@weiqifa-System-Product-Name:~$ sudo cat /proc/ioports
0000-0cf7 : PCI Bus 0000:000000-001f : dma10020-0021 : pic10040-0043 : timer00050-0053 : timer10060-0060 : keyboard0064-0064 : keyboard0070-0077 : rtc00080-008f : dma page reg00a0-00a1 : pic200c0-00df : dma200f0-00ff : fpu00f0-00f0 : PNP0C04:000290-029f : pnp 00:0003f8-03ff : serial0680-069f : pnp 00:020800-087f : pnp 00:03
0cf8-0cff : PCI conf1
0d00-ffff : PCI Bus 0000:00164e-164f : pnp 00:021800-18fe : pnp 00:021800-1803 : ACPI PM1a_EVT_BLK1804-1805 : ACPI PM1a_CNT_BLK1808-180b : ACPI PM_TMR1850-1850 : ACPI PM2_CNT_BLK1854-1857 : pnp 00:051880-189f : ACPI GPE0_BLK2000-2fff : PCI Bus 0000:05d000-dfff : PCI Bus 0000:04d000-d0ff : 0000:04:00.0e000-efff : PCI Bus 0000:01e000-e0ff : 0000:01:00.0f000-f01f : 0000:00:1f.4f020-f03f : 0000:00:17.0f020-f03f : ahcif040-f043 : 0000:00:17.0f040-f043 : ahcif050-f057 : 0000:00:17.0f050-f057 : ahcife00-fefe : pnp 00:08ffff-ffff : pnp 00:02ffff-ffff : pnp 00:02ffff-ffff : pnp 00:02
weiqifa0@weiqifa-System-Product-Name:~$

#总结

ioremap 这些曾经用起来很不错,或者说是设计者设计的时候,觉得很不错的东西,现在突然被遗忘,我认为很大程度是因为设计的时候允许的地址范围太小,也就是因为太小,要加新的东西总是畏首畏尾。

回复「 篮球的大肚子」进入技术群聊

回复「1024」获取1000G学习资料

PS:想加入技术群的同学,加了我好友后,就给我发「篮球的大肚子」这句话,有可能机器人打瞌睡,可以多发几次,不要发与技术无关的消息或者推广。

Linux io内存存在的意义~相关推荐

  1. 【linux开发】IO端口和IO内存的区别及分别使用的函数接口

    IO端口和IO内存的区别及分别使用的函数接口 每个外设都是通过读写其寄存器来控制的.外设寄存器也称为I/O端口,通常包括:控制寄存器.状态寄存器和数据寄存器三大类.根据访问外设寄存器的不同方式,可以把 ...

  2. linux wc -l 对io,linux设备驱动归纳总结(五):2.操作硬件——IO内存

    linux设备驱动归纳总结(五):2.操作硬件--IO内存 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ...

  3. Linux系统IO端口,Linux系统对IO端口和IO内存的管理

    五.Linux下访问IO端口 对于某一既定的系统,它要么是独立编址.要么是统一编址,具体采用哪一种则取决于CPU的体系结构. 如,PowerPC.m68k等采用统一编址,而X86等则采用独立编址,存在 ...

  4. 基于Linux的内存模拟型的字符IO设备驱动程序的设计,并实现线程间通信

    要求:基于Linux的内存模拟型的字符IO设备驱动程序的设计,并编写应用程序实现线程间的通信. 基于Linux的内存模拟型的字符IO设备驱动程序的设计 1 内存模拟型的字符IO设备驱动程序memDrv ...

  5. 嵌入式linux+io+优化,嵌入式Linux系统内存优化使用方法研究

    [摘要] 嵌入式系统功能的提高,占用了较大内存空间,继而时常出现运行无响应.基于用户方面看,由于系统内存问题影响运行,针对系统内存与进程应用状态研究,可以调整系统数值与执行文件elf分析,进行系统优化 ...

  6. 浅析Linux IO

    点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试文章 来源:0xffffff.org/ 写在前面 在开始正式的讨论前,我 ...

  7. 深入剖析Linux IO原理和几种零拷贝机制的实现

    本文来说下Linux IO原理和几种零拷贝机制的实现 文章目录 概述 物理内存和虚拟内存 物理内存 虚拟内存 内核空间和用户空间 内核空间 用户空间 Linux的内部层级结构 Linux I/O读写方 ...

  8. Linux IO原理和零拷贝机制

    目录 1 概述 2 Linux I/O读写方式 2.1 I/O中断原理 2.2. DMA传输原理 2.3 传统I/O方式 3 零拷贝方式 3.1 用户态直接I/O 3.2 mmap + write 3 ...

  9. [linux]linux IO 5种方式

    1.几个重要概念 用户空间与内核空间: 现在操作系统都是采用虚拟存储器,那么对32位操作系统而言,它的寻址空间(虚拟存储空间)为4G(2的32次方).操作系统的核心是内核,独立于普通的应用程序,可以访 ...

最新文章

  1. ubuntu12.04 alternate win7 双系统安装
  2. Go语言,作为一门没有对象的OOP
  3. Python-Evoked地形图可视化
  4. Android开发--图形图像与动画(二)--Animation实现图像的 渐变 缩放 位移 旋转
  5. centos系统linux复制命令行,linux系统CentOS7中find命令使用
  6. pytorch分布式训练(一):torch.nn.DataParallel
  7. 第五章 列表、元组和字符串[DDT书本学习 小甲鱼]【2】
  8. HTML CSS 响应式-菜单
  9. springcloud(十):服务网关zuul初级篇
  10. python blp模型 估计_随机系数Logit模型及Stata实现
  11. 【安全测试工具】Drozer介绍及使用
  12. 精读《磁贴布局 - 功能分析》
  13. 电脑城最简单骗局,仍然有无数人上当
  14. RC滤波分析计算——信号与系统
  15. 正圆锥体空间方程_科学解读:什么是时间?什么是空间?理论上时空是什么?...
  16. Oracle数据库原理
  17. c语言函数变量地址符,C语言中取地址符做函数形参?—— 引用的讨论
  18. STM32 中断向量表的位置 、重定向
  19. vue 传参获取数据
  20. 用Python做兼职是如何挣钱的?

热门文章

  1. hive求差集和交集
  2. JavaScript动画知多少?
  3. 【字符串问题】求一个字符串中重复出现的最长的子串
  4. MSBuild编译扩展
  5. 书籍推荐-记这几年看的书
  6. 第一二三范式的简单理解
  7. 清华大学《操作系统》(二十三):I/O子系统
  8. Python 之 Python2 和 Python3 的区别
  9. python安装环境傻瓜式安装_前后端分离——前端开发环境傻瓜式一步到位 nodejs ruby python nginx 安装搭建配置...
  10. Day04-循环和列表