Virtual Serial Port สำหรับ Linux


129

ฉันต้องการทดสอบแอปพลิเคชันพอร์ตอนุกรมบน Linux อย่างไรก็ตามเครื่องทดสอบของฉันมีพอร์ตอนุกรมเดียวเท่านั้น

มีวิธีเพิ่มพอร์ตอนุกรมเสมือนลงใน Linux และทดสอบแอปพลิเคชันของฉันโดยจำลองอุปกรณ์ผ่านเชลล์หรือสคริปต์หรือไม่

หมายเหตุ: ฉันไม่สามารถทำการแมปพอร์ตใหม่ได้มันยากที่จะเข้ารหัสบน ttys2 และฉันต้องทดสอบแอปพลิเคชันตามที่เขียนไว้

คำตอบ:


75

คุณสามารถใช้ pty ("pseudo-teletype" โดยที่พอร์ตอนุกรมคือ "โทรพิมพ์จริง") สำหรับสิ่งนี้ จากปลายด้านหนึ่งเปิด/dev/ptyp5แล้วแนบโปรแกรมของคุณเข้ากับ/dev/ttyp5; ttyp5จะทำหน้าที่เหมือนพอร์ตอนุกรม แต่จะส่ง / รับทุกอย่างผ่าน / dev / ptyp5

ถ้าคุณต้องการจริงๆมันจะพูดคุยกับไฟล์ที่เรียกว่า/dev/ttys2แล้วก็ย้ายเก่าของคุณ/dev/ttys2ออกจากทางและทำให้ symlink จากไปptyp5ttys2

แน่นอนคุณสามารถใช้หมายเลขอื่น ๆ ptyp5กว่าบาง บางทีเลือกหนึ่งที่มีตัวเลขสูงเพื่อหลีกเลี่ยงการซ้ำกันเนื่องจากเทอร์มินัลการเข้าสู่ระบบทั้งหมดของคุณจะใช้ ptys ด้วย

Wikipedia มีข้อมูลเพิ่มเติมเกี่ยวกับ ptys: http://en.wikipedia.org/wiki/Pseudo_terminal


8
บน linux คุณสามารถใช้การเรียกระบบ openpty / forkpty ดูหน้าคน
Matthew Smith

8
วิธีสร้างคู่พอร์ตอนุกรมเสมือนโดยใช้เครื่องมือบรรทัดคำสั่ง
linjunhalida

8
โปรดทราบว่าพารามิเตอร์พอร์ตอนุกรมจำนวนมากเช่น baudrate, parity, hw flow control, character size (?) ไม่ได้ใช้ใน pty ดังนั้นจึงเป็นไปไม่ได้ที่จะทดสอบแอปพลิเคชันของคุณเมื่อมีข้อผิดพลาดในการส่งแบบอนุกรม
Dima Tisnek

10
สิ่งนี้มีประโยชน์ แต่อธิบายถึงขั้วหลอก BSD "แบบเก่า" เครื่องเทอร์มินัลหลอก "รูปแบบใหม่" UNIX 98 ทำงานแตกต่างกันเล็กน้อยโปรดดูรายละเอียดในptsหน้าคน
Craig McQueen

3
@LaszloPapp ฉันขอโทษฉันโกหกตลอดเวลา
Matthew Smith

161

เติมเต็มคำตอบของ @ slonik

คุณสามารถทดสอบ socat เพื่อสร้าง Virtual Serial Port โดยทำตามขั้นตอนต่อไปนี้ (ทดสอบบน 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]

