LinuxGod

LinuxGod.net
Linux大神网——精选每一篇高品质的技术干货
  1. 首页
  2. 开源快讯
  3. 正文

3.3.mmap完成物理地址映射到用户虚拟地址空间上文件对应硬件外设

2022年12月4日 516点热度

3.3.mmap地址映射方法

明确:mmap就是完成物理地址映射到用户虚拟地址用的

明确:用户3G虚拟地址空间划分:

0x00000000-------------------------------------------------------0xBFFFFFFF

代码段 数据段 BSS段 堆区 MMAP虚拟内存区 栈区

---->

1.回顾mmap系统调用函数

函数原型:

void *mmap(void *addr, size_t length,

int prot, int flags,

int fd, off_t offset);

函数功能:将物理地址空间映射到用户虚拟内存空间上

将物理地址映射到用户虚拟地址

老王课程这么讲:将文件映射到用户虚拟地址空间上

文件对应硬件外设,外设通过物理地址访问

linux系统不允许访问物理地址,利用mmap映射不得了

参数:

addr:给NULLlinux 驱动通知应用层,让linux内核帮你在用户虚拟内存区域找一块

空间内存用来映射物理地址

length:让linux内核帮你找的空闲用户虚拟内存的大小

切记:大小必须是页面大小(4KB)的整数倍

prot:描述内核帮你找的空闲用户虚拟内存的访问权限

一般指定为:PROT_READ|PROT_WRITE

flags:其余属性,一般指定为:MAP_SHARED

fd:硬件外设

linux 驱动通知应用层_开发linux应用--用gtk+和gdk开发linux图形用_dz全站弹出层通知

offset:偏移量,一般给0

返回值:linux内核将空闲的用户虚拟内存的首地址进行返回

这个起始用户虚拟地址同样也是4KB整数倍

参考代码:

void *addr;

int fd = open("a.txt", O_RDWR);

addr = mmap(NULL, 0x1000, PROT_READ|PROT_WRITE,

MAP_SHARED, fd, 0);

说明:将文件a.txt映射到以addr起始的用户虚拟内存上

将来访问映射的用户虚拟内存就是访问文件

//向映射的用户虚拟内存拷贝字符串数据

本质是向文件a.txt写入数据

memcpy(addr, "hello,world", 12);

2.了解mmap系统调用函数所做的工作:

2.1.应用程序调用mmap,首先跑到C库的mmap函数定义

2.2.C库的mmap函数作两件事:

1.保存mmap系统调用号到r7寄存器

2.调用swi/svc指令触发软中断异常

2.3.一旦触发软中断异常,CPU核立马处理软中断异常

2.4.最后进程跑到内核空间继续运行,跑到软中断异常的入口地址

运行,做如下事情:

1.调用软中断异常处理函数,而此函数做两件事:

1.从r7寄存器中取出mmap系统调用号

2.以mmap系统调用号为下标在内核的系统调用表中

找到mmap对应的内核函数sys_mmap,而内核的

sys_mmap做三件事:

1.内核的sys_mmap首先在当前进程的3G虚拟地址空间中

找一块空闲的用户虚拟内存,将来用于和物理地址

做映射

2.一旦找到空闲的用户虚拟内存,并且用户mmap本身

也给用户虚拟内存指定了一堆的属性(大小,权限等)

所以内核用struct vm_area_struct数据结构定义

初始化一个对象来描述空闲的用户虚拟内存的属性

struct vm_area_struct {

unsigned long vm_start; //空间用户虚拟内存的起始地址

//等于mmap的返回值addr

unsigned long vm_end; //结束地址=vm_start+大小

pgprot_t vm_page_prot; //等于mmap传递的PROT_READ|PROT_READ|PROT_WRITE

unsigned long vm_flags; //等于mmap传递的MAP_SHARED

unsigned long vm_pgoff; //等于mmap传递的0

...

};

3.最后内核的sys_mmap调用底层驱动的mmap接口

并且内核sys_mmap将第2步创建的对象的地址

也传递给底层驱动的mmap接口

3.底层驱动mmap执行完毕,进程返回,至此mmap调用结束

3.对应的底层驱动的mmap接口

struct file_operations {

int (*mmap) (struct file *file,

struct vm_area_struct *vma);

dz全站弹出层通知_linux 驱动通知应用层_开发linux应用--用gtk+和gdk开发linux图形用

};

接口功能:永远只能唯一做一件事:将已知的物理地址和已知的

用户虚拟地址做映射,类似:媒婆

由于用户虚拟地址在用户空间,所以将来访问操作

都是在应用程序完成,而不是在内核驱动完成

访问映射的用户虚拟地址就是在访问物理地址

file:跟fd亲戚关系

vma:指向内核sys_mmap创建的一个对象,此对象来描述空闲的

用户虚拟内存的各种属性,将来底层驱动mmap接口利用

此指针可以获取到用户虚拟内存的属性:

vma->vm_start //获取起始用户虚拟地址

vma->vm_end

vma->vm_flags

vma->vm_page_prot

...

问:底层驱动的mmap接口到底如何最终完成映射呢?

因为已知物理地址可以看手册获取到

已知的用户虚拟地址通过vma指针能够获取到

如何将两者关联在一起呢?

万事俱备只欠东风

答:只需调用以下函数完成关联映射:

int remap_pfn_range(struct vm_area_struct *vma,

unsigned long addr,

unsigned long pfn,

unsigned long size,

linux 驱动通知应用层_dz全站弹出层通知_开发linux应用--用gtk+和gdk开发linux图形用

pgprot_t prot);

函数功能:完成最终的地址映射

vma:传递内核sys_mmap创建的对象地址

也就是传递驱动mmap接口的第二个参数

addr:传递空闲的用户虚拟内存的首地址

也就是传递vma->vm_start

pfn:传递起始的物理地址>>12

切记:此物理地址大小必须是4KB(0x1000)整数倍

例如:

0xC001C000>>12:合法

0xC001C004>>12:不合法

size:传递映射的用户虚拟内存的大小

也就是传递:vma->vm_end - vma->vm_start

prot:传递用户虚拟内存的访问权限

也就是传递:vma->vm_page_prot

案例:利用mmap实现开关灯操作

参考代码:day09/1.0

dz全站弹出层通知_开发linux应用--用gtk+和gdk开发linux图形用_linux 驱动通知应用层

linux 驱动通知应用层_开发linux应用--用gtk+和gdk开发linux图形用_dz全站弹出层通知

linux 驱动通知应用层_dz全站弹出层通知_开发linux应用--用gtk+和gdk开发linux图形用

4.世纪大PK:read,write,ioctl和mmap对比

什么时候用:read,write,ioctl

什么时候用: mmap

4.1.read,write,ioctl数据操作流程

对设备读操作:read,ioctl

开发linux应用--用gtk+和gdk开发linux图形用_linux 驱动通知应用层_dz全站弹出层通知

数据流:硬件寄存器----->内核缓冲区------->用户缓冲区

gpio_get_value copy_to_user

对设备写操作:write,ioctl

数据流:用户缓冲区----->内核缓冲区------->硬件寄存器

copy_from_user gpio_set_value

结论:read,writelinux 驱动通知应用层,ioctl数据操作势必要经过两次数据拷贝:

用户-内核->硬件

硬件->内核->用户

4.2.mmap数据操作流程:

对设备读操作: 应用程序直接以指针形式读取寄存器

data = *gpiocout;

对设备写操作: 应用程序直接以指针的形式写入寄存器

