【IMX6ULL驱动开发学习】19.mmap内存映射

news/2024/4/20 13:31:06/文章来源:https://blog.csdn.net/HuangChen666/article/details/131683860

mmap将一个文件或者其它对象映射进内存,使得应用层可以直接读取到驱动层的数据,无需通过copy_to_user函数
可以用于像LCD这样的外设, 需要读写大量数据的

一、应用层

mmap用法:

  • 用open系统调用打开文件, 并返回描述符fd.
  • 用mmap建立内存映射, 并返回映射首地址指针start.
  • 对映射(文件)进行各种操作, 显示(printf), 修改(strcpy、memncpy、sprintf、直接修改等).
  • munmap(void *start, size_t lenght)关闭内存映射.
  • close系统调用关闭文件fd.

mmap函数:

void *mmap(void *addr, size_t length, int prot, int flags,int fd, off_t offset);
参数含义
addr指向欲映射的内存起始地址,通常设为 NULL
代表让系统自动选定地址,映射成功后返回该地址
length代表将文件中多大的部分映射到内存。
prot映射区域的保护方式。可以为以下几种方式的组合:
PROT_EXEC 映射区域可被执行
PROT_READ 映射区域可被读取
PROT_WRITE 映射区域可被写入
PROT_NONE 映射区域不能存取
flags影响映射区域的各种特性。
在调用mmap()时必须要指定MAP_SHAREDMAP_PRIVATE
fd要映射到内存中的文件描述符。
如果使用匿名内存映射时,即flags中设置了MAP_ANONYMOUS,fd设为-1。
有些系统不支持匿名内存映射,则可以使用fopen打开/dev/zero文件,
然后对该文件进行映射,可以同样达到匿名内存映射的效果。
offset文件映射的偏移量,通常设置为0
代表从文件最前方开始对应,offset必须是分页大小的整数倍。

内存映射之后对内存进行读写,可以用write、read,但是效率低,可以直接对mmap函数返回的地址进行操作
使用 strcpy 等字符串处理函数即可


应用程序示例:

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <sys/mman.h>#define   MMSIZE   128int main(int argc, char *argv[])
{int len;char wr_buf[] = "hello mmap";char read_buf[1024];char *start;....../*open*/int fd;fd = open(argv[1], O_RDWR);if(fd < 0){printf("open failed\n");return -2;}printf("pid = %d\n", getpid());/* 将文件映射到进程的虚拟内存空间 */start = mmap(NULL, MMSIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);printf("mmap address = 0x%x\n", start);/* 写数据 */strcpy(start, wr_buf);/* 读数据 */strcpy(read_buf, start);
//	read(fd, read_buf, MMSIZE);printf("new data = %s\n", start);printf("old data = %s\n", read_buf);while(1){sleep(5);}munmap(start, MMSIZE);close(fd);return 0;
}

二、驱动层

  • 首先,驱动程序先分配好一段内存
  • 接着用户进程通过库函数mmap()来告诉内核要将多大的内存映射到内核空间
  • 内核经过一系列函数调用后调用对应的驱动程序的file_operation中指定的xxx_mmap函数
  • 在xxx_mmap函数中调用remap_pfn_range()来建立映射关系。

驱动程序示例:

