Виртуальный последовательный порт для Linux

Мне нужно протестировать приложение последовательного порта в Linux, однако моя тестовая машина имеет только один последовательный порт.

Есть ли способ добавить виртуальный последовательный порт в Linux и протестировать мое приложение, эмулируя устройство через оболочку или скрипт?

Примечание: я не могу переназначить порт, он жестко запрограммирован на ttys2, и мне нужно протестировать приложение в том виде, в котором оно написано.

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
143
0
186 532
8
Перейти к ответу Данный вопрос помечен как решенный

Ответы 8

Сможете ли вы использовать адаптер USB-> RS232? У меня их несколько, и они просто используют драйвер FTDI. Затем вы сможете переименовать / dev / ttyUSB0 (или все, что будет создано) как / dev / ttyS2.

Я могу придумать три варианта:

Реализовать RFC 2217

RFC 2217 охватывает COM-порт в соответствии со стандартом TCP / IP, который позволяет клиенту в одной системе имитировать последовательный порт для локальных программ, при этом прозрачно отправляя и получая данные и управляющие сигналы на сервер в другой системе, которая фактически имеет последовательный порт. Вот общий обзор.

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

Затем вы реализуете серверную часть соединения локально в другой программе, позволяя клиенту подключаться и выдавать данные и команды управления по мере необходимости.

Это, вероятно, нетривиально, но RFC уже существует, и вы можете найти проект с открытым исходным кодом, который реализует одну или обе стороны соединения.

Измените драйвер последовательного порта linux

В качестве альтернативы легко доступен исходный код драйвера последовательного порта для Linux. Возьмите это, выпотрошите элементы управления оборудованием и пусть один драйвер запускает два порта / dev / ttySx в качестве простой обратной связи. Затем подключите свою реальную программу к ttyS2, а симулятор - к другому ttySx.

Используйте два последовательных кабеля USB <--> в кольцевой проверке.

Но что проще сделать прямо сейчас? Потратьте 40 долларов на два USB-устройства с последовательным портом, соедините их вместе (нуль-модем) и получите два реальных последовательных порта - один для программы, которую вы тестируете, другой для вашего симулятора.

-Адам

На самом деле нуль-модемные USB-кабели UART кажутся мне довольно элегантным решением, поскольку они поддерживают как локальное тестирование (получите USB-концентратор, если у вас мало портов), так и удаленную отладку.

Maxthon Chan 20.10.2014 20:31

Я не проверял его качество, но ttynvt реализует RFC 2217 через Linux FUSE

Daniel Santos 25.03.2020 02:55
Ответ принят как подходящий

Для этого вы можете использовать pty («псевдотелетайп», где последовательный порт является «настоящим телетайпом»). С одной стороны откройте /dev/ptyp5, а затем прикрепите свою программу к /dev/ttyp5; ttyp5 будет действовать как последовательный порт, но будет отправлять / получать все, что он делает, через / dev / ptyp5.

Если вам действительно нужно, чтобы он разговаривал с файлом с именем /dev/ttys2, просто переместите старый /dev/ttys2 в сторону и создайте символическую ссылку с ptyp5 на ttys2.

Конечно, вы можете использовать другой номер, кроме ptyp5. Возможно, выберите один с большим числом, чтобы избежать дублирования, поскольку все ваши терминалы входа также будут использовать ptys.

В Википедии есть больше о ptys: http://en.wikipedia.org/wiki/Pseudo_terminal

В Linux вы можете использовать системные вызовы openpty / forkpty. См. страница руководства

Matthew Smith 27.10.2008 08:25

как создать пару виртуальных последовательных портов с помощью инструмента командной строки?

linjunhalida 20.01.2010 05:53

используйте chroot для подделки имен устройств, не влияя на систему

Dima Tisnek 03.04.2012 11:08

обратите внимание, что многие параметры последовательного порта, например baudrate, четность, управление потоком hw, размер символа (?) не реализованы в pty, поэтому невозможно протестировать ваше приложение на наличие ошибок последовательной передачи.

Dima Tisnek 03.04.2012 11:10

Это полезно, но описывает псевдотерминалы BSD «старого стиля». Псевдотерминалы UNIX 98 «нового стиля» работают немного иначе - см. Справочная страница pts для подробностей.

Craig McQueen 21.08.2012 07:16

Преимущество использования ptys в старом стиле в этом вопросе заключается в том, что он действительно хотел, чтобы один был назван / dev / ttys2. Птицы в старом стиле можно легко переименовать, а в новом - нет. Нормальные люди должны использовать pty в новом стиле, как вы говорите.

apenwarr 22.08.2012 08:18

@MattSmith: у вас есть рабочий пример с openpty? Просто вызвать его недостаточно для привязки одного вывода к другому, и наоборот ...

lpapp 17.11.2013 01:33

