Синтетический порт должен быть простым и понятным. Нужно вначале
четко определить иерархию сущностей. Иначе все зря. -- Платформо-независимый простой код. Он просто исполняется, одинаково на всех платформах
-- Платформо-зависимый простой код. Например, переключение задач - он "по периметру" должен быть одинаковым, вставляется нужный вариант под платформу
-- события. Они вызывают некие действия в коде, происходят параллельно с исполнением кода
-- реальный мир:
.. регистры
.. области памяти
.. события
-- обобщенная модель драйвера устройства
Имеет смысл рассмотреть полусинтетический порт.
Например, UART или I2C утомительно полностью эмулировать на ПК, и не зачем. Или ЦАП/АЦП и реальный объект в виде мотора.
Драйвера живут в макете (не факт, что на целевом процессоре), а с ПК это все связано быстрым каналом, где и крутится синтетический порт.
Как я уже писал, для 10G Ethernet народ достигает латентности 20 мкс в user space на Linux, (10G здесь важен только правильными карточками с правильными дровами с аппаратным ускорением, воткнуть можно в 100М коммутатор) - это и может стать задержкой между реальным и виртуальными мирами.
С одной стороны, все, что касается синтетического порта, должно быть максимально простым, с другой стороны, максимально удобным. Это не простой баланс.
Если хотим связь с макетом иметь по USB - стоит посмотреть на патченные "музыкальные" Linux. которые в варианте USB устройств дают латентность 2 мс.
UbuntuStudio/RealTimeKernel вообще 100 мкс обещают
https://help.ubuntu.com/community/UbuntuStudio/RealTimeKernel
По сути я счастлив. 15 лет назад я по крупицам собирал и сам придумывал идеи таких решений, а сейчас это уже вполне общепринятая идеология.