簡體   English   中英

非阻塞stdio

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM