Linux应用程序-按键响应
Linux中的按键检测通过循环读取设备文件/dev/input/eventx设备文件获取按键事件,一般由主线程循环获取按键事件,然后通过消息队列通知其他子线程,从而做出响应。
在Linux内核中,按键事件用input_event结构体描述,该结构体在头文件中定义,同时该文件还定义了有关按键事件的API函数接口、标准按键编码等。
input_event结构体定义如下:
struct input_event {
struct timeval time;
__u16 type;
__u16 code;
__s32 value;
};
还定义了常用标准按键编码:
#define KEY_RESERVED 0
#define KEY_ESC 1
#define KEY_1 2
#define KEY_2 3
#define KEY_3 4
#define KEY_4 5
#define KEY_5 6
#define KEY_6 7
在用户态,我们只需要循环读取设备文件/dev/input/eventx,就可以得到相应的键盘事件,代码如下:
#include <linux/input.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdint.h>
#define KEY_EVENT_DEV1_NAME "/dev/input/event1"
int sysKeyScan(void)
{
int l_ret = -1;
int i = 0;
int key_fd = 0;
struct input_event key_event = {0};
key_fd = open(KEY_EVENT_DEV1_NAME, O_RDONLY);
if(key_fd <= 0)
{
printf("---open /dev/input/event1 device error!---\n");
return l_ret;
}
while(1)
{
l_ret = lseek(key_fd, 0, SEEK_SET);
l_ret = read(key_fd, &key_event, sizeof(key_event));
if(l_ret)
{
if(key_event.type == EV_KEY
&& (key_event.value == 0 || key_event.value == 1))
{
printf("key %d %s\n", key_event.code, (key_event.value) ? "pressed" : "released");
if(key_event.code == KEY_ESC)
{
break;
}
}
}
}
close(key_fd);
return l_ret;
}
int main(int arg, char *arc[])
{
printf("---This is a key event test!---\n");
sysKeyScan();
return 0;
}
有时候,我们的的Linux内核也可以把不同的按键封装到不同的event中,例如数字键键盘事件通过event1通知用户态,而功能键通过event0通知用户态。此时我们可以使用poll函数来同时监测多个等待事件,若事件未发生,进程睡眠,放弃CPU控制权,直到有键盘事件发生,poll将唤醒睡眠的进程,并执行相应的操作。代码如下:
#include <linux/input.h>
#include <fcntl.h>
#include <poll.h>
#include <stdio.h>
#include <stdint.h>
#define KEY_EVENT_DEV0_NAME "/dev/input/event0"
#define KEY_EVENT_DEV1_NAME "/dev/input/event1"
int sysKeyScan(void)
{
int l_ret = -1;
int i = 0;
int key_fd[2] = {0};
struct pollfd key_fds[2] = {0};
struct input_event key_event = {0};
key_fd[0] = open(KEY_EVENT_DEV0_NAME, O_RDONLY);
if(key_fd[0] <= 0)
{
printf("---open /dev/input/event0 device error!---\n");
return l_ret;
}
key_fd[1] = open(KEY_EVENT_DEV1_NAME, O_RDONLY);
if(key_fd[1] <= 0)
{
printf("---open /dev/input/event1 device error!---\n");
return l_ret;
}
for(i = 0; i < 2; i++)
{
key_fds[i].fd = key_fd[i];
key_fds[i].events = POLLIN;
}
while(1)
{
l_ret = poll(key_fds, 2, -1);
for(i = 0; i < 2; i++)
{
l_ret = lseek(key_fd[i], 0, SEEK_SET);
l_ret = read(key_fd[i], &key_event, sizeof(key_event));
if(l_ret)
{
if(key_event.type == EV_KEY
&& (key_event.value == 0 || key_event.value == 1))
{
printf("key value(%d) %s", key_event.code, key_event.value ? "press" : "release");
}
}
}
}
close(key_fd[0]);
close(key_fd[1]);
return l_ret;
}
int main(int argc, char *argv[])
{
printf("---This is a key event test!---\n");
sysKeyScan();
return 0;
}