???? 終端IO部分整體上讀了兩遍,感覺這一部分的內容又亂又碎,不太好理解。讀完了之后,仍然感覺什么也沒有學到。先做一個膚淺的記錄,等到以后要用到的時候,再回來補充。
???? 終端IO有兩種不同的工作方式,規范方式輸入處理和非規范方式輸入處理:
(1)規范方式輸入處理:終端以行為單位進行處理,對于每個讀要求,終端驅動程序最多返回一行。
(2)非規范方式輸入處理:輸入字符不以行為單位進行處理。
終端設備是由位于內核中的終端驅動程序所控制的,每個終端設備有一個輸入隊列和一個輸出隊列。
???? 關于終端IO的屬性存放在一個? termios? 的結構體中,這個結構體中的成員如下:
tcflag_t c_iflag; /* input modes */tcflag_t c_oflag; /* output modes */tcflag_t c_cflag; /* control modes */tcflag_t c_lflag; /* local modes */cc_t c_cc[NCCS]; /* special characters */
int tcgetattr(int fd, struct termios *termios_p);int tcsetattr(int fd, int optional_actions,const struct termios *termios_p);int tcsendbreak(int fd, int duration);int tcdrain(int fd);int tcflush(int fd, int queue_selector);int tcflow(int fd, int action);speed_t cfgetispeed(const struct termios *termios_p);speed_t cfgetospeed(const struct termios *termios_p);int cfsetispeed(struct termios *termios_p, speed_t speed);int cfsetospeed(struct termios *termios_p, speed_t speed);
UNIX環境高級編程,
???? 下面的一個例子用來禁止終端中的中斷字符(即CTRL+C),并且將文件結束的字符更改為CTRL+B:
#include <termios.h>
#include <stdio.h>
#include <unistd.h>int main(void)
{struct termios term;long vdisable;if(isatty(STDIN_FILENO)==0){printf("standard input is not terminal device\n");return -1;}if( (vdisable=fpathconf(STDIN_FILENO,_PC_VDISABLE))<0 ){printf("fpathconf error\n");return -1;}if(tcgetattr(STDIN_FILENO,&term)<0){printf("tcgetattr error\n");return -1;}term.c_cc[VINTR] = vdisable;term .c_cc[VEOF] = 2;if(tcsetattr(STDIN_FILENO,TCSAFLUSH,&term)<0){printf("tcsetattr error\n");return -1;}return 0;
}
???? 該程序先用? isatty? 函數來測試? STDIN_FILENO? 描述符所指向的文件是否是終端設備,如果測試的文件描述符是指向一個終端設備的話則返回1,否則返回0。
???? 然后使用函數? fpathconf? 獲取系統中的? _PC_VDISABLE? 的值,將這個值保存在? c_cc? 數組中的相應位置就可以禁止使用這個位置所代表的特殊字符。
???? 接著我們調用? tcgetattr? 函數用來獲取終端IO的屬性,然后設置? c_cc? 數組的? VINTR? 的位置為? _PC_VDISABLE,表示禁止使用中斷符號CTRL+C。而將VEOF的位置的值更改為2,即表示將文件的結束符號修改為CTRL+B,同理如果要修改為CTRL+A,則這個地方的值為1。
redis筆記,???? 最后使用? tcsetattr? 函數設置修改過的屬性,使這些屬性生效。tcsetattr? 函數的第二個參數用來表示設置屬性之后,這些屬性生效的時間,這個參數有三種選擇:
TCSANOW:更改立即生效
TCSADRAIN:發送了所有輸出之后,更改才生效。如果更改輸出參數,則應該使用此選項。
TCSAFLUSH:發送了所有輸出之后,更改才生效。這里和上面一個的不同是,當更改發生時,未讀的所有輸入數據都被刪除(丟棄)。
???? (1)ctermid? 函數用來返回控制終端的名字,一般是? /dev/tty。它的函數原型如下:
#include <stdio.h>char *ctermid(char *s);
#include <stdio.h>
#include <string.h>static char ctermid_name[L_ctermid];char* ctermid(char* str)
{if(str==NULL){str = ctermid_name;}return strcpy(str,"/dev/tty"); //strcpy returns str
}
???? (2)isatty? 函數的一種實現如下:
#include <termios.h>
#include <stdio.h>int isatty(int fd)
{struct termios term;return (tcgetattr(fd,&term)!=-1);
}
#include <termios.h>
#include <stdio.h>int isatty(int fd)
{struct termios term;return (tcgetattr(fd,&term)!=-1);
}int main(void)
{printf("fd 0:%s\n",isatty(0)?"tty":"not a tty");printf("fd 1:%s\n",isatty(1)?"tty":"not a tty");printf("fd 2:%s\n",isatty(2)?"tty":"not a tty");return 0;
}
fd 0:tty
fd 1:tty
fd 2:tty
./a.out</etc/passwd 2>/tmp/t
fd 0:not a tty
fd 1:tty
fd 2:not a tty
java筆記總結、???? (3)ttyname? 返回在指定描述符上打開的終端設備的路徑名,例如下面的一個程序可以演示一下它的使用:
#include <unistd.h>
#include <stdio.h>
int main(void)
{printf("fd 0:%s\n",isatty(0)?ttyname(0):"not a tty");printf("fd 1:%s\n",isatty(1)?ttyname(1):"not a tty");printf("fd 2:%s\n",isatty(2)?ttyname(2):"not a tty");return 0;
}
???? linux? 系統提供了一個跟蹤終端大小的功能,內核為每個終端或者是偽終端保存了一個? winsize? 結構體,這個結構體中保存了當前終端大小的信息,這個結構體如下:
struct winsize {unsigned short ws_row;unsigned short ws_col;unsigned short ws_xpixel;unsigned short ws_ypixel;
};
#include <signal.h>
#include <termios.h>
#ifndef TIOCGWINSZ
#include <sys/ioctl.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>static void pr_winsize(int fd)
{struct winsize size;if(ioctl(fd,TIOCGWINSZ,(char*)&size)<0){printf("TIOCGWINSZ error\n");exit(-1);}printf("%d rows,%d columns\n",size.ws_row,size.ws_col);
}static void sig_winch(int signo)
{printf("SIGWINCH received\n");pr_winsize(STDIN_FILENO);return;
}int main(void)
{if(isatty(STDIN_FILENO)==0){exit(1);}if(signal(SIGWINCH,sig_winch)==SIG_ERR){printf("signal error\n");return -1;}pr_winsize(STDIN_FILENO);for(;;){pause();}
}
55 rows,178 columns
SIGWINCH received
6 rows,63 columns
SIGWINCH received
6 rows,124 columns
SIGWINCH received
24 rows,124 columns
SIGWINCH received
53 rows,178 columns
SIGWINCH received
55 rows,178 columns
版权声明:本站所有资料均为网友推荐收集整理而来,仅供学习和研究交流使用。
工作时间:8:00-18:00
客服电话
电子邮件
admin@qq.com
扫码二维码
获取最新动态