Linux終端輸入輸出(termios)函數

來源:互聯網
上載者:User
termios系列函數-tcgetattr, tcsetattr, tcsendbreak, tcdrain, tcflush, tcflow, cfmakeraw, cfgetospeed, cfgetispeed, cfsetispeed, cfsetospeed, cfsetspeed等,用以擷取/設定終端裝置的屬性/控制/速度。
1. 函式宣告
函式宣告
#include <termios.h>#include <unistd.h>/*擷取檔案描述符fd對應裝置狀態置入termios_p所指向結構體中*/int tcgetattr(int fd, struct termios *termios_p);/*設定檔案描述符對應裝置狀態*/int tcsetattr(int fd, int optional_actions, const struct termios *termios_p);/*向fd發送0位元*/int tcsendbreak(int fd, int duration);/*掛起直到所有寫入fd的輸出全部發送完畢*/int tcdrain(int fd);/*丟棄所有準備寫入但還未發送給fd的資料或從fd已接收但還還未被讀取的資料*//*丟棄對象取決於queue_selector*/int tcflush(int fd, int queue_selector);/*掛起fd發送操作或接收操作,掛起對象取決於action*/int tcflow(int fd, int action);/*裝置終端屬性*/void cfmakeraw(struct termios *termios_p);/*返回termios_p所指向結構體中的輸入傳輸速率*/speed_t cfgetispeed(const struct termios *termios_p);/*返回termios_p所指向結構體中的輸出傳輸速率*/speed_t cfgetospeed(const struct termios *termios_p);/*設定termios_p所指向結構體中的輸入傳輸速率*/int cfsetispeed(struct termios *termios_p, speed_t speed);/*設定termios_p所指向結構體中的輸出傳輸速率*/int cfsetospeed(struct termios *termios_p, speed_t speed);/*4.4BSD擴充,設定輸入輸出傳輸速率*/int cfsetspeed(struct termios *termios_p, speed_t speed); 
glibc功能測試宏定義:
cfsetspeed(), cfmakeraw(): _BSD_SOURCE
2. termios結構體
大多數termios函數都會用到termios結構。termios結構體定義如下:
 
typedef unsigned char   cc_t;typedef unsigned int    speed_t;typedef unsigned int    tcflag_t;struct termios{tcflag_t c_iflag;       /* input mode flags */tcflag_t c_oflag;       /* output mode flags */tcflag_t c_cflag;       /* control mode flags */tcflag_t c_lflag;       /* local mode flags */cc_t c_line;            /* line discipline */cc_t c_cc[NCCS];        /* control characters */speed_t c_ispeed;       /* input speed */speed_t c_ospeed;       /* output speed */#define _HAVE_STRUCT_TERMIOS_C_ISPEED 1#define _HAVE_STRUCT_TERMIOS_C_OSPEED 1};
c_iflag標誌常量
  • IGNBRK 忽略輸入BREAK條件 
  • BRKINT 如果設定了IGNBRK,BREAK將會被忽略;如果僅僅設定了BRKINT,BREAK將會丟棄輸入和輸出隊列中的資料(flush),並且如果終端為前台進程組的控制終端,則BREAK將會產生一個SIGINT訊號發送到這個前台進程組。如果IGNBRK和BRKINT均未設定,BREAK將會被當作讀入了null位元組('\0'),除非設定了PARMRK標誌被設定,在這種情況下,BREAK將會被當作讀入了\377\0\0序列。 
  • IGNPAR 忽略幀錯誤和同位錯誤 
  • PARMRK 如果未設定IGNPAR標誌,在帶有同位錯誤或幀錯誤的字元前使用\377\0來標誌;如果IGNPAR和PARMRK均未設定,則將同位錯誤的字元當作\0 
  • INPCK 允許輸入同位 
  • ISTRIP 剝離第8個bit 
  • INLCR 將輸入中的NL轉換成CR 
  • IGNCR 忽略輸入中的斷行符號 
  • ICRNL 將輸入中的CR轉換為NL 
  • IUCLC (非POSIX)將輸入中的大寫字元轉換為小寫 
  • IXON 允許輸出端的XON/XOFF流控 
  • IXANY (XSI)任意擊鍵將會重啟已停止的輸出(預設情況僅允許使用START字元來重啟輸出) 
  • IXOFF 允許輸入端XON/XOFF流控 
  • IMAXBEL (非POSIX)輸入隊列滿時響鈴。Linux未實現此標誌位,總是以此標誌位被設定的情況動作 
  • IUTF8 (從Linux 2.6.4開始支援,非POSIX)輸入為UTF8編碼 
c_oflag標誌常量定義(POSIX.1):
  • OPOST 允許實現定義的輸出處理 
  • OLCUC (非POSIX)將輸出中的小寫字母映射為大寫 
  • ONLCR (XSI)將輸出中的NL映射為CR-NL 
  • OCRNL 將輸出中的CR映射為NL 
  • ONOCR 不在第零列輸出CR 
  • ONLRET 不輸出CR 
  • OFILL 發送填充字元實現延遲,而不是使用時間上的延遲 
  • OFDEL (非POSIX)填充字元為ASCII DEL(0177)。如果未設定,填充字元為ASCII NUL('\0')。(Linux中未實現) 
  • NLDLY 新行延遲掩碼。值為NL0和NL1。(需要_BSD_SOURCE或_SVID_SOURCE或_XOPEN_SOURCE) 
  • CRDLY 斷行符號(CR)延遲掩碼。值為CR0,CR1,CR2,或CR3。(需要_BSD_SOURCE或_SVID_SOURCE或_XOPEN_SOURCE) 
  • TABDLY 水平定位字元延遲掩碼。值為TAB0,TAB1,TAB2,TAB3(或XTABS)。值TAB3/XTABS表示將定位字元擴充為空白格(每8列為一個定位字元停止位)。(需要_BSD_SOURCE或_SVID_SOURCE或_XOPEN_SOURCE) 
  • BSDLY 回退符延遲掩碼。值為BS0或BS1.(從未實現)(需要_BSD_SOURCE或_SVID_SOURCE或_XOPEN_SOURCE) 
  • VTDLY 垂直定位字元延遲掩碼。值為VT0或VT1。 
  • FFDLY 表單輸入延遲掩碼。值為FF0或FF1.(需要_BSD_SOURCE或_SVID_SOURCE或_XOPEN_SOURCE) 
c_cflag標誌常量:
  • CBAUD (非POSIX)傳輸速率速率掩碼(4+1位元)。(需要_BSD_SOURCE或_SVID_SOURCE或_XOPEN_SOURCE) 
  • CBAUDEX (非POSIX)附加傳輸速率速率掩碼(1位元),包含在CBAUD中。(需要_BSD_SOURCE或_SVID_SOURCE或_XOPEN_SOURCE) 
  • CSIZE 字元尺寸掩碼。值為CS5,CS6,CS7,或CS8 
  • CSTOPB 設定兩個停止位(bits),而不是一位 
  • CREAD 允許接收器 
  • PARENB 允許輸出端生產同位位元,輸入端進行校正 
  • PARODD 如設定,則輸入輸出端同位為奇數同位;未設定則為偶校正 
  • HUPCL 上一次操作關閉裝置後將數據機控制線設為低電平(掛起) 
  • CLOCAL 忽略數據機控制線 
  • LOBLK (非POSIX)阻塞非當前shell層輸出。(Linux未實現) 
  • CIBAUD (非POSIX)輸入速率掩碼。 
  • CMSPAR (非POSIX)使用"stick"同位:如果設定了PARODD,將奇偶檢驗位總是置為1;如果未設定PARODD,同位位元總是置為0. 
  • CRTSCTS 允許RTS/CTS(硬體)流控。(需要_BSD_SOURCE或_SVID_SOURCE) 
c_lflag標誌常量:
  • ISIG 當接收到INTR/QUIT/SUSP/DSUSP字元,產生一個相應的訊號 
  • ICANON 允許canonical模式 
  • XCASE (非POSIX,Linux不支援)如果設定了ICANON,終端僅為大寫字元模式。輸入字元被轉換為小寫,除非以'\'開始;輸出端,大寫字元以'\'開始,小寫字元被轉換為大寫 
  • ECHO 回顯所輸入的字元 
  • ECHOE 如果同時設定了ICANON標誌,ERASE字元刪除前一個所輸入的字元,WERASE刪除前一個輸入的單詞 
  • ECHOK 如果同時設定有ICANON標誌,KILL字元刪除當前行 
  • ECHONL 如果同時設定有ICANON標誌,回顯NL字元即使ECHO未設定 
  • ECHOCTL (非POSIX)如果同時設定有ECHO標誌,除TAB/NL/START/STOP外的ASCII控制字元將會被回顯成'^X',其中X為控制符數值加0x40 
  • ECHOPRT (非POSIX)如果同時設定有ICANON和IECHO,字元以已刪除方式列印 
  • ECHOKE (非POSIX)如果設定有ICANON,KILL以刪除所在行所有字元方式顯示 
  • DEFECHO (非POSIX)僅當有進程讀取時回顯字元(Linux未實現) 
  • FLUSHO (非POSIX,LINUX不支援)輸出被丟棄。 
  • NOFLSH 當產生SIGINT/SIGQUIT/SIGSUSP訊號時禁止丟棄(flush)輸入輸出隊列 
  • TOSTOP 當後台進程試圖寫入自己的控制終端時,發送SIGTTOU訊號給進程組 
  • PENDIN (非POSIX,Linux不支援) 
  • IEXTEN 允許實現所定義的輸入處理。 
c_cc數組定義了一些特殊控制字元:
  • VINTR 003,ETX,Ctrl-C,0177,DEL,rubout,中斷字元。發送SIGINT訊號。 
  • VQUIT 034,FS,Ctrl-\,退出字元。發送SIGQUIT訊號。 
  • VERASE 0177,DEL,rubout,010,BS,Ctrl-H,#, 刪除字元。刪除上一個未刪除的字元,但不刪除前面的EOF或者行開始字元。 
  • VKILL 025,NAK,Ctrl-U,Cgtrl-X,@,Kill字元。刪除自上一個EOF或行開始字元之後的所有輸入字元。 
  • VEOF 004,EOT,Ctrl-D,檔案結尾(End-of-file)。EOF將會讓掛起的tty緩衝區內容發送給處於等待中的使用者程式,而不用等待行結束標識(End-of-line)。 
  • VMIN 非canonical模式讀操作的最少字元數 
  • VEOL (0,NUL)額外的行結束符(End-of-line) 
  • VTIME 非canonical模式讀操作逾時(單位為1/10秒) 
  • VEOL2 (非POSIX;0,NUL)另一個行結束標識 
  • VSWTCH (非POSIX;Linux不支援;0,NUL)切換字元 
  • VSTART 021,DC1,Ctrl-Q,開始字元。重啟被STOP字元停止的輸出 
  • VSTOP 023,DC3,Ctrl-S,停止字元。停止輸出直到START 
  • VSUSP 032,SUB,Ctrl-Z,掛起字元。發送SIGSTP訊號 
  • VDSUSP (非POSIX;Linux不支援)031,EM,Ctrl-Y,延遲掛起字元:當使用者程式讀取字元時發送SIGTSTP訊號 
  • VLNEXT (非POSIX)026,SYN,Ctrl-V,標識下一個字元為字面意思而非可能的特殊控制含義 
  • VWERASE (非POSIX)027,ETC,Ctrl-W,單詞刪除 
  • VREPRINT (非POSIX)022,DC2,Ctrl-R,再次列印未讀取字元 
  • VDISCARD (非POSIX;Linux不支援)017,SI,Ctrl-O,開關切換:開始/停止丟棄掛起的輸出 
  • VSTATUS (非POSIX;Linux不支援)024,DC4,Ctrl-T,狀態請求 
3. 擷取/更改終端設定
tcgetattr(),tcsetattr()分別用於擷取/更改終端設定
  • tcgetattr() 擷取fd所指定終端的設定並存放入termios結構指標termios_p指向的地址空間;後台進程所擷取的終端設定也可能隨後被前台進程更改 
  • tcsetattr() 設定指定終端的屬性。可選動作項指定終端屬性何時更改: 
    • TCSANOW 立即更改 
    • TCSADRAIN 當寫入fd的所有輸出發送完畢後更改 
    • TCSAFLUSH 所有寫入fd的輸出發送完畢,並且所有已接收但未讀入的輸入被丟棄後更改設定 
4. Canonical和non-canonical模式
c_lflag欄位中的ICANON標誌決定終端是否工作在canonical模式。預設情況下,終端為canonical模式
canonical模式
  • 輸入工作在行模式。收到行定界符(NL,EOL,EOL2;或行首的EOF)後,輸入行可供讀取。read操作所讀取的行內容包含行定界符。 
  • 允許行編輯(ERASE,KILL;如設定了IEXTEN標誌,WERASE,REPRINT,LNEXT)。 
non-canonical模式下,無需使用者輸入行定界符,輸入立即可讀取。
c_cc[VTIME]和c_cc[VMIN]對read操作的影響: 
 
  • MIN==0;TIME==0:如有資料可用,read立即返回min(請求數量,可用字元數量)個字元;如無資料可用,read返回0 
  •  
  • MIN>0;TIME==0:read阻塞,直到至少有min(請求數量,MIN)個字元可用,read返回兩值中較小的一個 
  • MIN==0;TIME>0:TIME指定讀取逾時(單位為1/10秒)。當調用read時設定定時器。當至少有一個字元可用或逾時後,read返回。如果在逾時前無可用字元,read返回0 
  • MIN>0;TIME>0:TIME指定讀取逾時,收到輸入的第一個字元後重啟定時器。read在讀取到MIN和所請求數量兩者中較少的字元,或逾時後,返回。至少會讀取到一個字元。 
5. Raw模式
cfmakeraw()設定終端工作在"raw"模式下:輸入以字元方式提供,禁止回顯,所有特殊字元被禁止。
raw模式下,終端屬性如下:
  1. termios_p->c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP   
  2.                       | INLCR | IGNCR | ICRNL | IXON);   
  3. termios_p->c_oflag &= ~OPOST;   
  4. termios_p->c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);   
  5. termios_p->c_cflag &= ~(CSIZE | PARENB);   
  6. termios_p->c_cflag |= CS8;  
termios_p->c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP                      | INLCR | IGNCR | ICRNL | IXON);termios_p->c_oflag &= ~OPOST;termios_p->c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);termios_p->c_cflag &= ~(CSIZE | PARENB);termios_p->c_cflag |= CS8;
6. 線控
控制與終端的串連
  • tcsendbreak 如果終端工作在非同步串列資料發送模式,在指定時間長度內發送0位元流。如果時間長度為0,發送0位元流至少0.25s,但不多於0.5s。如果終端未工作在非同步串列資料發送模式,tcsendbreak立刻返回不作任何操作。 
  • tcdrain() 等待直到所有輸出至fd的資料均被發送 
  • tcflush() 丟棄已寫入fd但還未發送的資料,或丟棄已接收但還未讀取的資料。丟棄對象取決於queue_selector: 
    • TCIFLUSH 丟棄已接收但還未讀取的資料 
    • TCOFLUSH 丟棄已寫入但還未發送的資料 
    • TCIOFLUSH 丟棄以上兩種 
  • tcflow() 掛起fd的發送或接收操作。掛起對象取決於action: 
    • TCOOFF 掛起輸出 
    • TCOON 重啟掛起的輸出 
    • TCIOFF 發送STOP字元,停止終端裝置向系統發送資料 
    • TCION 發送START字元,啟動裝置向系統發送資料 
