Linux için Sanal Seri Bağlantı Noktası


129

Linux'ta bir seri bağlantı noktası uygulamasını test etmem gerekiyor, ancak test makinemin yalnızca bir seri bağlantı noktası var.

Linux'a sanal bir seri bağlantı noktası eklemenin ve bir aygıtı bir kabuk veya komut dosyası aracılığıyla taklit ederek uygulamamı test etmenin bir yolu var mı?

Not: Bağlantı noktasını yeniden eşleştiremiyorum, ttys2'ye sabit olarak kodlandı ve uygulamayı yazıldığı gibi test etmem gerekiyor.

Yanıtlar:


75

Bunun için bir pty ("sözde teletip", burada bir seri bağlantı noktası "gerçek bir teletiptir") kullanabilirsiniz. Bir uçtan, /dev/ptyp5programınızı açın ve ardından /dev/ttyp5; ttyp5tıpkı bir seri bağlantı noktası gibi davranacak, ancak yaptığı her şeyi / dev / ptyp5 yoluyla gönderecek / alacak.

Eğer çağrılan bir dosyayla gerçekten konuşmaya ihtiyacınız varsa /dev/ttys2, o zaman /dev/ttys2eskinizi yoldan çıkarın ve arasında bir sembolik bağlantı ptyp5oluşturun ttys2.

Elbette dışında bir sayı da kullanabilirsiniz ptyp5. Tüm oturum açma terminalleriniz de ptys kullanacağından, yinelemeleri önlemek için belki de yüksek numaralı bir tane seçin.

Wikipedia'da ptys hakkında daha fazla bilgi var: http://en.wikipedia.org/wiki/Pseudo_terminal


8
Linux'ta openpty / forkpty sistem çağrılarını kullanabilirsiniz. Man sayfasına
Matthew Smith

8
komut satırı aracını kullanarak sanal seri bağlantı noktası çifti nasıl oluşturulur?
linjunhalida

8
baud hızı, parite, hw akış kontrolü, karakter boyutu (?) gibi birçok seri port parametresinin pty olarak uygulanmadığını, bu nedenle uygulamanızı seri iletim hataları durumunda test etmeniz imkansız olduğunu unutmayın.
Dima Tisnek

10
Bu yararlıdır, ancak "eski tarz" BSD sözde terminallerini tanımlar. "Yeni stil" UNIX 98 sözde terminalleri biraz farklı çalışır - ayrıntılar için ptsman sayfasına bakın.
Craig McQueen

3
@LaszloPapp Özür dilerim, her zaman yalan söylüyordum
Matthew Smith

161

@ Slonik'in cevabını tamamlamak.

Aşağıdaki prosedürü uygulayarak Sanal Seri Bağlantı Noktası oluşturmak için socat'ı test edebilirsiniz (Ubuntu 12.04'te test edilmiştir):

Bir terminal açın (buna Terminal 0 diyelim) ve çalıştırın:

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

Yukarıdaki kod şunu döndürür:

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]

Başka bir terminal açın ve (Terminal 1) yazın:

cat < /dev/pts/2

bu komutun port adı bilgisayara göre değiştirilebilir. önceki çıktıya bağlıdır.

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 

vurgulanan alanda bulunan numarayı kullanmalısınız.

Başka bir terminal açın ve (Terminal 2) yazın:

echo "Test" > /dev/pts/3

Şimdi Terminal 1'e dönün ve "Test" dizesini göreceksiniz.


Bu benim için slonik'in cevabından daha iyi çalıştı, çünkü sanal COM port dosyalarına otomatik olarak atıyor ve yankı yapmıyor.
gbmhunter

7
Yeniden üretilebilir bir dosya adı istiyorsanız, link=/path/to/linkher aygıt bildiriminden sonra (echo = 0'dan sonra) kullanın. Bu nedenle otomatik testlerde kullanılabilir. (slonik'in cevabında yaptığı gibi)
Patrick B.

Bu tam olarak belirtildiği gibi çalıştı. Bana teşekkür etti.
nim118

1
Gerçek bir seri port bağlantıları olduğu bir pty oluşturmak için: socat -d -d pty,raw,echo=0 /dev/ttyUSB5,raw,echo=0.
Penghe Geng

/dev/ttyS0yerine gibi isimlerle bir seri bağlantı noktası oluşturabilir /dev/pts/1miyim?
mrid

48

Bunun için socat kullanın:

Örneğin:

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

Bu benim için iyi çalıştı, minicom ile test edildi! Görünüşe göre bir terminale giriş her ikisine de yankılanıyor (böylece giriş terminalinde de yeniden görünecek).
gbmhunter

1
Aynı yankı davranışına sahip değilim ... minicom'un "yerel yankı" özelliği var ... ama devre dışı bırakıldığında, tam olarak gerçek bir seri bağlantı noktası gibi çalışıyor. Bahşiş için teşekkürler.
cptHammer

