繁体   English   中英

如何模拟内存映射的I / O

[英]How to emulate memory-mapped I/O

我有一些我想模仿的硬件; 我想知道我是否可以在这样的低水平上做到这一点。 硬件有很多寄存器,我将它们排列在一个结构中:

#include <stdint.h>
struct MyControlStruct
{
    uint32_t data_reg_1;
    uint32_t data_reg_2;
    uint32_t dummy[2]; // to make the following registers have certain addresses
    uint32_t control_reg_1;
    uint32_t control_reg_2;
};
volatile struct MyControlStruct* MyDevice = (struct MyControlStruct*)0xDeadF00;

因此,我想为Windows和linux上的硬件访问支持以下语法:

MyDevice->data_reg_1 = 42;
MyDevice->data_reg_2 = 100;
MyDevice->control_reg_1 = 1;

当执行最后一行代码时,我希望硬件仿真器“唤醒”并做一些事情。 我可以在Windows和/或Linux上实现此功能吗? 我考虑过以某种方式捕获“分段故障”信号,但不确定是否可以在Windows上完成,或者根本不行。

我看了mmap的手册页; 看来它可以提供帮助,但是我不明白如何使用它。

当然,我可以通过定义WriteToMyDevice函数来抽象化对硬件的访问,并且一切都会变得容易(也许),但是我想了解是否可以以这种确切的方式安排对硬件的访问。

原则上,您可以为SIGSEGV编码(不重要地)一个处理程序,该处理程序将捕获并处理对不需要的页面的访问,并可以检查是否访问了指定的地址。

为此,您需要在Linux中使用sigaction系统调用和SA_SIGINFO并使用信号处理程序的ucontext_t*第三个参数。

这是极其不可移植的:在不同的Unix(甚至Linux内核的版本号可能很重要)以及更改处理器时,您都必须编写不同的代码。

而且我听说Linux内核在这种处理方面不是很快。

其他更好的内核(Hurd,Plan9)提供用户级别的分页,这应该有所帮助。

我最初误解了您的问题。 您有一块内存映射的硬件,并且您希望仿真是二进制兼容的。 在Windows上,您可以使用VirtualAlloc为该结构分配内存,并使其成为保护页,并使用SEH捕获对其的任何访问。

实际上,在纯用户空间代码的Linux上,您的仿真器是(而不是粗略的)可能的。

要构建仿真器,只需让第二个线程或进程(使用共享内存,或者可能是mmap'd文件并进行inotify)来监视正在模拟内存映射设备的内存。

对于真正的硬件驱动程序,您只需要一点点内核代码,但这可能只是将实际的硬件地址映射到具有适当权限的用户空间中的东西。 实际上,这会使现代的多用户操作环境退化为像旧的dos box或简单的微控制器一样工作-不是很好的做法,但是至少在不考虑安全性的情况下才可行。

您可能考虑的另一件事是在虚拟机中运行代码。

如果您要执行的代码是您自己的代码,则最好以可移植的方式开始编写,将硬件访问权限抽象为可以为每个平台重写的功能(例如,操作系统,硬件版本或物理/模拟)。 如果您需要其他人的现有代码来创建环境,那么这些技术将更加有用。 您可以考虑考虑的另一件事(如果原始文档没有太紧密地集成在一起)是使用特定功能的动态库级拦截,例如在Linux上使用LD_PRELOAD或在Windows上使用包装dll。 或为此,修补二进制文件。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM