Как эмулировать отображаемый в память ввод-вывод - PullRequest
7 голосов
/ 26 октября 2011

У меня есть оборудование, которое я хочу эмулировать;Интересно, смогу ли я сделать это на низком уровне, как это.Аппаратное обеспечение имеет много регистров, которые я размещаю в структуре:

#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, и все было бы легко (может быть,), но я хочу понять, могу ли я организовать доступ к своему оборудованию именно таким образом.

Ответы [ 3 ]

3 голосов
/ 26 октября 2011

В принципе, вы можете кодировать (не переносимо) обработчик для SIGSEGV, который будет перехватывать и обрабатывать доступ к нежелательным страницам и который может проверять доступ к указанному адресу.

Для этого в Linuxвам нужно использовать системный вызов sigaction с SA_SIGINFO и третий аргумент ucontext_t* вашего обработчика сигналов.

Это крайне непереносимо: вам придется кодировать по-разному для разныхUnix (возможно, даже номер версии вашего ядра Linux может иметь значение) и при смене процессоров.

И я слышал, что ядра Linux не очень быстро справляются с такой обработкой.

Другие лучшие ядра(Hurd, Plan9) предлагает разбиение на страницы на уровне пользователя, что должно помочь.

2 голосов
/ 12 января 2018

Я изначально неправильно понял ваш вопрос. У вас есть часть оборудования с отображенной памятью, и вы хотите, чтобы ваша эмуляция была двоично-совместимой. В Windows вы можете выделить память для структуры с помощью VirtualAlloc, сделать ее защитной страницей и перехватить любой доступ к ней с помощью SEH.

1 голос
/ 07 ноября 2011

На самом деле ваш эмулятор (довольно грубо) возможен в Linux с чистым кодом пользовательского пространства.

Чтобы создать эмулятор, просто создайте второй поток или процесс (с использованием общей памяти или, возможно, mmap'd).файл и inotify) наблюдая за памятью, которая эмулирует отображенное устройство памяти

Для реального аппаратного драйвера вам потребуется небольшой кусочек кода ядра, но это может быть просто то, что отображает фактические аппаратные адреса в пользователяпространство с соответствующими разрешениями.По сути, это ограничивает современную многопользовательскую операционную среду и ведет себя как старая коробка с досками или простой микроконтроллер - не очень хорошая практика, но работоспособная, по крайней мере, там, где безопасность не имеет значения.

Еще одна вещь, которую вы могли бы рассмотретьбудет запускать код на виртуальной машине.

Если код, который вы будете использовать, принадлежит вам, вероятно, для начала лучше написать его переносимым способом, абстрагируя аппаратный доступ от функций, которые вы используете.можно переписать для каждой платформы (т. е. ОС, аппаратной версии или физической / эмулированной).Эти методы более полезны, если вам нужен чужой код для создания среды.Еще одна вещь, которую вы можете рассмотреть (если оригинал не слишком тесно интегрирован) - это использование перехвата определенных функций на уровне динамической библиотеки, например, с LD_PRELOAD в Linux или оболочкой dll в Windows.Или, в этом отношении, исправление двоичного файла.

...