Zxa*_*aos 76 c linux asynchronous input nonblocking
我正在尝试用C语言编写一个程序(在Linux上)循环,直到用户按下一个键,但不应该要求按键继续每个循环.
有一个简单的方法吗?我想我可以做到这一点,select()但这似乎很多工作.
或者,有没有办法在程序关闭之前捕获ctrl- ckeypress进行清理而不是非阻塞io?
Aln*_*tak 61
如前所述,您可以使用sigaction陷阱ctrl-c或select陷阱任何标准输入.
但请注意,对于后一种方法,您还需要设置TTY,使其一次一个字符而不是一次一行模式.后者是默认值 - 如果您键入一行文本,则在按Enter键之前不会将其发送到正在运行的程序的stdin.
您需要使用该tcsetattr()功能关闭ICANON模式,也可能还禁用ECHO.从内存中,您还必须在程序退出时将终端设置回ICANON模式!
为了完整性,这里有一些代码我刚刚敲了(nb:没有错误检查!),它设置了一个Unix TTY并模拟了DOS <conio.h>函数,kbhit()并且getch():
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/select.h>
#include <termios.h>
struct termios orig_termios;
void reset_terminal_mode()
{
tcsetattr(0, TCSANOW, &orig_termios);
}
void set_conio_terminal_mode()
{
struct termios new_termios;
/* take two copies - one for now, one for later */
tcgetattr(0, &orig_termios);
memcpy(&new_termios, &orig_termios, sizeof(new_termios));
/* register cleanup handler, and set the new terminal mode */
atexit(reset_terminal_mode);
cfmakeraw(&new_termios);
tcsetattr(0, TCSANOW, &new_termios);
}
int kbhit()
{
struct timeval tv = { 0L, 0L };
fd_set fds;
FD_ZERO(&fds);
FD_SET(0, &fds);
return select(1, &fds, NULL, NULL, &tv);
}
int getch()
{
int r;
unsigned char c;
if ((r = read(0, &c, sizeof(c))) < 0) {
return r;
} else {
return c;
}
}
int main(int argc, char *argv[])
{
set_conio_terminal_mode();
while (!kbhit()) {
/* do some work */
}
(void)getch(); /* consume the character */
}
Run Code Online (Sandbox Code Playgroud)
Nor*_*sey 15
select()为方便起见有点太低级了.我建议您使用该ncurses库将终端设置为cbreak模式和延迟模式,然后调用getch(),ERR如果没有字符准备就会返回:
WINDOW *w = initscr();
cbreak();
nodelay(w, TRUE);
Run Code Online (Sandbox Code Playgroud)
那时你可以getch不受阻塞地打电话.
Meh*_*ari 11
在UNIX系统上,您可以使用sigactioncall为SIGINT信号注册信号处理程序,该信号处理程序代表Control + C键序列.信号处理程序可以设置一个标志,该标志将在循环中检查,使其适当地中断.
你可能想要 kbhit();
//Example will loop until a key is pressed
#include <conio.h>
#include <iostream>
using namespace std;
int main()
{
while(1)
{
if(kbhit())
{
break;
}
}
}
Run Code Online (Sandbox Code Playgroud)
这可能不适用于所有环境.一种可移植的方法是创建一个监视线程并设置一些标志getch();
另一种获得非阻塞键盘输入的方法是打开设备文件并读取它!
你必须知道你正在寻找的设备文件,/dev/input/event* 之一。你可以运行 cat /proc/bus/input/devices 来找到你想要的设备。
此代码适用于我(以管理员身份运行)。
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <linux/input.h>
int main(int argc, char** argv)
{
int fd, bytes;
struct input_event data;
const char *pDevice = "/dev/input/event2";
// Open Keyboard
fd = open(pDevice, O_RDONLY | O_NONBLOCK);
if(fd == -1)
{
printf("ERROR Opening %s\n", pDevice);
return -1;
}
while(1)
{
// Read Keyboard Data
bytes = read(fd, &data, sizeof(data));
if(bytes > 0)
{
printf("Keypress value=%x, type=%x, code=%x\n", data.value, data.type, data.code);
}
else
{
// Nothing read
sleep(1);
}
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
100969 次 |
| 最近记录: |