我有一些我想模仿的硬件;我想知道我是否可以在这样的低水平做到这一点。硬件有很多寄存器,我在一个结构中安排:
#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
之类的函数来抽象对硬件的访问,一切都很简单(也许),但我想知道我是否可以按照这种方式安排访问我的硬件。
答案 0 :(得分:3)
原则上,您可以编码(不可移植)SIGSEGV
的处理程序,该处理程序将陷阱和处理对不需要的页面的访问,并且可以检查是否访问了指定的地址。
要在Linux下执行此操作,您需要使用sigaction
系统调用SA_SIGINFO
并使用信号处理程序的ucontext_t*
第三个参数。
这非常难以置信:对于不同的Unix(甚至Linux内核的版本号可能很重要)以及更换处理器时,您必须采用不同的代码。
我听说Linux内核的处理速度不是很快。
其他更好的内核(Hurd,Plan9)提供了用户级别的分页,这应该会有所帮助。
答案 1 :(得分:2)
我最初误解了你的问题。你有一块内存映射硬件,你希望你的仿真是二进制兼容的。在Windows上,您可以使用VirtualAlloc为结构分配内存,并使其成为一个保护页面,并使用SEH捕获对它的任何访问权。
答案 2 :(得分:1)
实际上,您的模拟器(在相当粗略的情况下)可以在Linux上使用纯用户空间代码。
要构建模拟器,只需要第二个线程或进程(使用共享内存,或者mmap'd文件和inotify),观察模拟内存映射设备的内存
对于真正的硬件驱动程序,您将需要一些内核代码,但这可能只是将实际硬件地址映射到具有适当权限的用户空间。实际上,这会使现代多用户操作环境回归到像旧的dos盒或简单的微控制器一样 - 不是很好的做法,但至少在安全性不是问题的情况下是可行的。
您可以考虑的另一件事是在虚拟机中运行代码。
如果您要执行的代码是您自己的代码,最好以可移植的方式编写代码,将硬件访问抽象为可以为每个平台重写的函数(即OS,硬件)版本或物理/模拟)。如果这是其他人创建环境所需的现有代码,那么这些技术会更有用。您可以考虑的另一件事(如果原始版本没有太紧密集成)是使用特定函数的动态库级别拦截,例如在Linux上使用LD_PRELOAD或在Windows上使用包装器DLL。或者就此而言,修补二进制文件。