......
......#define   MM_SIZE   1024 * 8
#define   MIN(x,y)  (x < y ? x : y)static char *buf = NULL;static ssize_t hello_read (struct file *filp, char  *buff, size_t size, loff_t *offset)
{int err;err = copy_to_user(buff, buf, MIN(MM_SIZE, size));return MIN(MM_SIZE, size);
}static int hello_mmap (struct file *filp, struct vm_area_struct *vma)
{	/*设置属性: cache,buffer */vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);if(remap_pfn_range(vma,//虚拟内存区域,即设备地址将要映射到这里  vma->vm_start,//虚拟空间的起始地址  virt_to_phys(buf)>>PAGE_SHIFT,//与物理内存对应的页帧号,物理地址右移12位  vma->vm_end - vma->vm_start,//映射区域大小,一般是页大小的整数倍  vma->vm_page_prot))//保护属性,  {  return -EAGAIN;  }  return 0;
}/*定义 file_operations 结构体*/
static const struct file_operations hello_drv = {.read		= hello_read,.open		= hello_open,.mmap 		= hello_mmap,............
};/*入口函数*/
static int hello_init(void)
{//内核申请内存只能按页申请,申请该内存以便后面把它当作虚拟设备buf = kmalloc(MM_SIZE, GFP_KERNEL);strcpy(buf, "abc");  //先放入一些数据............return 0;
}/*退出函数*/
static void hello_exit(void)
{kfree(buf);............
}	......
......

三、测试

直接口述吧
当mmap的参数为MAP_SHARED时,使用strcpy和read读取的数据和写入的相同;
当mmap的参数为MAP_PRIVATE时,使用strcpy读取的数据和写入的相同,read的数据和写入的不同(因为read到的是原内存的数据,MAP_PRIVATE标志会使得在写入内存数据时,内核会自动把内存空间拷贝一份,从而read到的是原来的内存,而写入的数据写入到了拷贝的新内存中)
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_330283.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

vue生命周期四个阶段(created和mount)

1.四个阶段 1&#xff09;必经阶段 2&#xff09;非必经阶段 提示&#xff1a;主动调用 vm.$destroy() 函数销毁后&#xff0c;可用 vm.$mount("#app") 将断开的 new Vue() 和页面重新建立虚拟 DOM 树&#xff0c;重新绑定起来挂载界面。 2. 生命周期钩子函数&…

ue4 MRQ渲染器时,媒体纹理播放速度会被加快

问题描述&#xff1a;当MRQ渲染器开启抗锯齿时&#xff0c;媒体纹理的播放速度会被加快 解决办法&#xff1a;通过执行抗锯齿控制台命令来解决

Proteus 8.13安装教程

不涉及版权问题。 1、双击“Proteus 8.13 SP0 Pro.exe”开始安装 2、按照安装向导进行操作&#xff0c;等待安装成功 1&#xff09;选择“Browse"自定义安装路径&#xff0c;再点击&#xff1a;Next 2&#xff09;点击&#xff1a;Next 3&#xff09;等待一段时间&#xf…

spark3新特性之动态分区裁剪

Spark3.0为我们带来了许多令人期待的特性。Spark中的静态分区裁剪在介绍动态分区裁剪之前&#xff0c;有必要对Spark中的静态分区裁剪进行介绍。因此&#xff0c;在这种情况下&#xff0c;我们不能再应用静态分区裁剪&#xff0c;因为filter条件在join表的一侧&#xff0c;而对…

第一百零四天学习记录:C++核心:类和对象Ⅶ(五星重要)继承下

继承同名成员处理方式 1、访问子类同名成员&#xff0c;直接访问即可 2、访问父类同名成员&#xff0c;需要加作用域 #include<iostream> using namespace std; class Base { public:Base(){m_A 100;}int m_A;void func(){cout << "Base - func()调用"…

C++图形开发(16):绘制一个圆环和一根针

文章目录 绘制一个圆环和一根针1.1 绘制1.2 line()函数1.3 circle()函数1.4 setlinestyle()函数1.5 setlinecolor()函数 接下来&#xff0c;我会继续制作一些小游戏&#xff0c;但因为整个难度的上升&#xff08;毕竟我也是初学者&#xff09;&#xff0c;可能文章不会再像之前…

spring复习:(22)实现了BeanNameAware等Aware接口的bean,相应的回调方法是在哪里被调用的?

AbstractAutowireCapableBeanFactory的doCreateBean用来创建bean, 其中调用了initializeBean方法对bean进行初始化 initializeBean包含如下代码&#xff1a; 而invokeAwareMethods代码如下&#xff1a; 可见其分别判断是否实现了BeanNameAware接口、BeanClassLoaderAware接口…

如何利用PLC远程通讯模块搭建PLC远程控制系统

随着工业自动化的快速发展&#xff0c;PLC&#xff08;可编程逻辑控制器&#xff09;作为重要的控制设备&#xff0c;被广泛应用于工厂和生产线的自动化控制系统。然而&#xff0c;传统的PLC控制系统受限于物理连接和局域网范围内的限制&#xff0c;无法实现远程监控和控制&…

dp算法 力扣174地下城游戏

在学习编程时&#xff0c;算法是一道硬菜&#xff0c;而dp作为算法的一份子&#xff0c;它的地位在编程界举足轻重。 174. 地下城游戏 - 力扣&#xff08;LeetCode&#xff09; 本文是Java代码哦~ 一、题目详情 恶魔们抓住了公主并将她关在了地下城 dungeon 的 右下角 。地…

React中 Real DOM 和 Virtual DOM 的区别?优缺点?

一、是什么 Real DOM&#xff0c;真实 DOM&#xff0c;意思为文档对象模型&#xff0c;是一个结构化文本的抽象&#xff0c;在页面渲染出的每一个结点都是一个真实 DOM 结构&#xff0c;如下&#xff1a; Virtual Dom&#xff0c;本质上是以 JavaScript 对象形式存在的对 DOM …

代码随想录算法学习心得 44 | 309.最佳买卖股票的时机含冷冻期、714.买卖股票的最佳时机含手续费、最近买卖股票时机总结...

一、最佳买卖股票的时机含冷冻期 链接&#xff1a;力扣 描述&#xff1a;给定一个整数数组prices&#xff0c;其中第 prices[i] 表示第 i 天的股票价格 。​ 设计一个算法计算出最大利润。在满足以下约束条件下&#xff0c;你可以尽可能地完成更多的交易&#xff08;多次买…

k8s 大量 pod 处于 ContainerStatusUnknown 状态

如图所示&#xff0c;nexus 正常运行&#xff0c;但产生了大量的状态不明的 pod&#xff0c;原因也无从所知 解决办法&#xff0c;删除多余的 pod&#xff0c;一个一个删除&#xff0c;非常费劲 获取 namespace 中状态为 ContainerStatusUnknown 的 pod&#xff0c;并删除 …

什么是深度学习的误差分解

误差分解是将深度学习模型的预测误差拆分为多个组成部分&#xff0c;以便更好地理解模型性能。在深度学习中&#xff0c;我们通常将预测误差分解为三个部分&#xff1a;偏差&#xff08;Bias&#xff09;、方差&#xff08;Variance&#xff09;和不可避免的误差&#xff08;Ir…

2. CSS3的新特性

2.1CSS3的现状 ●新增的CSS3特性有兼容性问题, ie9才支持 ●移动端支持优于PC端 ●不断改进中 ●应用相对广泛 ●现阶段主要学习: 新增选择器和盒子模型以及其他特性 CSS3给我们新增了选择器,可以更加便捷,更加自由的选择目标元素&#xff1a; 1.属性选择器 2.结构伪类选择器…

【UE】运行游戏时就获取鼠标控制

问题描述 我们经常在点击运行游戏后运行再在视口界面点击一下才能让游戏获取鼠标控制。其实只需做一个设置就可以在游戏运行后自动获取鼠标控制。 解决步骤 点击编辑器偏好设置 如下图&#xff0c;点击“播放”&#xff0c;再勾选“游戏获取鼠标控制” 这样当你运行游戏后直…

熬夜敲代码不伤眼,选好灯具很重要

文章目录 一、引言1.1 程序员的痛点&#xff1a;长时间使用电脑对眼睛的损害1.2 保护眼睛的重要性 二、明基ScreenBar Halo的保护眼睛功能2.1 自动调光&#xff1a;根据环境光调整亮度2.2 非对称光学设计&#xff1a;减少反光和刺眼2.3 沉浸式灯光&#xff1a;照亮全场视野&…

使用Pycharm

本人没有单独安装python&#xff0c;而是直接安装了anaconda 使用Pycharm创建项目 项目取名为HelloWorld&#xff0c;环境使用前面安装的anaconda pycharm安装模块的方法&#xff1a; 打开Pycharm>File > Settings>Project: Python>Project Interpreter

计网笔记--运输层(vital)

1--运输层概述 运输层的任务&#xff1a; 为运行在不同主机上的应用进程提供直接的通信服务&#xff1b; 运输层为应用层提供了两种不同的运输协议&#xff1a; 面向连接的 TCP 和无连接的 UDP 协议&#xff1b; 2--端口号、复用与分用的概念 端口号&#xff1a; 端口号用于区分…

Kotlin基础(五):类和接口

前言 本文主要讲解类和接口&#xff0c;主要包括类的声明、构造器、类成员、修饰符、类的继承、接口、抽象类。 Kotlin文章列表 Kotlin文章列表: 点击此处跳转查看 目录 1.1 类的声明 在 Kotlin 中&#xff0c;类的声明使用关键字 class。下面是一个简单的类声明的示例&…

感受C++模版的所带来的魅力

一、泛型编程思想 首先我们来看一下下面这三个函数&#xff0c;如果学习过了 C函数重载 和 C引用 的话&#xff0c;就可以知道下面这三个函数是可以共存的&#xff0c;而且传值会很方便 void Swap(int& left, int& right) {int temp left;left right;right temp; }…