เปิดเทอร์มินัลอื่นแล้วเขียน (Terminal 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 

คุณควรใช้หมายเลขที่มีอยู่ในบริเวณที่ไฮไลต์

เปิดเทอร์มินัลอื่นและเขียน (Terminal 2):

echo "Test" > /dev/pts/3

กลับไปที่ Terminal 1 แล้วคุณจะเห็นสตริง "Test"


สิ่งนี้ทำงานได้ดีกว่าสำหรับฉันมากกว่าคำตอบของ slonik เพราะมันกำหนดให้กับไฟล์พอร์ต COM เสมือนโดยอัตโนมัติและไม่สะท้อน
gbmhunter

7
หากคุณต้องการใช้ชื่อไฟล์ที่ทำซ้ำได้link=/path/to/linkหลังจากการประกาศอุปกรณ์แต่ละครั้ง (หลังจาก echo = 0) จึงสามารถใช้ในการทดสอบอัตโนมัติ (ตามที่ slonik ตอบ)
Patrick B.

สิ่งนี้ได้ผลตามที่กล่าวไว้ มันช่วยฉันด้วยขอบคุณ
nim118

1
ในการสร้าง pty ที่เชื่อมโยงไปยังพอร์ตอนุกรมจริง: 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

1
ฉันไม่มีพฤติกรรมก้องเหมือนกัน ... มินิคอมมีคุณสมบัติ "เสียงสะท้อนเฉพาะที่" ... แต่เมื่อปิดใช้งานมันจะทำงานเหมือนกับพอร์ตอนุกรมจริง ขอบคุณสำหรับทิป.
cptHammer

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 ไม่ทำงาน ดูเหมือนว่าโค้ดจะคัดลอกมาจากโค้ดตัวอย่าง "tiny tty" ดูเหมือนว่าจะมีการจัดการ TIOCMIWAIT แต่จะไม่ตื่นขึ้นมาเพราะไม่มีการโทรไปยัง wake_up_interruptible () ที่เกี่ยวข้อง

แก้ไข:

ความผิดพลาดในสำนักงานเป็นความผิดของคนขับจริงๆ ไม่มีการกำหนดค่าเริ่มต้นและรหัส TIOCMIWAIT ที่ยังไม่ผ่านการทดสอบอย่างสมบูรณ์ทำให้เครื่องขัดข้อง

ฉันใช้เวลาเมื่อวานนี้และวันนี้เขียนไดรเวอร์ใหม่ มีปัญหามากมาย แต่ตอนนี้มันใช้ได้ดีสำหรับฉัน ยังไม่มีรหัสสำหรับการควบคุมการไหลของฮาร์ดแวร์ที่จัดการโดยไดรเวอร์ แต่ฉันไม่ต้องการเพราะฉันจะจัดการพินด้วยตัวเองโดยใช้ TIOCMGET / TIOCMSET / TIOCMIWAIT จากรหัสโหมดผู้ใช้

หากใครสนใจรหัสรุ่นของฉันโปรดส่งข้อความมาหาฉันแล้วฉันจะส่งไปให้


2
ฉันสนใจที่จะดูรหัสของคุณ คุณช่วยกลับไปที่โครงการ tty0tty ได้ไหม อย่างไรก็ตามฉันอยากเห็นผู้คนปรับปรุงโค้ดเทอร์มินัลหลอกในเคอร์เนลลินุกซ์ เช่นเพิ่มการรองรับการจับมือฮาร์ดแวร์และ TIOCMIWAIT
Craig McQueen

3
"หากใครสนใจรหัสรุ่นของฉันโปรดส่งข้อความมาหาฉันแล้วฉันจะส่งไปให้" ใช่ฉันสนใจ! คุณสามารถชี้ไปที่ใดที่หนึ่งเช่น GitHub ได้ไหม
Craig McQueen

7
ฉันอัปโหลดไดรเวอร์ไปที่: github.com/pitti98/nullmodemขออภัยใช้เวลาตอบกลับนานมาก ฉันไม่ค่อยกระตือรือร้นกับ stackoverflow และมองข้ามความคิดเห็นของคุณไป!
Peter Remmers

ไม่ฉันเขียนมันเพราะฉันต้องการและหยุดเมื่อมันดีพอที่จะทำในสิ่งที่ฉันต้องการ ตอนนี้เป็นที่สาธารณะฉันหวังว่ามันจะมีประโยชน์สำหรับคนอื่นและอาจมีใครบางคนมารับฉันทิ้งไว้
Peter Remmers

8

คุณอาจต้องการดูTibbo VSPDLสำหรับการสร้างพอร์ตอนุกรมเสมือน linux โดยใช้ไดรเวอร์เคอร์เนลดูเหมือนจะค่อนข้างใหม่และพร้อมให้ดาวน์โหลดแล้ว (รุ่นเบต้า) ไม่แน่ใจเกี่ยวกับใบอนุญาต ณ จุดนี้หรือว่าพวกเขาต้องการให้ใช้ในเชิงพาณิชย์เท่านั้นในอนาคต

มีทางเลือกในเชิงพาณิชย์อื่น ๆ เช่นมีhttp://www.ttyredirector.com/

ใน Open Source Remserial (GPL) อาจทำในสิ่งที่คุณต้องการโดยใช้ Unix PTY's ส่งข้อมูลอนุกรมใน "รูปแบบดิบ" ไปยังซ็อกเก็ตเครือข่าย ต้องตั้งค่าพารามิเตอร์เทอร์มินัลแบบ STTY เมื่อสร้างพอร์ตการเปลี่ยนแปลงในภายหลังเหมือนที่อธิบายไว้ใน RFC 2217 ดูเหมือนจะไม่ได้รับการสนับสนุน คุณควรจะสามารถรัน remserial อินสแตนซ์สองตัวเพื่อสร้าง nullmodem เสมือนเช่น com0com ยกเว้นว่าคุณจะต้องตั้งค่าความเร็วพอร์ต ฯลฯ ล่วงหน้า

Socat (เช่น GPL) เปรียบเสมือนตัวแปรเพิ่มเติมของ Remserial ที่มีตัวเลือกอื่น ๆ อีกมากมายรวมถึงวิธี "PTY" สำหรับเปลี่ยนเส้นทาง PTY ไปยังอย่างอื่นซึ่งอาจเป็นอีกตัวอย่างหนึ่งของ Socat สำหรับหน่วย tets socat น่าจะดีกว่า remserial เนื่องจากคุณสามารถ cat ไฟล์ลงใน PTY ได้โดยตรง ดูตัวอย่าง PTYใน manpage มีโปรแกรมแก้ไขภายใต้ "Contrib" เพื่อให้การสนับสนุน RFC2217 สำหรับการเจรจาการตั้งค่าสายอนุกรม


6

ใช้ลิงก์ที่โพสต์ไว้ในคำตอบก่อนหน้านี้ฉันเขียนโค้ดตัวอย่างเล็กน้อยใน C ++ โดยใช้ Virtual Serial Port ฉันผลักรหัสลงใน GitHub: https://github.com/cymait/virtual-serial-port-example

รหัสนี้ค่อนข้างอธิบายตัวเองได้ ขั้นแรกให้คุณสร้างกระบวนการหลักโดยเรียกใช้. / หลักหลักและจะพิมพ์ไปยัง stderr ที่อุปกรณ์ใช้อยู่ หลังจากนั้นคุณจะเรียกใช้. / อุปกรณ์ทาสหลักโดยที่อุปกรณ์คืออุปกรณ์ที่พิมพ์ในคำสั่งแรก

และนั่นแหล่ะ คุณมีลิงก์แบบสองทิศทางระหว่างสองกระบวนการ

การใช้ตัวอย่างนี้คุณสามารถทดสอบแอปพลิเคชันของคุณได้โดยการส่งข้อมูลทุกประเภทและดูว่าทำงานได้ถูกต้องหรือไม่

นอกจากนี้คุณสามารถเชื่อมโยงอุปกรณ์ได้ตลอดเวลาดังนั้นคุณไม่จำเป็นต้องรวบรวมแอปพลิเคชันที่คุณกำลังทดสอบอีกครั้ง


1
ในขณะที่ (read (fd, & inputbyte, 1) == 1) {... } read ไม่ได้กำหนดไว้ในโค้ดของคุณ เขียนไม่ได้กำหนด ปิดไม่ได้กำหนด
Mattis Asp

4

คุณจะสามารถใช้อะแดปเตอร์ USB-> RS232 ได้หรือไม่? ฉันมีไม่กี่คนและพวกเขาใช้ไดรเวอร์ FTDI จากนั้นคุณควรจะสามารถเปลี่ยนชื่อ / dev / ttyUSB0 (หรืออะไรก็ได้ที่สร้างขึ้น) เป็น / dev / ttyS2


4

ฉันคิดได้สามทางเลือก:

ใช้ RFC 2217

RFC 2217ครอบคลุมพอร์ต com เป็นมาตรฐาน TCP / IP ที่อนุญาตให้ไคลเอนต์ในระบบหนึ่งเลียนแบบพอร์ตอนุกรมไปยังโปรแกรมภายในเครื่องในขณะที่ส่งและรับข้อมูลและสัญญาณควบคุมไปยังเซิร์ฟเวอร์บนระบบอื่นอย่างโปร่งใสซึ่งมีพอร์ตอนุกรมจริง นี่คือภาพรวมระดับสูง

สิ่งที่คุณต้องทำคือค้นหาหรือใช้โปรแกรมควบคุมพอร์ตคอมไคลเอนต์ที่จะใช้งานฝั่งไคลเอ็นต์ของระบบบนพีซีของคุณซึ่งดูเหมือนจะเป็นพอร์ตอนุกรมจริง แต่ในความเป็นจริงแล้วจะปิดทุกอย่างไปยังเซิร์ฟเวอร์ คุณอาจสามารถรับไดรเวอร์นี้ได้ฟรีจาก Digi, Lantronix และอื่น ๆ เพื่อรองรับเซิร์ฟเวอร์พอร์ตอนุกรมแบบสแตนด์อโลนที่แท้จริง

จากนั้นคุณจะใช้ฝั่งเซิร์ฟเวอร์ของการเชื่อมต่อในเครื่องในโปรแกรมอื่น - อนุญาตให้ไคลเอนต์เชื่อมต่อและออกข้อมูลและควบคุมคำสั่งได้ตามต้องการ

อาจไม่ใช่เรื่องเล็กน้อย แต่ RFC อยู่ที่นั่นและคุณอาจพบโครงการโอเพ่นซอร์สที่ใช้การเชื่อมต่อด้านใดด้านหนึ่งหรือทั้งสองด้าน

แก้ไขไดรเวอร์พอร์ตอนุกรม linux

อีกวิธีหนึ่งคือแหล่งไดรเวอร์พอร์ตอนุกรมสำหรับ Linux พร้อมใช้งาน รับสิ่งนั้นเอาชิ้นส่วนควบคุมฮาร์ดแวร์และให้ไดรเวอร์หนึ่งตัวรันสองพอร์ต / dev / ttySx เป็นลูปแบ็คแบบธรรมดา จากนั้นเชื่อมต่อโปรแกรมจริงของคุณกับ ttyS2 และโปรแกรมจำลองของคุณกับ ttySx อื่น ๆ

ใช้สาย USB <--> Serial สองเส้นในการวนกลับ

แต่สิ่งที่ง่ายที่สุดที่จะทำในตอนนี้? ใช้จ่าย $ 40 กับอุปกรณ์ USB พอร์ตอนุกรมสองเครื่องเชื่อมต่อเข้าด้วยกัน (โมเด็มว่าง) และมีพอร์ตอนุกรมจริงสองพอร์ตหนึ่งพอร์ตสำหรับโปรแกรมที่คุณกำลังทดสอบหนึ่งพอร์ตสำหรับโปรแกรมจำลองของคุณ

อดัม


1
จริงๆแล้วสายเคเบิล USB UART ของโมเด็มว่างดูเหมือนจะเป็นทางออกที่ดีสำหรับฉันเพราะมันรองรับทั้งการทดสอบในพื้นที่ (รับฮับ USB หากคุณมีพอร์ตสั้น) และการดีบักระยะไกล
Maxthon Chan

ฉันยังไม่ได้ตรวจสอบคุณภาพ แต่ttynvtใช้ RFC 2217 ผ่าน Linux FUSE
Daniel Santos
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.