我正在研究一個程序,它將從控制檯接收用戶輸入以及在單獨的線程中進行打印輸出。我想避免用戶在輸入內容並輸出printf並在光標處自行打印的情況。非阻塞stdio
有沒有辦法在控制檯窗口中執行c中的非阻塞io?理想情況下,捕獲按鍵或類似的東西,使用戶輸入的內容不會出現在屏幕上。我在Ubuntu中開發,如果我不需要使用ncurses這樣的東西,那最好。
我正在研究一個程序,它將從控制檯接收用戶輸入以及在單獨的線程中進行打印輸出。我想避免用戶在輸入內容並輸出printf並在光標處自行打印的情況。非阻塞stdio
有沒有辦法在控制檯窗口中執行c中的非阻塞io?理想情況下,捕獲按鍵或類似的東西,使用戶輸入的內容不會出現在屏幕上。我在Ubuntu中開發,如果我不需要使用ncurses這樣的東西,那最好。
這裏有一個如何從C關閉回聲,直接從an HP forum採取的一個例子(我沒有親自測試過):
好吧,這應該是一個簡單的例子 回聲關閉的:
#include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <termios.h> #define STDIN_FDES 0 struct termios save; int main(int argc, char *argv[]) { int cc = 0; char s_tmp[80],*p = NULL; struct termios work; cc = tcgetattr(STDIN_FDES,&save); work = save; work.c_lflag &= ~(ECHO); cc = tcsetattr(STDIN_FDES,TCSANOW,&work); (void) printf("\nEnter value: "); (void) fflush(stdout); p = fgets(s_tmp,sizeof(s_tmp),stdin); if (p != NULL) (void) printf("Out -> %s\n",p); cc = tcsetattr(STDIN_FDES,TCSANOW,&save); return(cc); }
注意:您 有信號處理趕上SIGINT, SIGTERM,......並利用原有的termios重置終端 這是非常重要的,因爲 last tcsetattr()獲勝並且這將 應用於終端設備,而不僅僅是 進程。如果您離開 回收過程,它也將在外殼 中關閉。
否則,如果bash是一個合適的方法,顯然你可以做stty -echo
。
使用termios
可以禁用終端呼應:
#include <termios.h>
struct termios oflags, nflags;
tcgetattr(fileno(stdin), &oflags);
nflags = oflags;
nflags.c_lflag &= ~ECHO;
nflags.c_lflag |= ECHONL;
if (tcsetattr(fileno(stdin), TCSANOW, &nflags) != 0) {
/* handle error */
}
然後退出(使用atexit
)之前,必須恢復終端:
if (tcsetattr(fileno(stdin), TCSANOW, &oflags) != 0) {
/* handle error */
}
關閉回波或使用非阻塞I/O是不是答案,如果我正確理解你的問題。相反,你想阻止後臺線程中斷用戶輸入線程,對吧?
爲此,您需要訪問原始按鍵而不是線路緩衝輸入。我不知道你爲什麼對ncurses或類似的圖書館過敏;這就是他們的目標!我想你可以用的termios或ioctl調用做到這一點,如果這就是你怎麼滾....
但爲您解決多線程TTY輸出的問題,你可以這樣做:
1)創建一個互斥以控制誰可以訪問控制檯
在後臺線程,以輸出信息:
抓鬥互斥;寫信息;釋放互斥量;回去睡覺!
在用戶輸入線程:
抓鬥檢測新的輸入時互斥。保持獨佔訪問,直到用戶點擊輸入, 然後釋放互斥量併爲後臺線程提供聊天機會。
這是否幫助?
查看原始終端模式下的cfmakeraw()。請務必在調用此函數之前保存termios結構,以便在完成後恢復它。 – 2009-08-14 18:40:36
感謝您的支持。爲什麼'ECHONL'? – 2015-03-02 02:32:54