16

Ayrıca linux için gerçek bir boş modem emülatörü olan tty0tty http://sourceforge.net/projects/tty0tty/ de vardır .

Basit bir çekirdek modülüdür - küçük bir kaynak dosyası. Sourceforge'da neden sadece beğenilmediğini bilmiyorum, ama benim için iyi çalışıyor. Bununla ilgili en iyi şey, donanım pinlerini de (RTC / CTS DSR / DTR) taklit etmesidir. TIOCMGET / TIOCMSET ve TIOCMIWAIT iotcl komutlarını bile uygular!

Yeni bir çekirdekte derleme hataları alabilirsiniz. Bunu düzeltmek kolaydır. Modül / tty0tty.c kaynağının üst kısmına birkaç satır eklemeniz yeterlidir (içerilenlerden sonra):

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

Modül yüklendiğinde 4 çift seri port oluşturur. Aygıtlar / dev / tnt0 ile / dev / tnt7 arasındadır; burada tnt0, tnt1'e, tnt2, tnt3'e bağlıdır, vb. Aygıtları kullanabilmek için dosya izinlerini düzeltmeniz gerekebilir.

Düzenle:

Sanırım coşkumla biraz hızlı davrandım. Sürücü umut verici görünse de dengesiz görünüyor. Kesin olarak bilmiyorum ama evden çalıştığım ofiste bir makinenin düştüğünü düşünüyorum. Pazartesi ofise dönene kadar kontrol edemem.

İkinci şey, TIOCMIWAIT'in çalışmamasıdır. Kod, bazı "küçük tty" örnek kodundan kopyalanmış görünüyor. TIOCMIWAIT'in işlenmesi yerinde görünüyor, ancak karşılık gelen wake_up_interruptible () çağrısı eksik olduğu için asla uyanmıyor.

Düzenle:

Ofisteki kaza gerçekten sürücünün hatasıydı. Bir başlatma eksikti ve tamamen test edilmemiş TIOCMIWAIT kodu makinenin çökmesine neden oldu.

Dünü ve bugünü sürücüyü yeniden yazarak geçirdim. Çok fazla sorun vardı ama şimdi benim için iyi çalışıyor. Sürücü tarafından yönetilen donanım akış kontrolü için hala kod eksik, ancak buna ihtiyacım yok çünkü pinleri kullanıcı modu kodundan TIOCMGET / TIOCMSET / TIOCMIWAIT kullanarak kendim yöneteceğim.

Kodun versiyonuyla ilgilenen varsa, bana bir mesaj gönderin, ben de size göndereyim.


2
Kodunuzu görmek isterim. Tty0tty projesine geri katkıda bulunabilir misiniz? Ancak, insanların Linux çekirdeğindeki sözde terminal kodunu geliştirdiklerini görmeyi tercih ederim. Örneğin, donanım anlaşması desteği ve TIOCMIWAIT ekleyin.
Craig McQueen

3
"Kodun versiyonuyla ilgilenen varsa, bana bir mesaj gönderin, ben de size göndereyim." Evet, ilgileniyorum! Bir yere, örneğin GitHub'a işaret edebilir misiniz?
Craig McQueen

7
Sürücüyü şu adrese yükledim : github.com/pitti98/nullmodem Üzgünüm yanıt vermem çok uzun sürdü. Stackoverflow konusunda pek aktif değilim ve yorumunuzu gözden kaçırdım!
Peter Remmers

Hayır, ona ihtiyacım olduğu için yazdım ve istediğimi yapmak için yeterince iyi olduğunda durdum. Artık halka açık olduğuna göre, umarım başkası için yararlıdır ve belki birisi bıraktığım yerden devam eder.
Peter Remmers

8

Bir Kernel sürücüsü kullanarak bir linux sanal seri bağlantı noktası oluşturmak için Tibbo VSPDL'ye bakmak isteyebilirsiniz - oldukça yeni görünüyor ve şu anda indirilebilir (beta sürümü). Bu noktada lisans hakkında emin değilim veya lisansı yalnızca gelecekte ticari olarak kullanılabilir hale getirmek isteyip istemedikleri.

Http://www.ttyredirector.com/ gibi başka ticari alternatifler de vardır .

Açık Kaynakta, Remserial (GPL), Unix PTY'leri kullanarak da istediğinizi yapabilir. Seri verileri "ham formda" bir ağ soketine iletir; Bağlantı noktası oluşturulurken terminal parametrelerinin STTY benzeri kurulumu yapılmalıdır, bunları daha sonra RFC 2217'de açıklandığı gibi değiştirmek desteklenmiyor gibi görünmektedir. Com0com gibi sanal bir nullmodem oluşturmak için iki remserial örneği çalıştırabilmeniz gerekir, ancak önceden bağlantı noktası hızını vb. Ayarlamanız gerekir.

