如何检查一个键是否在Linux中被按下?
我假设你想在终端模拟器上(而不是在X客户端上)这样做,并且你不关心密钥版本。
执行此操作的Linux方法是使用termios(3)将终端设置为非规范或原始模式,然后使用通常的libc函数读取stdin。
Linux上的系统调用编号位于/usr/include/asm/unistd.h(或unistd_64.h)上,但termios函数最终转换为ioctl()。所以,如果你因为一些奇怪的和不寻常的原因而不能调用libc,你将不得不查找ioctl的系统调用号,以及ioctl对应的termios函数。
编辑:
显然,你假设Linux使用相同的模型DOS,其中控制台输入是键盘的抽象(与像的keyPressed,GETC功能,...)而控制台输出是面向字符显示的抽象。
Unix/Linux的抽象是关于终端,它可以是物理控制台,串口上的终端(或终端仿真器),xterm,...这里重要的一点是,默认情况下,输入行直到终端(或终端仿真器)看到一个行分隔符时才会被提供给程序。
在POSIX上,这些终端受termios(3)
功能的控制。 Linux的最终翻译那些的ioctl()调用,如下(见tty_ioctl(4)
):
- tcgetattr(FD,ARG)=>的ioctl(FD,TCGETS,ARG)
- tcsetattr(FD,TCSANOW,精氨酸)=>的ioctl(FD,TCSETS,ARG)
- tcsetattr(FD,TCSADRAIN,ARG)=>的ioctl(FD,TCSETSW,ARG)
- tcsetattr(FD,TCSAFLUSH,ARG)=>的ioctl(FD,TCSETSF ,arg)
- ...
所以,一个C程序做你要的是什么,使用termios(3)
和poll(2)
(检查剥离的简洁和清晰的错误):现在
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <poll.h>
#include <signal.h>
#include <termios.h>
#include <sys/ioctl.h>
static sig_atomic_t end = 0;
static void sighandler(int signo)
{
end = 1;
}
int main()
{
struct termios oldtio, curtio;
struct sigaction sa;
/* Save stdin terminal attributes */
tcgetattr(0, &oldtio);
/* Make sure we exit cleanly */
memset(&sa, 0, sizeof(struct sigaction));
sa.sa_handler = sighandler;
sigaction(SIGINT, &sa, NULL);
sigaction(SIGQUIT, &sa, NULL);
sigaction(SIGTERM, &sa, NULL);
/* This is needed to be able to tcsetattr() after a hangup (Ctrl-C)
* see tcsetattr() on POSIX
*/
memset(&sa, 0, sizeof(struct sigaction));
sa.sa_handler = SIG_IGN;
sigaction(SIGTTOU, &sa, NULL);
/* Set non-canonical no-echo for stdin */
tcgetattr(0, &curtio);
curtio.c_lflag &= ~(ICANON | ECHO);
tcsetattr(0, TCSANOW, &curtio);
/* main loop */
while (!end) {
struct pollfd pfds[1];
int ret;
char c;
/* See if there is data available */
pfds[0].fd = 0;
pfds[0].events = POLLIN;
ret = poll(pfds, 1, 0);
/* Consume data */
if (ret > 0) {
printf("Data available\n");
read(0, &c, 1);
}
}
/* restore terminal attributes */
tcsetattr(0, TCSANOW, &oldtio);
return 0;
}
,ioctl
和poll
是系统调用,你可以找到关于他们的人数/ usr/include/asm/unistd.h(x86上的54和168)和/usr/include/asm/ioctls.h具有您需要的ioctl常量(在x86上:TCGETS = 0x5401,TCSETS = 0x5402,TCSETSW = 0x5403, TCSETSF = 0x5404)。
我想使用中断服务。我知道dos中断有这样的服务,所以我认为这也适用于linux ... – Sason 2010-10-19 08:05:03
不,ninjalj已经描述了你需要的东西。在Linux(i386体系结构)上,可以使用int 0x80与eax中的服务编号进行系统调用。但是,与DOS不同,没有直接调用“检查按键是否被按下”。由于原因,请参阅http://en.wikipedia.org/wiki/Ring_%28computer_security%29和http://en.wikipedia。组织/维基/ User_space。类Unix系统使用终端抽象,除非你想修改Linux本身,否则你必须遵循ninjalj的指示。 – 2010-10-19 22:10:19
你不应该做一个系统调用来做到这一点吗? – 2010-10-18 18:42:24
Linux中的系统调用ARE中断。 – 2010-10-18 19:00:55
投票结束,因为不清楚。用什么语言?做什么? C版本:http://stackoverflow.com/questions/2984307/c-key-pressed-in-linux-console – 2016-07-02 10:38:34