Linux下如何操作寄存器

news2024/10/6 8:36:06

本期主题:
linux下操作寄存器


往期链接:

  • linux设备驱动中的并发
  • linux设备驱动中的编译乱序和执行乱序
  • linux设备驱动之内核模块
  • linux字符驱动
  • linux字符驱动之ioctl部分
  • linux字符驱动之read、write部分
  • linux驱动调试之Debugfs

文章目录

  • 1.为什么有这个问题
    • 1.内存空间与I/O空间
    • 2.内存管理单元
    • 3.Linux内存管理
  • 2.用户空间下怎么访问寄存器
    • 1.mmap原理
    • 2.mmap函数原型
    • 3.mmap使用例子
  • 3.内核空间下怎么访问寄存器
    • 1.ioremap
    • 2.实际例子


1.为什么有这个问题

Linux开发与裸机开发不同,在裸机开发中直接使用指针方式就能访问到对应地址,但是在Linux中,由于内存管理的存在,并不能这么粗暴的直接用指针进行访问。

那么Linux下的内存管理是怎样的呢?linux内存管理相当复杂,本篇文章只能简单介绍一部分:

1.内存空间与I/O空间

  • I/O空间: 在x86处理器中存在着I/O空间的概念,I/O空间是相对于内存空间而言的,通过特定的指令 in、out来访问,端口号标识了外设的寄存器地址;
//intel的in指令格式如下:
IN 累加器, { 端口号 | DX}
  • 内存空间: 大多数的嵌入式微控制器(如ARM、PowerPC等)并不提供I/O空间,仅存在内存空间,可以直接通过地址、指针来进行访问;

下图给出了内存空间和I/O空间的对比:
在这里插入图片描述
从上图可以看出,内存空间是必须的,而I/O空间是可选的。

2.内存管理单元

高性能处理器一般会提供一个内存管理单元MMU,该单元辅助操作系统进行内存管理。
提供虚拟地址和物理地址映射内存访问权限保护cache缓存控制等硬件支持。

3.Linux内存管理

对于包含MMU的处理器,linux提供了复杂的存储管理系统,(以32位处理器为例),进程所能够访问的空间达到4GB。
在Linux系统中,进程的4GB内存空间被分为两个部分——用户空间和内核空间,具体的描述可以看这个链接:操作系统系列(二)——进程

2.用户空间下怎么访问寄存器

用户空间下我们对于寄存器的访问可以使用 mmap接口

1.mmap原理

mmap是一种内存映射文件的方法,即将一个文件或者其它对象映射到进程的地址空间,实现文件磁盘地址和进程虚拟地址空间中一段虚拟地址的一一对映关系。实现这样的映射关系后,进程就可以采用指针的方式读写操作这一段内存,而系统会自动回写脏页面到对应的文件磁盘上,即完成了对文件的操作而不必再调用read,write等系统调用函数。

在这里插入图片描述

2.mmap函数原型

void *mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset);

参数:

start:映射区的开始地址
length:映射区的长度

prot:期望的内存保护标志,不能与文件的打开模式冲突。是以下的某个值,可以通过or运算合理地组合在一起
PROT_EXEC :页内容可以被执行
PROT_READ :页内容可以被读取
PROT_WRITE :页可以被写入
PROT_NONE :页不可访问

flags:指定映射对象的类型,映射选项和映射页是否可以共享。它的值可以是一个或者多个以下位的组合体
MAP_FIXED //使用指定的映射起始地址,如果由start和len参数指定的内存区重叠于现存的映射空间,重叠部分将会被丢弃。如果指定的起始地址不可用,操作将会失败。并且起始地址必须落在页的边界上。
MAP_SHARED //与其它所有映射这个对象的进程共享映射空间。对共享区的写入,相当于输出到文件。直到msync()或者munmap()被调用,文件实际上不会被更新。
MAP_PRIVATE //建立一个写入时拷贝的私有映射。内存区域的写入不会影响到原文件。这个标志和以上标志是互斥的,只能使用其中一个。
MAP_DENYWRITE //这个标志被忽略。
MAP_EXECUTABLE //同上
MAP_NORESERVE //不要为这个映射保留交换空间。当交换空间被保留,对映射区修改的可能会得到保证。当交换空间不被保留,同时内存不足,对映射区的修改会引起段违例信号。
MAP_LOCKED //锁定映射区的页面,从而防止页面被交换出内存。
MAP_GROWSDOWN //用于堆栈,告诉内核VM系统,映射区可以向下扩展。
MAP_ANONYMOUS //匿名映射,映射区不与任何文件关联。
MAP_ANON //MAP_ANONYMOUS的别称,不再被使用。
MAP_FILE //兼容标志,被忽略。
MAP_32BIT //将映射区放在进程地址空间的低2GB,MAP_FIXED指定时会被忽略。当前这个标志只在x86-64平台上得到支持。
MAP_POPULATE //为文件映射通过预读的方式准备好页表。随后对映射区的访问不会被页违例阻塞。
MAP_NONBLOCK //仅和MAP_POPULATE一起使用时才有意义。不执行预读,只为已存在于内存中的页面建立页表入口。

