Віртуальний послідовний порт для 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, тому неможливо перевірити вашу програму на предмет наявності помилок послідовної передачі.
Діма Тиснек

10
Це корисно, але воно описує псевдотермінали BSD "старого стилю". Псевдо-термінали "нового стилю" UNIX 98 працюють трохи інакше - детальніше див. ptsСторінку "man" .
Крейг МакКуін

3
@LaszloPapp Я вибачаюся, весь час брехав
Меттью Сміт

160

Доповнення відповіді @ 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

7
Якщо ви хочете відтворювати ім'я файлу, використовуйте link=/path/to/linkпісля кожного оголошення пристрою (після відлуння = 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

Це добре працювало для мене, перевірене мініміком! Здається, що вхід до одного терміналу перегукується з обома (тому він знову з’явиться і на вхідному терміналі).
gbmhunter

1
У мене немає такої ехо-поведінки ... minicom має функцію "локального відлуння" ... але коли він відключений, він працює точно так, як справжній серійний порт. дякую за пораду.
cptHammer

16

Існує також tty0tty http://sourceforge.net/projects/tty0tty/, який є справжнім емулятором нульового модему для Linux.

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

На останньому ядрі ви можете отримати помилки компіляції. Це легко виправити. Просто вставте кілька рядків у верхній частині джерела модуля / tty0tty.c (після включеного):

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

Коли модуль завантажується, він створює 4 пари послідовних портів. Пристрої / dev / tnt0 to / dev / tnt7, де tnt0 підключено до tnt1, tnt2 підключено до tnt3 і т. Д. Можливо, вам потрібно буде виправити права доступу до файлів, щоб мати можливість використовувати пристрої.

редагувати:

Я здогадуюсь, я трохи захопився своїм захопленням. Хоча водій виглядає багатообіцяючим, він здається нестабільним. Я не знаю точно, але я думаю, що в офісі, над яким я працював, врізалася машина. Я не можу перевірити, поки не повернусь в офіс у понеділок.

Друге, що TIOCMIWAIT не працює. Здається, що код скопійовано з якогось "крихітного" прикладу коду. Робота з TIOCMIWAIT здається на місці, але вона ніколи не прокидається, оскільки відсутній відповідний виклик wake_up_interruptible ().

редагувати:

Аварія в офісі справді була виною водія. Не було ініціалізації, і повністю неперевірений код TIOCMIWAIT спричинив збій машини.

Я вчора і сьогодні переписав водія. Проблем було багато, але зараз це добре працює для мене. Досі відсутній код для керування потоком апаратних засобів, керований драйвером, але він мені не потрібен, оскільки я керую шпильками сам, використовуючи TIOCMGET / TIOCMSET / TIOCMIWAIT з коду режиму користувача.

Якщо когось цікавить моя версія коду, надішліть мені повідомлення, і я надішлю вам його.


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

3
"Якщо когось цікавить моя версія коду, надішліть мені повідомлення, і я надішлю його вам". Так, мені цікаво! Чи можете ви десь вказати на це, наприклад, на GitHub?
Крейг МакКуін

7
Я завантажив драйвер на сторінку: github.com/pitti98/nullmodem Вибачте, що відповісти пройшло так багато часу. Я не дуже активний у стаковому потоці і не помітив ваш коментар!
Пітер Реммерс

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

8

Ви можете подивитися Tibbo VSPDL для створення віртуального послідовного порту Linux за допомогою драйвера Kernel - він здається досить новим і доступний для завантаження прямо зараз (бета-версія). На даний момент не впевнені, що стосується ліцензії, чи вони хочуть зробити її комерційною доступною лише в майбутньому.

Є й інші комерційні альтернативи, такі як http://www.ttyredirector.com/ .

У Open Source Remserial (GPL) також може робити все, що завгодно, використовуючи Unix PTY. Він передає серійні дані у "необробленому вигляді" в мережеву розетку; Установка термінальних параметрів типу STTY повинна бути виконана під час створення порту, їх зміна пізніше, як описано в RFC 2217, схоже, не підтримується. Ви повинні мати змогу запустити два повторних екземпляри для створення віртуальної нульмодеми на зразок com0com, за винятком того, що вам потрібно буде заздалегідь встановити швидкість порту тощо.

Socat (також GPL) - це як розширений варіант Remserial з багатьма іншими можливостями, включаючи метод "PTY" для перенаправлення PTY на щось інше, що може бути ще одним екземпляром Socat. Для одиниць тетів, socat, швидше за все, приємніше, ніж повторне використання, оскільки ви можете безпосередньо вводити файли в PTY Див. Приклад PTY на сторінці сторінки. Патч існує під «вно» , щоб забезпечити підтримку RFC2217 для узгодження параметрів послідовної лінії.


6

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

Код досить зрозумілий. По-перше, ви створюєте головний процес, запустивши ./main master, і він буде надрукований для більш жорсткого використання пристрою. Після цього ви викликаєте ./main підлеглий пристрій, де пристрій - це пристрій, надрукований у першій команді.

І це все. Ви маєте двосторонній зв’язок між двома процесами.

Використовуючи цей приклад, ви можете перевірити програму, надіславши всі види даних, і побачити, чи працює вона правильно.

Крім того, ви завжди можете посилатись на пристрій, тому вам не потрібно повторно компілювати програму, яку ви тестуєте.


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

4

Чи зможете ви використовувати адаптер USB-> RS232? У мене є кілька, і вони просто використовують драйвер FTDI. Тоді ви маєте змогу перейменовувати / dev / ttyUSB0 (або все, що створюється) як / dev / ttyS2.


4

Я можу придумати три варіанти:

Реалізуйте RFC 2217

RFC 2217 охоплює компорт до стандарту TCP / IP, що дозволяє клієнтові в одній системі емулювати послідовний порт для локальних програм, при цьому прозоро надсилаючи та приймаючи дані та управляючі сигнали на сервер іншої системи, який фактично має послідовний порт. Ось огляд високого рівня .

Що б ви зробили, це знайти або реалізувати драйвер клієнтського порту, який би реалізував клієнтську частину системи на вашому ПК - здавалося б, це справжній послідовний порт, але насправді все переносить на сервер. Ви можете отримати цей драйвер безкоштовно від Digi, Lantronix тощо для підтримки їх реальних автономних серверів послідовних портів.

Потім ви будете реалізовувати серверну частину з'єднання локально в іншій програмі - дозволяючи клієнту підключатися та видавати команди даних та керуючі команди за потребою.

Це, мабуть, нетривіально, але RFC є там, і ви, можливо, зможете знайти проект з відкритим кодом, який реалізує одну або обидві сторони з'єднання.

Змініть драйвер послідовного порту Linux

Крім того, джерело драйвера послідовного порту для Linux легко доступний. Візьміть це, маючи апаратні елементи керування, і цей драйвер має два порта / dev / ttySx, як просту петлю. Потім підключіть вашу реальну програму до ttyS2, а ваш тренажер - до іншого ttySx.

Використовуйте два USB <--> послідовних кабелю в циклі

Але найпростіше зробити зараз? Витратьте 40 доларів на два USB-пристрої послідовного порту, з'єднайте їх між собою (нульовий модем) і насправді є два справжні послідовні порти - один для програми, яку ви тестуєте, один для вашого тренажера.

-Адам


1
Насправді нульовий модем USB UART-кабелі здається мені досить елегантним рішенням, оскільки він підтримує локальне тестування (отримайте концентратор USB, якщо вам не вистачає портів) та віддалену налагодження.
Макшон Чан

Я не переглядав її якість, але ttynvt реалізує RFC 2217 через Linux FUSE
Daniel Santos
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.