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


128

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

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

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

Ответы:


75

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

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

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

В Википедии есть дополнительная информация о ptys: http://en.wikipedia.org/wiki/Pseudo_terminal


8
В Linux вы можете использовать системные вызовы openpty / forkpty. См. Справочную страницу
— Мэтью Смит,

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

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

10
Это полезно, но описывает псевдотерминалы BSD «старого стиля». Псевдотерминалы UNIX 98 «нового стиля» работают немного иначе - подробности см. На ptsстранице руководства.
— Craig McQueen

3
@LaszloPapp: Прошу прощения, я все время лгал
— Мэтью Смит,

160

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

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

Откройте терминал (назовем его Terminal 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

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

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

1
Чтобы создать псевдотерминал, ссылки на реальный последовательный порт: socat -d -d pty,raw,echo=0 /dev/ttyUSB5,raw,echo=0.
— Penghe Geng

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

48

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

Например:

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

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

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

16

Также существует 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 из кода пользовательского режима.

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


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

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

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

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

8

Вы можете посмотреть Tibbo 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 для согласования настроек последовательной линии.


6

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

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

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

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

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


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

4

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


4

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

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

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

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

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

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

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

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

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

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

-Адам


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

Я не проверял его качество, но ttynvt реализует RFC 2217 через Linux FUSE
— Даниэль Сантос,
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.