@LaszloPapp Я заставил его работать, просмотрев страницы руководства по openpty и forkpty. У меня больше нет доступа к исходному коду, поскольку я ушел из этой компании.

Matthew Smith 19.11.2013 10:12

@MattSmith: как я уже писал, openpty и forkpty сами по себе недостаточны для создания петли! Это как-то странно, вы даже не знаете теорию ... В любом случае, я не рекомендую это другим, потому что я провел целый день, не понимая, как это сделать. Это была пустая трата времени.

lpapp 19.11.2013 10:20

@LaszloPapp Прошу прощения, я все время лгал

Matthew Smith 20.11.2013 05:58

@DimaTisnek Думаю, пора это изменить! Просто погуглил «виртуальный последовательный порт linux», чтобы убедиться, что я не отключился от качели и не переписываю колесо. Я думаю, что я собираюсь добавить флаг CVSERIAL в поле termios c_cflag (много битов в настоящее время не используется) в качестве переключателя для его включения и выключения (со стороны ведущего, конечно), и когда он установлен, ведомое устройство и ведущее устройство будут иметь все ioctls управления модемом, за исключением того, что мастер будет выполнять все строки RI, CD и т. д. Думаю, тогда мы посмотрим, смогу ли я пройти мимо сопровождающих.

Daniel Santos 25.03.2020 02:48

@DanielSantos звучит как план. Возможно, в зависимости от того, что вы хотите виртуализировать, такое виртуальное последовательное "оборудование" должно быть собственным модулем ... Например, если вы хотите смоделировать несоответствие скорости передачи данных. В любом случае, флаг - хороший способ начать взламывать!

Dima Tisnek 25.03.2020 04:42

Вы можете посмотреть Тиббо VSPDL для создания виртуального последовательного порта Linux с использованием драйвера ядра - он кажется довольно новым и доступен для загрузки прямо сейчас (бета-версия). Не уверен насчет лицензии на данный момент, или хотят ли они сделать ее коммерчески доступной только в будущем.

Есть и другие коммерческие альтернативы, например http://www.ttyredirector.com/.

В Open Source Remserial (GPL) также может делать то, что вы хотите, используя Unix PTY. Он передает последовательные данные в «сыром виде» в сетевой сокет; Настройка параметров терминала в стиле STTY должна выполняться при создании порта, изменение их позже, как описано в RFC 2217, похоже, не поддерживается. У вас должна быть возможность запустить два экземпляра remserial для создания виртуального нульмодема, такого как com0com, за исключением того, что вам нужно будет заранее настроить скорость порта и т. д.

Socat (также GPL) похож на расширенный вариант Remserial со многими другими опциями, включая метод «PTY» для перенаправления PTY на что-то другое, которое может быть другим экземпляром Socat. Для Unit tets, socat, вероятно, лучше, чем remserial, потому что вы можете напрямую cat файлы в PTY. См. Пример PTY на странице руководства. патч существует в разделе «contrib» для обеспечения поддержки RFC2217 для согласования настроек последовательной линии.

Используя ссылки, опубликованные в предыдущих ответах, я написал небольшой пример на C++ с использованием виртуального последовательного порта. Я поместил код в GitHub: https://github.com/cymait/virtual-serial-port-example.

Код довольно понятен. Сначала вы создаете главный процесс, запустив ./main master, и он будет печатать на stderr, используемом устройством. После этого вы вызываете ./main slave device, где device - это устройство, напечатанное в первой команде.

И это все. У вас есть двунаправленная связь между двумя процессами.

Используя этот пример, вы можете протестировать приложение, отправив всевозможные данные, и посмотреть, правильно ли оно работает.

Кроме того, вы всегда можете создать символическую ссылку на устройство, поэтому вам не нужно повторно компилировать тестируемое приложение.

while (read (fd, & inputbyte, 1) == 1) {...} чтение не определено в вашем коде. запись не определена. close не определено.

Mattis Asp 04.01.2018 12:35

@MattisAsp прав, вы должны хотя бы включить <unistd.h>. Плюс есть куча исправляемых вещей, которые нельзя игнорировать, но в целом простой код, который мне нравится.

Yves Lhuillier 10.11.2020 12:58

Для этого используйте socat:

Например:

socat PTY,link=/dev/ttyS10 PTY,link=/dev/ttyS11

У меня это сработало, протестировано с minicom! Похоже, что вход в один терминал отражается на обоих (так что он снова появится на входном терминале).

gbmhunter 08.01.2014 08:09

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

cptHammer 09.06.2016 17:46

Существует также tty0tty http://sourceforge.net/projects/tty0tty/, настоящий эмулятор нуль-модема для Linux.

Это простой модуль ядра - небольшой исходный файл. Я не знаю, почему он получил отрицательные отзывы на sourceforge, но мне он подходит. Самое лучшее в нем то, что он также эмулирует аппаратные контакты (RTC / CTS DSR / DTR). Он даже реализует команды TIOCMGET / TIOCMSET и TIOCMIWAIT iotcl!

В недавнем ядре вы можете получить ошибки компиляции. Это легко исправить. Просто вставьте несколько строк вверху исходного файла module / tty0tty.c (после включений):

#ifndef init_MUTEX
#define init_MUTEX(x) sema_init((x),1)
#endif

Когда модуль загружен, он создает 4 пары последовательных портов. Устройства от / dev / tnt0 до / dev / tnt7, где tnt0 подключен к tnt1, tnt2 подключен к tnt3 и т. д. Возможно, вам потребуется исправить права доступа к файлам, чтобы иметь возможность использовать устройства.

редактировать:

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

Во-вторых, TIOCMIWAIT не работает. Код, кажется, скопирован из какого-то примера кода "крошечного терминала". Обработка TIOCMIWAIT кажется на месте, но он никогда не просыпается, потому что соответствующий вызов wake_up_interruptible () отсутствует.

редактировать:

Авария в офисе действительно произошла по вине водителя. Отсутствовала инициализация, и полностью непроверенный код TIOCMIWAIT вызвал сбой машины.

Вчера и сегодня потратил на переписывание драйвера. Было много проблем, но теперь у меня все работает хорошо. По-прежнему отсутствует код для аппаратного управления потоком данных, управляемого драйвером, но он мне не нужен, потому что я сам буду управлять контактами, используя TIOCMGET / TIOCMSET / TIOCMIWAIT из кода пользовательского режима.

Если кого-то заинтересует моя версия кода, напишите мне, и я отправлю его вам.

Мне было бы интересно увидеть ваш код. Можете ли вы внести свой вклад в проект tty0tty? Однако я бы предпочел, чтобы люди улучшали код псевдотерминала в ядре Linux. Например. добавить поддержку аппаратного квитирования и TIOCMIWAIT.

Craig McQueen 20.03.2013 13:47

«Если кого-то заинтересует моя версия кода, отправьте мне сообщение, и я отправлю его вам». Да, мне интересно! Можете ли вы указать на это где-нибудь, например на GitHub?

Craig McQueen 01.07.2013 06:26

Я загрузил драйвер по адресу: github.com/pitti98/nullmodem Извините, что так долго не отвечал. Я не очень активен в stackoverflow и пропустил ваш комментарий!

Peter Remmers 14.11.2013 00:57

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

Peter Remmers 17.11.2013 01:16

Дополняя ответ @ slonik.

Вы можете протестировать socat для создания виртуального последовательного порта, выполнив следующую процедуру (проверено на Ubuntu 12.04):

Откройте терминал (назовем его Терминал 0) и запустите его:

socat -d -d pty,raw,echo=0 pty,raw,echo=0

Приведенный выше код возвращает:

2013/11/01 13:47:27 socat[2506] N PTY is /dev/pts/2
2013/11/01 13:47:27 socat[2506] N PTY is /dev/pts/3
2013/11/01 13:47:27 socat[2506] N starting data transfer loop with FDs [3,3] and [5,5]

Откройте другой терминал и напишите (Терминал 1):

cat < /dev/pts/2

имя порта этой команды может быть изменено в зависимости от компьютера. это зависит от предыдущего вывода.

2013/11/01 13:47:27 socat[2506] N PTY is /dev/pts/**2**
2013/11/01 13:47:27 socat[2506] N PTY is /dev/pts/**3**
2013/11/01 13:47:27 socat[2506] N starting data transfer loop with FDs 

вы должны использовать номер, доступный в выделенной области.

Откройте другой терминал и напишите (Терминал 2):

echo "Test" > /dev/pts/3

Теперь вернитесь в Терминал 1, и вы увидите строку «Тест».

Это сработало для меня лучше, чем ответ slonik, потому что он автоматически назначается файлам виртуального COM-порта и не эхо.

gbmhunter 08.01.2014 08:17

Если вы хотите, чтобы имя файла воспроизводилось, используйте link=/path/to/link после каждого объявления устройства (после echo = 0). Таким образом, его можно использовать в автоматизированных тестах. (как это делает слоник в своем ответе)

Patrick B. 09.08.2017 23:31

Это сработало именно так, как упоминалось. Мне помогло спасибо.

nim118 11.04.2018 11:09

Чтобы создать pty, который подключается к реальному последовательному порту: socat -d -d pty,raw,echo=0 /dev/ttyUSB5,raw,echo=0.

Penghe Geng 31.08.2018 18:28

Могу ли я создать последовательный порт с такими именами, как /dev/ttyS0 вместо /dev/pts/1?

mrid 29.04.2020 13:35

Другие вопросы по теме