Socat (ayrıca GPL), PTY'yi başka bir şeye yeniden yönlendirmek için bir "PTY" yöntemi de dahil olmak üzere daha birçok seçeneğe sahip genişletilmiş bir Remserial varyantı gibidir; bu, Socat'ın başka bir örneği olabilir. Unit tets için, socat muhtemelen reyserial olmaktan daha iyidir çünkü dosyaları doğrudan PTY'ye aktarabilirsiniz. Man sayfasındaki PTY örneğine bakın . Seri hat ayarlarının anlaşılması için RFC2217 desteği sağlamak için "katkı" altında bir yama bulunmaktadır .


6

Önceki cevaplarda yayınlanan bağlantıları kullanarak, Sanal Seri Port kullanarak C ++ 'da küçük bir örnek kodladım. Kodu GitHub'a aktardım: https://github.com/cymait/virtual-serial-port-example .

Kod oldukça açıklayıcıdır. Önce ./main master'ı çalıştırarak ana işlemi yaratırsınız ve aygıtın kullandığı stderr'e yazdırır. Bundan sonra, aygıtın ilk komutta basılan aygıt olduğu ./main bağımlı aygıtı çağırırsınız.

Ve bu kadar. İki işlem arasında çift yönlü bir bağlantınız var.

Bu örneği kullanarak her türlü veriyi göndererek uygulamayı test edebilir ve doğru çalışıp çalışmadığını görebilirsiniz.

Ayrıca, cihazı her zaman sembolik bağlayabilirsiniz, böylece test ettiğiniz uygulamayı yeniden derlemenize gerek kalmaz.


1
while (read (fd, & inputbyte, 1) == 1) {...} okuma kodunuzda tanımsızdır. yazma tanımsız. yakın tanımsız.
Mattis Asp

4

Bir USB-> RS232 adaptörü kullanabilir misiniz? Birkaç tane var ve sadece FTDI sürücüsünü kullanıyorlar. Sonra, / dev / ttyUSB0'ı (veya oluşturulan her şeyi) / dev / ttyS2 olarak yeniden adlandırabilmeniz gerekir.


4

Üç seçenek düşünebilirim:

RFC 2217'yi uygulayın

RFC 2217 , bir sistemdeki bir istemcinin yerel programlara bir seri bağlantı noktası taklit etmesine izin verirken, aynı zamanda seri bağlantı noktasına sahip başka bir sistemdeki bir sunucuya şeffaf bir şekilde veri gönderip alır ve sinyalleri kontrol etmesine olanak tanıyan TCP / IP standardına bir com bağlantı noktasını kapsar. İşte üst düzey bir genel bakış .

Yapacağınız şey, sistemin istemci tarafını PC'nizde uygulayacak bir istemci com port sürücüsü bulmak veya uygulamaktır - gerçek bir seri bağlantı noktası gibi görünse de gerçekte her şeyi bir sunucuya aktarır. Bu sürücüyü, gerçek bağımsız seri bağlantı noktası sunucularını desteklemek için Digi, Lantronix, vb.'den ücretsiz olarak edinebilirsiniz.

Daha sonra, bağlantının sunucu tarafını başka bir programda yerel olarak uygularsınız - istemcinin bağlanmasına ve gerektiğinde veri ve kontrol komutlarını vermesine izin verirsiniz.

Muhtemelen önemsiz değildir, ancak RFC oradadır ve bağlantının bir veya iki tarafını uygulayan açık kaynaklı bir proje bulabilirsiniz.

Linux seri port sürücüsünü değiştirin

Alternatif olarak, Linux için seri bağlantı noktası sürücü kaynağı kullanıma hazırdır. Bunu alın, donanım denetim parçalarını çıkarın ve tek bir sürücünün iki / dev / ttySx bağlantı noktasını basit bir geri döngü olarak çalıştırmasını sağlayın. Ardından gerçek programınızı ttyS2'ye ve simülatörünüzü diğer ttySx'e bağlayın.

Geridöngüde iki USB <--> Seri kablo kullanın

Ama şu anda yapılacak en kolay şey? İki seri bağlantı noktalı USB cihazına 40 dolar harcayın, bunları birbirine bağlayın (boş modem) ve aslında iki gerçek seri bağlantı noktasına sahip olun - biri test ettiğiniz program için, diğeri simülatörünüz için.

-Adam


1
Aslında boş modem USB UART kabloları, hem yerel testi (bağlantı noktalarında kısaysanız bir USB hub'ı edinin) hem de uzaktan hata ayıklamayı desteklediği için oldukça şık bir çözüm gibi görünüyor.
Maxthon Chan

Kalitesini gözden geçirmedim , ancak ttynvt RFC 2217'yi Linux FUSE aracılığıyla uyguluyor
Daniel Santos
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.