[英]Non-blocking stdio
我正在開發一個程序,它將從控制台接收用戶輸入以及在單獨的線程中打印出來。 我想避免用戶在輸入內容的中途並且printf出現並在光標處打印自己的情況。
有沒有辦法在控制台窗口中執行c中的非阻塞io? 理想情況下,捕獲按鍵或類似的東西,使得用戶鍵入的內容不會出現在屏幕上。 我正在開發Ubuntu,如果我不必使用像ncurses這樣的東西,那就最好了。
使用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 */
}
這是一個如何從C關閉回聲的示例,直接來自HP論壇 (我還沒有親自測試過):
好的,這應該是一個關閉echo的簡單例子:
#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重置終端是非常重要的,因為最后一個tcsetattr()獲勝,這適用於終端設備而不僅僅是進程。 如果你將回顯關閉,那么它也將在shell中關閉。
否則,如果Bash是一個合適的方法,顯然你可以做stty -echo
。
如果我正確理解您的問題,關閉回聲或使用非阻塞I / O不是答案。 相反,你想防止后台線程中斷用戶輸入線程,對吧?
為此,您需要訪問原始按鍵而不是行緩沖輸入。 我不知道你為什么對ncurses或類似的圖書館過敏; 這就是他們的目的! 我想你可以用termios或ioctl調用來做,如果這就是你如何滾動....
但要解決多線程TTY輸出問題,您可以這樣做:
1)創建一個互斥鎖來控制誰可以訪問控制台
在后台線程中 ,輸出一條消息:
抓住互斥體; 寫信息; 釋放互斥鎖; 回去睡覺!
在用戶輸入線程中:
檢測到新輸入時抓取互斥鎖。 在用戶點擊進入之前保持獨占訪問權限,然后釋放互斥鎖並為后台主題提供通話機會。
這有幫助嗎?
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.