C

如何實時直接讀取鍵盤輸入?

  • January 26, 2013

我不確定這最終是否是問這個問題的正確地方,但我正在開發一個需要使用者實時輸入的程序。那是; 它需要能夠實時讀取被按下(以及可選地按住和釋放)的鍵。讓這個問題有點麻煩的是,我絕對不能為此使用任何類型的庫;甚至不是標準的 C 庫。所以這需要使用原始核心系統呼叫和int 0x80.

我想我會將標準輸入設置為非阻塞模式,fcntl然後O_NONBLOCK從標準輸入讀取輸入數據。但是,令我驚訝的是,我的程式碼似乎無法正常工作。現在似乎在按下 Enter 鍵*後從標準輸入讀取輸入。*棘手的部分是我發現很難弄清楚這是否是以下原因的錯:

  • 我的程式碼行為不正確(很可能)
  • 我的終端/使用者/程序(無論處理它嗎?)沒有對標準輸入的非阻塞寫訪問(不太可能)。
  • 我錯誤地假設我可以從標準輸入讀取直接鍵盤輸入。

所以我的問題是,如果不是通過將標準輸入設置為非阻塞模式並從那裡讀取鍵盤輸入數據,那麼讀取直接鍵盤互動的最佳/通常方法是什麼?還是我是正確的,應該只修復我的程式碼?:)

(對於好奇的人,不,它不是鍵盤記錄器。它適用於大小非常有限(可執行大小 <= 256 字節)的展示場景產品,需要使用者能夠從介紹中退出。)

如果您要從 閱讀stdin,您應該閱讀 的聯機幫助頁tcsetattr,特別是有關“規範和非規範模式”的部分 ( ICANON)。除非你禁用ICANONon stdin,否則輸入是面向行的(在按下 Enter 之前你什麼也得不到)。即使對於O_NONBLOCK.

如果有疑問,strace -v stty raw &gt;&log; stty sane; grep TCSETSW log看看它對stdin. 您可以使用具有相同參數的相同系統呼叫來取消終端。請注意,除非您在退出時恢復設置,否則程序終止後終端將無用。(這就是我stty sane之後做的原因stty raw

使用原始硬體 I/O 可能是一個非常糟糕的主意,除非您絕對確定您的目標硬體,和/或您希望預測存在的每種類型的鍵盤。

哦,儘管它是“原始的”,但您仍然從鍵盤讀取一些經過處理的輸入:您不會得到掃描碼,您會得到 ASCII(或 UTF-8,很可能)。所以 Escape 是十進制的 27,而不是 1(就像在最初的 IBM PC 鍵盤上一樣)。

需要超級使用者訪問的替代建議:閱讀事件設備,打開正確的設備並從中讀取 Linux 事件結構。此方法返回原始的按下/釋放事件和鍵(它們是核心的內部鍵碼,但不是硬體掃描碼)。查看詳情/usr/include/linux/input.h。當然,找到合適的eventX設備以打開 256 字節的程式碼完全是另一回事。

引用自:https://unix.stackexchange.com/questions/29830