fd:有效的文件描述词。如果MAP_ANONYMOUS被设定,为了兼容问题,其值应为-1

offset:被映射对象内容的起点

3.mmap使用例子

以操作一个地址为0xA4030000的寄存器为例

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <time.h>
#include <unistd.h>
#include <string.h>

#deinfe REG_BASE 0xA4030000

int main(void)
{
	int fd;
	void *map_reg_base;
    // map to register base and memory
	fd = open("/dev/mem", O_RDWR | O_SYNC);
	if (fd)	{
		DEBUG("Success to open /dev/mem fd=%08x\n", fd);
	} else {
		DEBUG("Fail to open /dev/mem fd=%08x\n", fd);
	}
	//这里的map_reg_base就是被mmap过后的指针,可以直接操作了
	map_reg_base = mmap(0, 0x400, PROT_READ | PROT_WRITE,
			MAP_SHARED, fd, REG_BASE);

}

3.内核空间下怎么访问寄存器

1.ioremap

在内核中访问I/O内存(通常是一些控制器的寄存器)之前,需要使用ioremap()函数将设备所处的物理地址映射到虚拟地址上

函数原型:

void __iomem *ioremap(resource_size_t phys_addr, unsigned long size)
/**
 * ioremap     -   map bus memory into CPU space
 * @phys_addr:    bus address of the memory
 * @size:      size of the resource to map
 *
 * ioremap performs a platform specific sequence of operations to
 * make bus memory CPU accessible via the readb/readw/readl/writeb/
 * writew/writel functions and the other mmio helpers. The returned
 * address is not guaranteed to be usable directly as a virtual
 * address.
 *
 * This version of ioremap ensures that the memory is marked uncachable
 * on the CPU as well as honouring existing caching rules from things like
 * the PCI bus. Note that there are other caches and buffers on many
 * busses. In particular driver authors should read up on PCI writes
 *
 * It's useful if some control registers are in such an area and
 * write combining or read caching is not desirable:
 *
 * Must be freed with iounmap.
 */

2.实际例子

使用ioremap和不使用ioremap进行对比:

#include <linux/init.h>
#include <linux/module.h>
#include <linux/sched.h>
#include <asm/io.h>

#define USE_IOREMAP

#define H3_GPIO_BASE (0x01C20800)

static volatile unsigned long *gpio_regs = NULL;

static int __init ioremap_mod_init(void)
{

    int i = 0;
    printk(KERN_INFO "ioremap_mod init\n");

#ifdef USE_IOREMAP
    gpio_regs = (volatile unsigned long *)ioremap(H3_GPIO_BASE, 1024);
#else
    gpio_regs = (volatile unsigned long *)H3_GPIO_BASE;
#endif

    for (i=0; i<3; i++)
        printk(KERN_INFO "reg[%d] = %lx\n", i, gpio_regs[i]);

    return 0;
}
module_init(ioremap_mod_init);

static void __exit ioremap_mod_exit(void)
{
    printk(KERN_INFO "ioremap_mod exit\n ");

#ifdef USE_IOREMAP
    iounmap(gpio_regs);
#endif 
}

module_exit(ioremap_mod_exit);

MODULE_AUTHOR("es-hacker");
MODULE_LICENSE("GPL v2");

实验结果:
1.使用ioremap

$ insmod ioremap
ioremap_mod init
reg[0] = 71227722
reg[1] = 33322177
reg[2] = 773373

2.不使用ioremap

$ insmod ioremap_mod.ko

