Cổng nối tiếp ảo cho Linux


127

Tôi cần kiểm tra một ứng dụng cổng nối tiếp trên Linux, tuy nhiên, máy thử nghiệm của tôi chỉ có một cổng nối tiếp.

Có cách nào để thêm một cổng nối tiếp ảo vào Linux và kiểm tra ứng dụng của tôi bằng cách giả lập một thiết bị thông qua trình bao hoặc tập lệnh không?

Lưu ý: Tôi không thể ánh xạ lại cổng, nó được mã hóa cứng trên ttys2 và tôi cần kiểm tra ứng dụng khi nó được viết.

Câu trả lời:


74

Bạn có thể sử dụng một pty ("pseudo-teletype", trong đó một cổng nối tiếp là "teletype thực") cho việc này. Từ một đầu, mở /dev/ptyp5, và sau đó đính kèm chương trình của bạn vào /dev/ttyp5; ttyp5sẽ hoạt động giống như một cổng nối tiếp, nhưng sẽ gửi / nhận mọi thứ nó thực hiện thông qua / dev / ptyp5.

Nếu bạn thực sự cần nó để nói chuyện với một tập tin được gọi /dev/ttys2, thì chỉ cần di chuyển cái cũ của bạn /dev/ttys2ra khỏi đường và tạo một liên kết tượng trưng từ ptyp5đến ttys2.

Tất nhiên bạn có thể sử dụng một số số khác ptyp5. Có lẽ chọn một số có số lượng lớn để tránh trùng lặp, vì tất cả các thiết bị đầu cuối đăng nhập của bạn cũng sẽ sử dụng ptys.

Wikipedia có nhiều hơn về ptys: http://en.wikipedia.org/wiki/Pseudo_terminal


8
Trên linux, bạn có thể sử dụng các cuộc gọi hệ thống openpty / forkpty. Xem trang người đàn ông
Matthew Smith

8
Làm thế nào để tạo một cặp cổng nối tiếp ảo bằng cách sử dụng công cụ dòng lệnh?
linjunhalida

8
lưu ý rằng nhiều tham số cổng nối tiếp, ví dụ baudrate, chẵn lẻ, điều khiển luồng hw, kích thước ký tự (?) không được triển khai trong pty, do đó không thể kiểm tra ứng dụng của bạn khi có lỗi truyền nối tiếp.
Dima Tisnek

10
Điều này rất hữu ích, nhưng nó mô tả các thiết bị đầu cuối giả BSD "kiểu cũ". Thiết bị đầu cuối giả lập UNIX 98 "kiểu mới" hoạt động hơi khác một chút, xem ptstrang man để biết chi tiết.
Craig McQueen

3
@LaszloPapp Tôi xin lỗi, tôi đã nói dối suốt thời gian
Matthew Smith

160

Bổ sung cho câu trả lời của @ slonik.

Bạn có thể kiểm tra socat để tạo Cổng nối tiếp ảo thực hiện quy trình sau (đã thử nghiệm trên Ubuntu 12.04):

Mở một thiết bị đầu cuối (hãy gọi nó là Terminal 0) và thực hiện nó:

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

Mã trên trả về:

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]

Mở một thiết bị đầu cuối khác và viết (Terminal 1):

cat < /dev/pts/2

Tên cổng của lệnh này có thể được thay đổi theo pc. nó phụ thuộc vào đầu ra trước đó.

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 

bạn nên sử dụng số có sẵn trên khu vực được đánh dấu.

Mở một thiết bị đầu cuối khác và viết (Terminal 2):

echo "Test" > /dev/pts/3

Bây giờ quay lại Terminal 1 và bạn sẽ thấy chuỗi "Kiểm tra".


Điều này làm việc với tôi tốt hơn câu trả lời của slonik, vì nó tự động gán cho các tệp cổng COM ảo và không lặp lại.
gbmhunter

