2009-08-14 160 views
3

我正在研究一個程序,它將從控制檯接收用戶輸入以及在單獨的線程中進行打印輸出。我想避免用戶在輸入內容並輸出printf並在光標處自行打印的情況。非阻塞stdio

有沒有辦法在控制檯窗口中執行c中的非阻塞io?理想情況下,捕獲按鍵或類似的東西,使用戶輸入的內容不會出現在屏幕上。我在Ubuntu中開發,如果我不需要使用ncurses這樣的東西,那最好。

回答

2

這裏有一個如何從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

4

使用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 */ 
} 
+0

感謝您的支持。爲什麼'ECHONL'? – 2015-03-02 02:32:54

0

關閉回波或使用非阻塞I/O是不是答案,如果我正確理解你的問題。相反,你想阻止後臺線程中斷用戶輸入線程,對吧?

爲此,您需要訪問原始按鍵而不是線路緩衝輸入。我不知道你爲什麼對ncurses或類似的圖書館過敏;這就是他們的目標!我想你可以用的termios或ioctl調用做到這一點,如果這就是你怎麼滾....

但爲您解決多線程TTY輸出的問題,你可以這樣做:

1)創建一個互斥以控制誰可以訪問控制檯

在後臺線程,以輸出信息:

抓鬥互斥;寫信息;釋放互斥量;回去睡覺!

在用戶輸入線程:

抓鬥檢測新的輸入時互斥。保持獨佔訪問,直到用戶點擊輸入, 然後釋放互斥量併爲後臺線程提供聊天機會。

這是否幫助?

+0

查看原始終端模式下的cfmakeraw()。請務必在調用此函數之前保存termios結構,以便在完成後恢復它。 – 2009-08-14 18:40:36