我假设你想在终端模拟器上(而不是在X客户端上),并且你不关心密钥发布.
Linux的方法是使用termios(3)将终端设置为非规范或原始模式,然后使用通常的libc函数读取stdin.
Linux上的系统调用号在/usr/include/asm/unistd.h(或unistd_64.h)上,但是termios函数最终转换为ioctl().因此,如果您因为某些奇怪和不寻常的原因无法调用libc,则必须查找ioctl的系统调用号,以及与termios函数对应的ioctl.
编辑:
显然,你假设Linux使用与DOS相同的模型,其中控制台输入是键盘的抽象(具有类似KEYPRESSED,GETC等的函数),控制台输出是面向字符的抽象显示.
Unix/Linux抽象是关于终端,可以是物理控制台,串口上的终端(或终端仿真器),xterm,......这里重要的一点是,默认情况下,输入行不可用于程序直到终端(或终端仿真器)看到一个行分隔符.
在POSIX上,这些终端由termios(3)功能控制.Linux最终会将这些转换为ioctl()调用,如下所示(请参阅参考资料tty_ioctl(4)):
所以,一个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;
}
Run Code Online (Sandbox Code Playgroud)
现在,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).