7
Nếu bạn muốn tên tệp có thể lặp lại, hãy sử dụng link=/path/to/linksau mỗi lần khai báo thiết bị (sau echo = 0). Do đó, nó có thể được sử dụng trong các bài kiểm tra tự động. (như slonik làm trong câu trả lời của họ)
Patrick B.

Điều này làm việc chính xác như đã đề cập. Nó giúp tôi cảm ơn.
nim118

1
Để tạo một pty liên kết đến một cổng nối tiếp thực sự : socat -d -d pty,raw,echo=0 /dev/ttyUSB5,raw,echo=0.
Penghe Geng

Tôi có thể tạo một cổng nối tiếp với tên như /dev/ttyS0thay vì /dev/pts/1?
mrid

48

Sử dụng socat cho việc này:

Ví dụ:

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

Điều này làm việc tốt cho tôi, được thử nghiệm với minicom! Có vẻ như đầu vào của một thiết bị đầu cuối được lặp lại cho cả hai (vì vậy nó cũng sẽ xuất hiện lại trên thiết bị đầu cuối đầu vào).
gbmhunter

1
Tôi không có hành vi tiếng vang tương tự ... minicom có ​​tính năng "tiếng vang cục bộ" ... nhưng khi bị tắt, nó hoạt động chính xác như một cổng nối tiếp thực sự. cảm ơn vì tiền hỗ trợ.
cpt Hammer

16

Ngoài ra còn có tty0tty http://sourceforge.net/projects/tty0tty/ là trình giả lập modem null thực sự cho linux.

Nó là một mô-đun hạt nhân đơn giản - một tệp nguồn nhỏ. Tôi không biết tại sao nó chỉ đưa ngón tay cái xuống sourceforge, nhưng nó hoạt động tốt với tôi. Điều tốt nhất về nó là cũng mô phỏng các chân phần cứng (RTC / CTS DSR / DTR). Nó thậm chí còn thực hiện các lệnh iotcl TIOCMGET / TIOCMSET và TIOCMIWAIT!

Trên một kernel gần đây, bạn có thể gặp lỗi biên dịch. Điều này là dễ dàng để sửa chữa. Chỉ cần chèn một vài dòng ở đầu nguồn mô-đun / tty0tty.c (sau bao gồm):

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

Khi mô-đun được tải, nó tạo ra 4 cặp cổng nối tiếp. Các thiết bị là / dev / tnt0 đến / dev / tnt7 trong đó tnt0 được kết nối với tnt1, tnt2 được kết nối với tnt3, v.v. Bạn có thể cần sửa các quyền của tệp để có thể sử dụng các thiết bị.

biên tập:

Tôi đoán rằng tôi đã nhanh một chút với sự nhiệt tình của tôi. Trong khi trình điều khiển có vẻ hứa hẹn, nó có vẻ không ổn định. Tôi không biết chắc chắn nhưng tôi nghĩ rằng nó đã làm hỏng một máy trong văn phòng tôi đang làm việc ở nhà. Tôi không thể kiểm tra cho đến khi tôi trở lại văn phòng vào thứ hai.

Điều thứ hai là TIOCMIWAIT không hoạt động. Mã này dường như được sao chép từ một số mã ví dụ "tty nhỏ". Việc xử lý TIOCMIWAIT có vẻ đúng chỗ, nhưng nó không bao giờ thức dậy vì cuộc gọi tương ứng đến Wake_up_interruptible () bị thiếu.

biên tập:

Vụ tai nạn trong văn phòng thực sự là lỗi của tài xế. Thiếu một khởi tạo và mã TIOCMIWAIT chưa được kiểm tra hoàn toàn đã gây ra sự cố cho máy.

