Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在Linux中检查是否按下了键?_Linux - Fatal编程技术网

如何在Linux中检查是否按下了键?

如何在Linux中检查是否按下了键?,linux,Linux,我需要知道Linux中哪个中断会检查是否按下了任何键?我假设您希望在终端仿真器上(而不是在X客户机上)执行此操作,并且您不关心键的释放 Linux实现这一点的方法是使用termios(3)将终端设置为非规范模式或原始模式,然后使用常用的libc函数读取stdin Linux上的系统调用号在/usr/include/asm/unistd.h(或unistd_64.h)上,但termios函数最终会转换为ioctl()。因此,如果由于某些奇怪和不寻常的原因而无法调用libc,则必须查找ioctl的s

我需要知道Linux中哪个中断会检查是否按下了任何键?

我假设您希望在终端仿真器上(而不是在X客户机上)执行此操作,并且您不关心键的释放

Linux实现这一点的方法是使用termios(3)将终端设置为非规范模式或原始模式,然后使用常用的libc函数读取stdin

Linux上的系统调用号在/usr/include/asm/unistd.h(或unistd_64.h)上,但termios函数最终会转换为ioctl()。因此,如果由于某些奇怪和不寻常的原因而无法调用libc,则必须查找ioctl的syscall号码,以及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,arg)=>ioctl(fd,TCSETS,arg)
  • tcsetattr(fd,TCSADRAIN,arg)=>ioctl(fd,TCSETSW,arg)
  • tcsetttr(fd,TCSAFLUSH,arg)=>ioctl(fd,TCSETSF,arg)
因此,使用
termios(3)
poll(2)
(为了简洁和清晰起见,错误检查被剥离了),一个C程序可以完成您要求的任务:

#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
静态信号原子端=0;
静态无效信号发生器(内部信号)
{
结束=1;
}
int main()
{
结构termios oldtio,curtio;
struct-sigaction-sa;
/*保存stdin终端属性*/
tcgetattr(0,&oldtio);
/*确保我们干净地离开*/
memset(&sa,0,sizeof(struct-sigaction));
sa.sa_handler=sighandler;
sigation(SIGINT,&sa,NULL);
sigaction(SIGQUIT,&sa,NULL);
sigation(SIGTERM,&sa,NULL);
/*这是在挂断(Ctrl-C)后能够启动tcsetattr()所必需的
*请参见POSIX上的tcSetttr()
*/
memset(&sa,0,sizeof(struct-sigaction));
sa.sa_handler=SIG_IGN;
sigation(sigttoo,&sa,NULL);
/*为标准输入设置非规范无回显*/
tcgetattr(0和curtio);
curtio.c|lflag&=~(ICANON | ECHO);
tcsetattr(0、TCSANOW和curtio);
/*主回路*/
当(!结束){
结构pollfd pfds[1];
int ret;
字符c;
/*看看是否有可用的数据*/
pfds[0].fd=0;
pfds[0]。事件=POLLIN;
ret=投票(pfds,1,0);
/*消费数据*/
如果(ret>0){
printf(“可用数据”);
读取(0,&c,1);
}
}
/*恢复终端属性*/
tcSetttr(0、TCSANOW和oldtio);
返回0;
}

现在,
ioctl
poll
是系统调用,您可以在/usr/include/asm/unistd.h(x86上为54和168)上找到它们的编号,并且/usr/include/asm/ioctls.h具有您需要的ioctl常量(x86上为:tcget=0x5401,tcset=0x5402,TCSETSW=0x5403,TCSETSF=0x5404).

您不应该通过系统调用来实现这一点吗?Linux中的系统调用是中断。投票结束是不清楚的。用什么语言?做什么?C版本:我想使用中断服务。我知道有这样一种服务可以提供dos中断,所以我想linux也有这样一种服务……不,ninjalj已经描述了你需要什么。在Linux(i386体系结构)上,您可以使用int 0x80和eax中的服务号进行系统调用。然而,与DOS不同的是,没有直接调用“检查是否按下键”。有关原因,请参见和。类Unix系统使用终端抽象,除非您想修改Linux本身,否则必须遵循ninjalj的说明。
#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;
}