簡體   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