Tôi đã dành ngày hôm qua và hôm nay viết lại trình điều khiển. Có rất nhiều vấn đề, nhưng bây giờ nó hoạt động tốt với tôi. Vẫn còn thiếu mã cho điều khiển luồng phần cứng do trình điều khiển quản lý, nhưng tôi không cần nó bởi vì tôi sẽ tự mình quản lý các chân bằng TIOCMGET / TIOCMSET / TIOCMIWAIT từ mã chế độ người dùng.

Nếu bất cứ ai quan tâm đến phiên bản mã của tôi, hãy gửi cho tôi một tin nhắn và tôi sẽ gửi cho bạn.


2
Tôi rất muốn xem mã của bạn. Bạn có thể đóng góp nó trở lại dự án tty0tty không? Tuy nhiên, tôi muốn thấy mọi người cải thiện mã giả thiết bị đầu cuối trong nhân Linux. Ví dụ: thêm hỗ trợ bắt tay phần cứng và TIOCMIWAIT.
Craig McQueen

3
"Nếu bất cứ ai quan tâm đến phiên bản mã của tôi, hãy gửi cho tôi một tin nhắn và tôi sẽ gửi nó cho bạn." Vâng, tôi quan tâm! Bạn có thể chỉ nó ở đâu đó không, ví dụ như trên GitHub?
Craig McQueen

7
Tôi đã tải trình điều khiển lên: github.com/pitti98/nullmodem Xin lỗi, mất quá nhiều thời gian để trả lời. Tôi không hoạt động nhiều trên stackoverflow và bỏ qua bình luận của bạn!
Peter Remitters

Không, tôi đã viết nó bởi vì tôi cần nó và dừng lại một khi nó đủ tốt để làm những gì tôi muốn. Bây giờ nó là công khai, tôi hy vọng nó hữu ích cho người khác và có thể ai đó nhặt được nơi tôi để nó.
Peter Remmers

8

Bạn có thể muốn xem xét Tibbo VSPDL để tạo cổng nối tiếp ảo linux bằng trình điều khiển Kernel - nó có vẻ khá mới và có sẵn để tải xuống ngay bây giờ (phiên bản beta). Không chắc chắn về giấy phép tại thời điểm này, hoặc liệu họ có muốn cung cấp nó trên thị trường chỉ trong tương lai.

Có những lựa chọn thay thế thương mại khác, chẳng hạn như http://www.ttyredirector.com/ .

Trong Nguồn mở, Remserial (GPL) cũng có thể làm những gì bạn muốn, sử dụng Unix PTY. Nó truyền dữ liệu nối tiếp ở dạng "thô" đến ổ cắm mạng; Việc thiết lập các tham số đầu cuối giống như STTY phải được thực hiện khi tạo cổng, thay đổi chúng sau này như được mô tả trong RFC 2217 dường như không được hỗ trợ. Bạn sẽ có thể chạy hai phiên bản remererial để tạo một nullmodem ảo như com0com, ngoại trừ việc bạn sẽ cần thiết lập tốc độ cổng, v.v.

Socat (cũng là GPL) giống như một biến thể mở rộng của Remserial với nhiều tùy chọn khác, bao gồm phương thức "PTY" để chuyển hướng PTY sang một thứ khác, có thể là một ví dụ khác của Socat. Đối với các đơn vị đơn vị, socat có thể đẹp hơn so với remserial vì bạn có thể trực tiếp đưa các tệp vào PTY. Xem ví dụ PTY trên trang chủ. Một bản vá tồn tại dưới "đóng góp" để cung cấp hỗ trợ RFC2217 để đàm phán cài đặt dòng nối tiếp.


6

Sử dụng các liên kết được đăng trong các câu trả lời trước, tôi đã mã hóa một ví dụ nhỏ trong C ++ bằng Cổng nối tiếp ảo. Tôi đã đẩy mã vào GitHub: https://github.com/cymait/virtual-serial-port-example .

