關鍵詞:GNU/Linux;串口通訊;并口I/O操作;usb存儲設備 中圖分類號:Tll 文獻標識碼:A The Applications of the General I/O in the GNU/Linux LIU Yang,ZHOU Chun-jie (Department of Control Science and Engineering, HuaZhong University of Science & Technology, WuHan 430074, China) Abstract: This paper introduced the detailed operations of three kinds of the general I/O in the GNU/ Linux on the x86 platform, which are the serial communication, the standard parallel ports and the usb mass- storage devices. Key words: GNLT/Linux; serial communication; parallel ports; usb mass - storage 1 引言 GNU/Linux是一個開放源代碼,通用的,符合 POSIX(IEEE Standard Portable Operating System Interface for Computer Environment)標準的操作系統(tǒng)。其健壯、穩(wěn)定、功能強大的特點,在服務器領域與嵌入式設備上極為流行。在通常的PCx86體系下,常用的標準I/O操作有三種:串口,并口、USB口與網(wǎng)口。GNU/Linux作為一種類UNIX系統(tǒng)繼承了UNIX的傳統(tǒng),將所有I/0操作都作為一種特殊的文件操作,程序員只需用通常的open()、 read()、write()、ioctl()、close()等函數(shù)就可以完成大部分的操作,大大減輕了軟件開發(fā)的難度,提高了開發(fā)的效率與可靠性,而這些I/O、的組合使用又基本可以滿足大部分系統(tǒng)的應用。本文以一個實際系統(tǒng)為例,說明了基于PCx86體系下的串口、并口與USB口操作,網(wǎng)口由于其本身的特殊性,在本文就不作為一般的I/O介紹了。系統(tǒng)硬件示意圖如下,主控板為一塊586級的嵌入式主板PCM一5820,主頻為300Mhz、外擴128Mb內存、16M電子盤,主控板自帶兩個串口,一個標準25針并口,兩個USB口等接口;需要完成的功能有:與下層的一塊51為核心的按鍵顯示板通訊,讀入鍵值與刷新顯示;同時還需每10ms采集8路開關量輸入,通過一定的程序處理后輸出1路開關量;并不定期對采集的數(shù)據(jù)記錄做備份。實際系統(tǒng)正常工作時,實現(xiàn)長時間無人值守與可靠運行,本身要求有較高的穩(wěn)定性。本文將從串口、并口、USB口三個方面介紹。
2 串口通訊實現(xiàn) 根據(jù)按鍵顯示板本身對通訊要求,具有一定的偶發(fā)性和要求有交互性,我們利用主控板上的串口選用RS232的通訊方式。由于在Linux下,串口一般作為一個終端接口,即tty接口,POSIX.1定義了一個查詢和操作終端的標準接口,該接口被稱作 termios,在系統(tǒng)的頭文件
中定義。 termios是一個數(shù)據(jù)結構和一系列操作這些數(shù)據(jù)結構的函數(shù)。 #include struct termios{ tcflag-t c-iflag;/*指明輸入方式的標志位*/ tcflag-t c-oflag;/*指明輸出方式的標志位*/ tcflag-t c-cflag;/*指明控制方式的標志位*/ tcflag-t c-lflag;/*指明局部方式的標志位*/ cc-t c-line;/*指明分行定義*/ cc-t C-CC[NCCS];/*指明用于控制的特殊字符*/ speed-t c-ispeed;/*指明輸入傳輸速度*/ speed-t c-ospeed;/*指明輸出傳輸速度*/ } 對終端訪問的控制函數(shù)如下: 這些函數(shù)一起共構成了通用的終端界面,提供對終端的有效控制操作,使得系統(tǒng)具有復雜的異步串口設備處理能力[4]。 RS232C只是一個物理層接口,為了保障數(shù)據(jù)傳輸?shù)臏蚀_性與可靠性,須用戶自己保證數(shù)據(jù)傳輸正確,根據(jù)本系統(tǒng)通訊的特點:如果發(fā)生通訊,每次主機只會從按鍵顯示板接收到一幀包含按鍵信息的數(shù)據(jù),而每次按鍵都是獨立事件;主控板向鍵盤顯示板發(fā)送一定數(shù)據(jù)更新顯示。按照此需求,定義通訊協(xié)議如下:接收時,每幀數(shù)據(jù)長度為5字節(jié),發(fā)送時,每幀數(shù)據(jù)長度為12字節(jié),波特率為9600B/s,1位停止位,8位數(shù)據(jù)位,不帶奇偶校驗。發(fā)送與接收的幀格式都是一樣的,幀首字節(jié)固定為0x55,第二個字節(jié)是本幀數(shù)據(jù)長度,最末兩字節(jié)為校驗和,其余為數(shù)據(jù);緊跟著兩個相鄰數(shù)據(jù)包之間沒有關系,不需要幀序號,同時兩板之間距離很近,干擾源較少,因此誤碼率很低,用和校驗就可保證傳輸?shù)恼`碼率。具體設計實現(xiàn)如下: 具體設計時為了保證一定的系統(tǒng)響應速度,同時盡量減少主控板系統(tǒng)資源的使用,使用Linux下的信號驅動機制,使用SIGIO信號,當有下位機傳按鍵至主控板時,操作系統(tǒng)發(fā)出一個信號,用戶程序進入信號處理程序。初始化串口時,調用open()函數(shù),打開設備文件ttyS0,發(fā)送和接收數(shù)據(jù)時就可以直接使用read()和write()函數(shù),類似文件一樣使用串口。 3 并口操作實現(xiàn) 并口,有時也稱打印口,最初設計用于連接計算機和打印機。許多年后,其他很多設備也通過并口與計算機進行連接,例如掃描儀、可移動設備和復制保護設備等。現(xiàn)代PC上,并口有8根雙向數(shù)據(jù)線、四根雙向控制線以及5根狀態(tài)輸入線,他們通過一個DB一25凹口連接器供外部進行訪問。從并口發(fā)明之初到現(xiàn)在,共發(fā)展出4種類型,實際系統(tǒng)中,主板的bios可以設置并口類型,本系統(tǒng)將主控板設為標準并口類型(SPP)。 在GNU/Linux下,一般對于PC并口進行數(shù)據(jù)采集和控制有3種方法。第一種方法使用端口 I/O,簡單、操作性強,并且可以清楚說明編寫設備驅動程序開發(fā)所必需的底層硬件控制過程。第二種方法使用Linux并口設備驅動程序ppdev來控制并口。這種方法與通過使用設備驅動程序及 ioctl系統(tǒng)調用進行串口控制的方法相似。第三種方法創(chuàng)建自己訂制的并口驅動程序,這個并口驅動 程序使用/proc目錄。本系統(tǒng)要求達到每10ms采集一次開關量的要求,并根據(jù)運算結果,輸出一個開關量;可以利用并口中的pin2 - pin9數(shù)據(jù)口,一次將8個開關量全部采集,并通過程序判斷,輸出結果至pin1口。采用第一種方法就能滿足本系統(tǒng)的要求,因此具體實現(xiàn)如下: 在Linux中有一個用于輸入的命令inb(ad— dress)和一個用于輸出的命令outb(value,address)。 C語言的宏擴展實現(xiàn)了這兩個函數(shù),而且不涉及任何函數(shù)庫,但使用這兩個函數(shù)需要一些額外的函數(shù),函數(shù)ioperm()從內核中申請和釋放端口訪問權[7]。 向并口寫入一個字節(jié)代碼如下: if(ioperm(0x378,3,1) ) exit (1); outb ( LP-DATA, 0x378); if( ioperm(0X378,3,0 )) exit(1); 從并口讀人一個字節(jié)代碼如下: if(ioperm(Ox378,3,1)) exit(1); putc(inb(Ox378) ); if( ioperm(OX378,3,0)) exit (1); 只要在上述代碼增加少量代碼就可以作為一個完整的代碼。這種方法也有缺點,只有root用戶才能調用ioperm函數(shù),這會影響沒有root權限的用戶使用該程序,而且如果用戶想使用除了數(shù)據(jù)位以外的控制位作為輸出或輸入信號鎖存輸出值時,則會帶來很大困難,另外,這樣的程序實現(xiàn)可重入,將會面臨很大難度。但在本系統(tǒng)中,由于正式系統(tǒng)不存在用戶登錄的問題,同時,并口只會被本進程使用,不存在重入的問題。 為了保證每10ms的讀一次并口,利用Linux系統(tǒng)中的信號機制,使用settimer()函數(shù),每10ms產生一次SIGALRM信號,在這個信號的中斷函數(shù)里,采集一次開關量。保證了系統(tǒng)的實時性T4。 4 USB口用于數(shù)據(jù)備份具體實現(xiàn) 由于系統(tǒng)是24小時不停機的長時間運行,本身采集的數(shù)據(jù)量是比較大的,可是主控板本身的存儲空間很小,而現(xiàn)場不具備安裝網(wǎng)線的條件,所以需要考慮一種盡可能不增加硬件投資,又可以獲得高可靠性,同時考慮到數(shù)據(jù)量比較大,對傳輸速率要求比較高,一般的串口已經(jīng)無法滿足要求,因此,采用USB的傳輸方案,利用u盤將現(xiàn)場的數(shù)據(jù)暫存,回到控制中心,再將數(shù)據(jù)倒入數(shù)據(jù)庫。另外,為了減少工作人員的工作量,利用Linux本身特有的 RAMDISK功能,將內存中分出70Mb作為暫存區(qū),并將這部分作為系統(tǒng)的另一個分區(qū),在系統(tǒng)啟動的時候,直接掛載到系統(tǒng)中。 對于2.4.x的內核來說,USB存儲設備驅動已經(jīng)集成在內核里,但驅動程序只與Linux SCSI層交互。這意味著,在配置內核時,除了配置USB選項之外,還需要配置某些SCSI選項,選擇支持合適的文件系統(tǒng)。在內核已支持USB存儲設備的情況下,當USB設備接人系統(tǒng)的USB口后,直接使用外部命令mount和umount的命令就可以將 USB存儲設備掛載到系統(tǒng)和解除掛載了。用cp等外部命令就可以將需要備份的數(shù)據(jù)從暫存區(qū)移動至USB存儲設備中。在程序中,使用system函數(shù)可以完成對外部命令程序的調用。具體實現(xiàn)過程如下: 1、檢測外部USB設備是否掛載到系統(tǒng)上,檢查/proc/bus/usb/deviees文件,是否已經(jīng)正確掛載上去,其次,根據(jù)/proc/scsi/目錄中設備文件的內容,生成mount命令的第一個參數(shù);2、用system函數(shù)調用mount命令,將USB存儲設備掛載至文件系統(tǒng)節(jié)點/mnt下; 3、用system函數(shù)調用cp命令,將ramdisk中的內容拷貝到該目錄下; 4、用system函數(shù)調用umount命令,將移動介質卸載調。 5 總結 系統(tǒng)已經(jīng)在現(xiàn)場運行了半年,從運行的效果來看,串口通訊采用IO信號驅動的方式完全可以適應其偶發(fā)性與一定的實時性,并口經(jīng)常作為IO數(shù)據(jù)的采集與輸出,采用定時掃描,而linux2.4.26操作系統(tǒng)的最小時間間隙100Hz,保證了每10ms采集一次的要求;USB口由于其傳輸數(shù)據(jù)量大、可靠,作為大數(shù)據(jù)量與交換,在Linux下,所有u盤和活動硬盤必須遵循USB mass—storage協(xié)議才能穩(wěn)定可靠運行。另外,針對不同的硬件應該制作不同的Linux內核,充分利用內核的模塊化,使用最少模塊的內核,完成盡可能多的任務?,F(xiàn)在系統(tǒng)已經(jīng)開始實際運行,從運行的效果來開,所有的指標都可以滿足當初的設計要求,本身Linux系統(tǒng)的穩(wěn)定性,完全可以實現(xiàn)無人值守。 參考文獻 [1] (美)Kurt Wall等.張輝譯.GNU/Linx編程指南(第二版)[M].北京:清華