*gpiocout &= ~(1 硬件

硬件->用户

4.3.终极结论:

1.如果用户对硬件操作访问的数据量比较小,read,write,ioctl

的两次数据拷贝对系统性能肯定有影响,但是这种影响几乎

可以忽略不计,如果操作的数据量比较大,两次数据拷贝

性能的影响是致命的,例如:摄像头linux更改ip地址,LCD显示屏,声卡等

2.如果访问操作的数据量比较大linux 发邮件,用read,write,ioctl势必

影响系统的性能,务必采用mmap,将两次数据拷贝变成一次

提供系统的性能效率

3.由于mmap在使用的时候,分配的用户虚拟内存必须是4KB的

整数倍,如果操作的数据量比较小,此时还用mmap

即使提高了系统的性能(几乎体会不到),反而是浪费了

宝贵的内存资源

本作品采用 知识共享署名 4.0 国际许可协议 进行许可
标签: mmap 内存映射 对象关系映射 空间数据 虚拟内存
最后更新:2022年12月4日

Linux大神网

每日更新,欢迎收藏♥ 不积跬步无以至千里,加油,共勉。

点赞
< 上一篇
下一篇 >

Linux大神网

每日更新,欢迎收藏♥
不积跬步无以至千里,加油,共勉。

最新 热点 随机
最新 热点 随机
C语言教程之linuxC编程实战:linux电子书 #Ubuntu查看防火墙的状态#添加开放普通端口开放22:开启完成 Ubuntu18.04上安装GCC编译器通过终端执行以下命令命令 2019年Linux操作系统启动流程介绍-苏州安亲宝 如何安装Windows10下的WSL和mkfontdir命令? 获取内核源码:阅读linux内核设计的艺术 如何操作Linux启动盘?的安装目录信息详解 (多图预警)多篇Linux(centos7)安装流程 Ubuntu22.04最终发布最终RC版本号召大家积极进行进行测试 如何在Linux安装字体中用到各种命令如mkfontscale? 自带几个预设,你可以在Numix、Arc或Materia主题样式上创建自己的GTK主题 (架构)为什么要在Linux下写C++程序? Ubuntu中各种类型频繁发生的更新错误以及修复方法 图1.3编程的7个步骤,你知道吗? 虚拟机Linux安装教程及安装流程介绍-苏州安嘉 常用且流行的Linuxshell脚本编写工具:/Vim编辑器 Linux下统计C语言程序执行时间的几种常用方法 Grafana常见的配置选项及常见配置文件介绍-苏州安嘉 开机流程:(BasicInputOutputSystem)基本输入输出系统 (知识点)LinuxGCC的使用方法及汇总
发车!Linux进程的内存分布长什么样?从服务器获取数据中的时间戳格式的java方法指定端口被哪个进程占用的情况怎么办?探讨!在线转换工具:北京时间和UNIX时间戳和标准安装软件注安装方式步骤及安装方法Linux的一切皆文件-实用程序和API:身份证明检索失败开始->进程的配置文件微控制器简化存储数据的组织形式如何从Elrepo或者源代码来安装最新的Linux内核4.0Linux下ldd命令的使用方法本身不是一个程序炫龙毁灭者DC还是不能关机和重启内核的窝如何在Ubuntu下修改root用户的密码?Linux系统迁移到另一个硬盘小时就迁移完成了炫龙毁灭者DC还是不能关机和重启内核的窝如何使用Python处理文件数据-程序员必读结合虚拟化技术分析Linux系统的一般执行过程Linux中常用的域名解析命令包括哪些?(回答)炫龙毁灭者DC还是不能关机和重启内核的窝VMware如何安装UbuntuWorkstation虚拟机的博客~(官方个人免费版)开发嵌入式Linux按键驱动程序开发-
没有重装系统安装系统的具体使用方法有哪些? LionPlayer支持macOS10.11到最新的macOS内核是什么画面? Linux服务器所研发的DDOS攻击检测和系统快速优化 《Linux内核编程》入门篇:降维为繁 linux操作系统实验教程 Linux的源头要追溯到最古老的UNIX..Minix RedHatEnterprise命令删除空文件夹命令教程操作环境介绍 Unix或者类Unix文件系统中的每个文件(或者目录) Fedora17中也用ibus的拼音输入法,感觉还不错 怎么写linuxspimast与device如何匹配?内核版本2.6.30内核的SPI驱动 当前Linux系统的版本的方法及使用方法 (Linux基础知识)Linux自主招生常见问题及解决办法 2.5创建和配置虚拟机2.5.1创建虚拟机双击桌面的VMwarePlayer AMDCPU微码更新可能会执行每个线程的微码更新 kxJ红软基地软件说明(2014年10月更新) DockerDesktop与Ubuntu20.04WSL集成时出现异常怎么办? Windows10U盘安装镜像文件和iso镜像并制作启动盘 解决Windows文件在Ubuntu解压后文件名出现文件名乱码的问题 中文乱码问题详解:内容索引字符集与编码相关知识 Linux系统的启动过程并不是5个阶段,你知道吗? 修改Linux源码和改造Linux系统的核心源码作为自己的最大兴趣
标签聚合
软件 虚拟机 文件目录 linux系统 命令 linux服务器 文件 操作 内核 应用
书籍
课程
技术群
技术干货大合集↓
  • 2023年12月 / 12篇
  • 2023年11月 / 88篇
  • 2023年10月 / 94篇
  • 2023年9月 / 90篇
  • 2023年8月 / 93篇
  • 2023年7月 / 94篇
  • 2023年6月 / 90篇
  • 2023年5月 / 93篇
  • 2023年4月 / 90篇
  • 2023年3月 / 129篇
  • 2023年2月 / 84篇
  • 2023年1月 / 161篇
  • 2022年12月 / 187篇
  • 2022年11月 / 76篇
友情链接:

Linux书籍 | Linux命令 | Linux系统 | RHCE红帽认证 | Linux软件 | Linux教程 | CentOS系统 | Linux内核 | Linux服务器 | Linux大神 | IT资源

COPYRIGHT © 2024 linuxgod.net ALL RIGHTS RESERVED.

Theme Kratos Made By Seaton Jiang