Các mã là khá tự giải thích. Đầu tiên, bạn tạo quy trình chính bằng cách chạy ./main master và nó sẽ in ra thiết bị lỗi chuẩn mà thiết bị đang sử dụng. Sau đó, bạn gọi ./main thiết bị nô lệ, trong đó thiết bị là thiết bị được in trong lệnh đầu tiên.

Và đó là nó. Bạn có một liên kết hai chiều giữa hai quá trình.

Sử dụng ví dụ này, bạn có thể kiểm tra ứng dụng bằng cách gửi tất cả các loại dữ liệu và xem nó có hoạt động chính xác không.

Ngoài ra, bạn luôn có thể liên kết tượng trưng cho thiết bị, vì vậy bạn không cần phải biên dịch lại ứng dụng bạn đang kiểm tra.


1
while (read (fd, & inputbyte, 1) == 1) {...} read không được xác định trong mã của bạn. viết là không xác định. đóng là không xác định.
Mattis Asp

4

Bạn có thể sử dụng bộ chuyển đổi USB-> RS232 không? Tôi có một vài cái, và họ chỉ sử dụng trình điều khiển FTDI. Sau đó, bạn sẽ có thể đổi tên / dev / ttyUSB0 (hoặc bất cứ thứ gì được tạo) thành / dev / ttyS2.


4

Tôi có thể nghĩ về ba lựa chọn:

Thực hiện RFC 2217

RFC 2217 bao gồm một cổng com đến chuẩn TCP / IP cho phép máy khách trên một hệ thống mô phỏng một cổng nối tiếp với các chương trình cục bộ, trong khi gửi và nhận dữ liệu và tín hiệu điều khiển trong suốt đến một máy chủ trên một hệ thống khác thực sự có cổng nối tiếp. Đây là một tổng quan cấp cao .

Những gì bạn sẽ làm là tìm hoặc triển khai trình điều khiển cổng máy khách sẽ triển khai phía máy khách của hệ thống trên PC của bạn - dường như là một cổng nối tiếp thực sự nhưng thực tế lại chuyển mọi thứ đến máy chủ. Bạn có thể có được trình điều khiển này miễn phí từ Digi, Lantronix, v.v. để hỗ trợ các máy chủ cổng nối tiếp độc lập thực sự của họ.

Sau đó, bạn sẽ triển khai phía máy chủ của kết nối cục bộ trong một chương trình khác - cho phép máy khách kết nối và đưa ra các lệnh dữ liệu và điều khiển khi cần.

Nó có thể không tầm thường, nhưng RFC ở ngoài đó và bạn có thể tìm thấy một dự án nguồn mở thực hiện một hoặc cả hai mặt của kết nối.

Sửa đổi trình điều khiển cổng nối tiếp linux

Thay phiên, nguồn trình điều khiển cổng nối tiếp cho Linux có sẵn. Lấy điều đó, rút ​​ra các phần điều khiển phần cứng và để một trình điều khiển chạy hai cổng / dev / ttySx, như một vòng lặp đơn giản. Sau đó kết nối chương trình thực của bạn với ttyS2 và trình giả lập của bạn với ttySx khác.

Sử dụng hai cáp USB <-> Nối tiếp trong một vòng lặp

Nhưng điều dễ nhất để làm ngay bây giờ? Chi 40 đô la cho hai thiết bị USB cổng nối tiếp, nối chúng lại với nhau (modem null) và thực sự có hai cổng nối tiếp thực - một cho chương trình bạn đang thử nghiệm, một cho trình giả lập của bạn.

-Adam


1
Trên thực tế, cáp USB UART của modem null có vẻ như là một giải pháp khá thanh lịch đối với tôi vì nó hỗ trợ cả kiểm tra cục bộ (lấy một bộ chia USB nếu bạn thiếu cổng) và gỡ lỗi từ xa.
Maxthon Chan

Tôi chưa đánh giá chất lượng của nó, nhưng ttynvt thực hiện RFC 2217 thông qua Linux FUSE
Daniel Santos
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.