Posts 리눅스에서 키보드 이벤트 처리하기
Post
Cancel

리눅스에서 키보드 이벤트 처리하기

리눅스에서 키보드 이벤트는 하드웨어 인터럽트를 사용한다. 윈래는 입력만 처리하는 스레드를 만들어서 spin lock으로 키보드 입력을 인식하려 했다. 근데 입력 스레드에서 키보드 입력을 blocking 하게 대기하는 방법을 찾다보니, 결국 입력 이벤트를 대기하는 것과 같은 이야기였다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#include <stdio.h>
#include <linux/input.h>
#include <termios.h>
#include <fcntl.h>
#include <sys/signal.h>
#include <error.h>

int fd;
struct termios termAttr;
struct input_event evt;
const char* type[] = {
    "Released",
    "Pressed",
    "Repeated"
};
struct sigaction saio;
int n;

void signal_handler(int status){
    n = read(fd, &evt, sizeof(input_event));
    printf(" %s 0x%02X %d %d\n", type[evt.type], evt.code, evt.value);
}

int main(int argc, char* argv[]){
    fd = open("/dev/input/by-id/...", O_RDONLY | O_NOCTTY | O_NDELAY);
    if(fd == -1){
        perror("No device");
    }

    saio.sa_handler = signal_handler;
    saio.sa_flags = 0;
    saio.sa_restorer = NULL;
    sigaction(SIGIO, &saio, NULL);

    fcntl(fd, F_SETFL, FNDELAY);
    fcntl(fd, F_SETOWN, getpid());
    fcntl(fd, F_SETFL, O_ASYNC);

    while(1){

    }

    close(&fd);

    return 0;
}

open 함수의 첫 번째 인자는 키보드의 장치 id다. 아래의 명령어로 확인할 수 있다.(ubuntu16.04 기준)

1
$ ls /dev/input/by-id/

프로세스가 작동중일 때 키보드 입력 시 signal SIGIO 이 발생한다. 이 놈을 핸들러에 등록하고 fd에서 데이터를 읽어보면 evt에 관한 정보가 있다.

근데…

실행해보면 evt.type에 이상한 놈이 뜬다. 버튼을 누를때 Pressed, 땔 때 Released 가 떠야하나 중간중간에 (null) 이 뜬다. 디버깅 해보니

1
printf(" 0x%02X %d %d\n", evt.type, evt.code, evt.value);

evt.type에 0x04가 나온다. input-event-codes.h에서 0x04는 EV_MSC.

documents에서 말하기를

EV_MSC: Used to describe miscellaneous input data that do not fit into other types.

타입이 맞지 않은 기타 데이터를 설명하는데 사용이란다.

https://stackoverflow.com/questions/16695432/input-event-structure-description-from-linux-input-h

나랑 똑같은 현상이 stackoverflow에 올라와 있다.왜 키보드 버튼을 눌렀을 뿐인데 저런 문제가 생기는지 설명하고 있지는 않다.

해결하면 업데이트할 예정 아시는 분 댓글 부탁합니다.

This post is licensed under CC BY 4.0 by the author.