7. 線速
控制輸入/輸出傳輸速率
設定傳輸速率為B0會使數據機掛起(Hang up)。B38400對應的實際速率可能會受到setserial(8)的影響。 
 
  • cfgetospeed()返回輸出傳輸速率 
  • cfsetospeed()設定輸出傳輸速率為B0/B50/B75/B110/B134/B150/B200/B300/B600/B1200/B1800/B2400/B4800/B9600/B38400/B57600/B115200/B230400*B0用於終止串連 
  • cfgetispeed() 返回輸入傳輸速率 
  • cfsetispeed() 設定輸入傳輸速率 
  • cfsetspeed() 4.4BSD擴充,同時將輸入輸入傳輸速率設定為同一值 
8. 傳回值
標識函數調用結果
  • cfgetispeed()/cfgetospeed() 返回輸入/輸出傳輸速率 
  • 對其他函數,傳回值為0表示成功;-1表示失敗,errno給出錯誤*對於tcsetattr(),只要任一要更改的屬性設定成功,則會返回成功。 
9. 例
擷取標準輸入終端(STDIN)的屬性並更改標準輸入終端為raw模式(也可以使用更簡便的調用-cfmakeraw()完成),接收鍵盤輸入、顯示索引值,直到接收到Ctrl-b輸入。
·········10········20········30········40········50········60········70········80········90········100·······110·······120·······130·······140·······150
  1. #include <stdio.h>   
  2. #include <unistd.h>   
  3. #include <termios.h>   
  4. #include <errno.h>   
  5. #include <string.h>   
  6. #include <stdlib.h>   
  7.   
  8. #define BUF_LENGTH 255   
  9.   
  10. int main(void)   
  11. {   
  12.     int ret = 0;   
  13.     char buf[BUF_LENGTH]={0};   
  14.     int i = 0;   
  15.   
  16.     struct termios newtmios={0};   
  17.     struct termios oldtmios={0};   
  18.   
  19.     ret = tcgetattr(STDIN_FILENO, &oldtmios);   
  20.     if ( ret )   
  21.     {   
  22.         printf("tcgetattr() error, errno = 0x%X\n", errno);   
  23.         return -1;   
  24.     }   
  25.   
  26.     memcpy(&newtmios, &oldtmios, sizeof(struct termios));   
  27.     newtmios.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP   
  28.                 | INLCR | IGNCR | ICRNL | IXON);   
  29.     newtmios.c_oflag &= ~OPOST;   
  30.     newtmios.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);   
  31.     newtmios.c_cflag &= ~(CSIZE | PARENB);   
  32.     newtmios.c_cflag |= CS8;   
  33.   
  34.     ret = tcsetattr(STDIN_FILENO, TCSANOW, &newtmios);   
  35.     if ( ret )   
  36.     {   
  37.         printf("tcsetattr() error, errno = 0x%X\n", errno);   
  38.         return -2;   
  39.     }   
  40.   
  41.     printf("Press any key(Ctrl-b to quit) :\n ");   
  42.     tcdrain(STDIN_FILENO);   
  43.     while ( 1 )   
  44.     {   
  45.         ret = read(STDIN_FILENO, buf, BUF_LENGTH);   
  46.         if ( ret )   
  47.         {   
  48.             printf("\rread %d chars, you pressed ", ret);   
  49.             for(i=0; i<ret;i++) printf(" 0x%02X ", buf[i]);   
  50.             printf("\r\n");   
  51.   
  52.             if ( (1==ret) && (0x02 == buf[0]) )   
  53.             {   
  54.                 break;   
  55.             }   
  56.         }   
  57.     }   
  58.   
  59.     ret = tcsetattr(STDIN_FILENO, TCSANOW, &oldtmios);   
  60.     return ret;   
  61. }  
相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.