Unable to handle kernel paging request at virtual address 01c20800
pgd = c9ece7c0
[01c20800] *pgd=6ddd7003, *pmd=00000000
Internal error: Oops: 206 [#1] SMP ARM
CPU: 1 PID: 1253 Comm: insmod Tainted: G           O    4.14.111 #116
Hardware name: sun8i
task: ef15d140 task.stack: edc50000
PC is at ioremap_mod_init+0x3c/0x1000 [ioremap_mod]
LR is at ioremap_mod_init+0x14/0x1000 [ioremap_mod]
pc : [<bf5d903c>]    lr : [<bf5d9014>]    psr: 600e0013
sp : edc51df8  ip : 00000007  fp : 118fa95c
r10: 00000001  r9 : ee7056c0  r8 : bf5d6048
r7 : bf5d6000  r6 : 00000000  r5 : bf5d6200  r4 : 00000000
r3 : 01c20800  r2 : 01c20800  r1 : 00000000  r0 : bf5d5048
Flags: nZCv  IRQs on  FIQs on  Mode SVC_32  ISA ARM  Segment user
Control: 30c5387d  Table: 49ece7c0  DAC: b106c794
Process insmod (pid: 1253, stack limit = 0xedc50210)

[<bf5d903c>] (ioremap_mod_init [ioremap_mod]) from [<c0201a70>] (do_one_initcall+0x40/0x16c)
[<c0201a70>] (do_one_initcall) from [<c02b20c8>] (do_init_module+0x60/0x1f0)
[<c02b20c8>] (do_init_module) from [<c02b1214>] (load_module+0x1b48/0x2250)
[<c02b1214>] (load_module) from [<c02b1ad8>] (SyS_finit_module+0x8c/0x9c)
[<c02b1ad8>] (SyS_finit_module) from [<c0221f80>] (ret_fast_syscall+0x0/0x4c)
Code: e5953000 e3050048 e1a01004 e34b0f5d (e7932104) 
---[ end trace 928c64a33a054308 ]---
Segmentation fault

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

内网信息收集(基于红日靶场1)

net view # 查看局域网内其他主机名 net config Workstation # 查看计算机名、全名、用户名、系统版本、工作站、域、登录域 net user # 查看本机用户列表 net user /domain # 查看域用户 net localgroup administrators # 查看本地…

合宙esp32 环境搭建和使用方法

文章目录1.环境搭建2.问题2-1&#xff1a;exec: "cmd": executable file not found in %PATH%3.合宙esp32 使用3-1引脚定义3-1-1&#xff1a;板载LED3-2下载程序&#xff1a;3-3测试程序4.ESP32-C3开发板相关资料1.环境搭建 1-1&#xff1a;下载esp32 安装包 链接&a…

[一篇读懂]C语言八讲:数据结构概述

[一篇读懂]C语言八讲&#xff1a;数据结构概述1. 与408关联解析及本节内容介绍1 与408关联解析2 本节内容介绍2. 逻辑结构与存储结构1 逻辑结构2 存储结构顺序存储链式存储3 顺序存储与链式存储分析顺序存储优缺点链式存储优缺点3. 时间复杂度与空间复杂度1 算法定义2 时间复杂…

攻防世界1-misc

1-misc 题目描述&#xff1a;无 题目环境&#xff1a;https://download.csdn.net/download/m0_59188912/87094807 打开压缩包&#xff0c;提示密码是出题人生日。 使用archpr爆破压缩包。 得到密码&#xff1a;20001228 解压压缩包&#xff0c;得到两个文件&#xff0c;一个图片…

[附源码]java毕业设计网吧购物系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

【CSDN|每日一练】代写匿名信

目录 运行结果题目描述输入描述:输出描述:示例代码结语运行结果 题目描述 小Q想要匿名举报XX领导不务正业! 小Q害怕别人认出他的字迹。 他选择从报纸上剪裁下来英文字母组成自己的举报信。 现在小Q找来了报纸,和自己的举报信的Txt, 你能帮他确定一下是否能够完成匿名信…

6242. 二叉搜索树最近节点查询

目录题目关键词代码题目 给你一个 二叉搜索树 的根节点 root &#xff0c;和一个由正整数组成、长度为 n 的数组 queries 。 请你找出一个长度为 n 的 二维 答案数组 answer &#xff0c;其中 answer[i] [mini, maxi] &#xff1a; mini 是树中小于等于 queries[i] 的 最大值…

Vue-Router学习记录

目录 一.使用路由 1.1配置路由 1.2采用路由 二.路由懒加载 三.路由重定向 四.嵌套路由 五.路由跳转 1.1标签式 1.2编程式 1.3路由的query参数 1.4命名路由 前言: vue 属于单页面应用&#xff0c;所谓的路由&#xff0c;就是根据浏览器路径不同&#xff0c;用不同的…

常见Lidar点云数据处理及可视化软件汇总

常见的点云处理及可视化软件有&#xff1a; CloudCompare、Globalmapper、Pix4d、ArcGIS&#xff08;Pro&#xff09;、Lidar 360、PCL等等。 文章目录1. CloudCompare2. Globalmapper3. Pix4d4. ArcGIS&#xff08;Pro&#xff09;5. Lidar 3606. PCL1. CloudCompare CloudCo…

2022年11月20日 15点 纳指正在走到一个黄金分割点附近,是否会真的按照自然规则做调整,可以看看数据的威力。

行情核心源头: 纳斯达克指数&#xff0c; 是否会符合大数据规则&#xff0c;走黄金分割线规则 [数据说话] 第一波下跌3820&#xff0c; 反弹2299点&#xff0c;反弹了60%&#xff0c;接近61.8%第二波下跌4159&#xff0c;反弹2612&#xff0c;反弹了62.8%&#xff0c;接近61.…

借助第三方工具网站完成消息自动推送

文章目录前言pushplus是什么pushplus测试使用代码发送注意的问题总结前言 寻找消息推送的起因是之前买过一台云服务器&#xff0c;用于开发环境搭建和学习&#xff0c;最近想用它进行一些数据分析&#xff0c;而数据分析的结果如果每次都需要登录服务器来看就有点“太老土”了…

今天解决了一个主从延迟导致超发的问题

主从同步过程 MySQL主从同步由主节点dump线程、从节点 I/O 线程、从节点SQL线程三个线程配合完成。 1、从节点上的 I/O 进程主从去连接主节点&#xff0c;并带上同步的开始位置即指定日志文件的位置之后的日志内容 2、主节点接收到来自从节点的 I/O 请求后&#xff0c;通过主…

c风格字符串,数组,string ,vector

c风格字符串&#xff0c;数组&#xff0c;string &#xff0c;vector 数组 数组下标 数组下标通常定义为 size_t type arrayName [ arraySize ][arraySize1]; arraySize必须是一个大于等于零的整数常量。 1因为sizeof的计算值是个常量&#xff0c;所以sizeof的计算值和字…

深度学习基础-2

文章目录0 前言1 全连接神经网络2 激活函数2.1 Sigmoid2.2 Tanh2.3 ReLU2.4 Leaky ReLU3 交叉熵损失4 计算图与反向传播4.1 计算图4.2 梯度消失与梯度爆炸4.3 动量法5 权重初始化5.1 全零初始化5.2 标准随机初始化5.3 Xavier初始化5.4 Kaming初始化6 批归一化7 参考资料0 前言 …

腾讯云轻量应用服务器内网连接互通有什么限制?

腾讯云轻量应用服务器内网连接互通有什么限制&#xff1f;腾讯云轻量应用服务器可以通过内网访问同地域下的云数据库、云服务器CVM或负载均衡等实例吗&#xff1f;不可以&#xff0c;只能通过公网连接互通&#xff0c;主机教程网来详细说下腾讯云轻量应用服务器内网互通限制说明…

快速MOCK数据并插入数据表中(MySQL)

问题描述&#xff1a;在学习使用SQL语句操作数据库的时候&#xff0c;添加十几二十条数据总感觉不够直观&#xff0c;如何快速批量制造相对真实的假数据&#xff0c;以供测试使用&#xff1f; 一、操作步骤 1.准备一张表 CREATE TABLE IF NOT EXISTS products (id INT PRIMA…

关于qt中label挡住了dockwidget的窗体边缘

关于qt中label挡住了dockwidget的窗体标题 1.问题描述&#xff1a; dock_Image new QDockWidget(tr("图像"), this);setCentralWidget(dock_Image);imgLabel new QLabel(dock_Image);imgLabel->setScaledContents(true); // 设置QLabel自动适应图像大小//dock…

win下载安装不同java版本教程

不同版本jdk下载与安装 1. 下载 最全java版本官方下载地址https://www.oracle.com/java/technologies/downloads 下载.exe安装文件即可 2.安装 下载后双击exe程序即可安装&#xff0c;在第二布时要特别注意&#xff1a;安装路径不要有中文或含有空格 3.检查java是否安装成…

你在编程过程中养成了哪些好习惯?

写工作日志。 我一直有大量写笔记的习惯。编程的时候&#xff0c;也经常遇到一些麻烦的问题&#xff0c;思路转瞬即逝&#xff0c;于是把所有这些思路记录下来&#xff0c;会在以后的搜索中成为重要的灵感来源。 我的工作日志里通常以项目为单位&#xff0c;包含四个重要的章…

[Linux/初学者]Vim文本编译器的模式切换及其常用指令

前言 Linux 系统中所有的内容都以文件的形式进行存储&#xff0c;当在命令行下更改文件内容时&#xff0c;常会用到文本编辑器。 Vi编辑器是Unix及Linux系统下的标准编辑器&#xff0c;同时也是Linux中最基本的文本编辑器&#xff0c; Vim编译器则是Vi编译器的升级版本&…