我有一个程序来检测键盘。
首先,我使用read()
从键盘设备读取struct input_event
,它工作得很好。
然后我尝试用fread()
替换read()
。数据错误。
demo在下面。要复制这个bug,您需要将/dev/input/event0
与您的键盘开发人员交换,并使用sudo
运行它。
#include <unistd.h>
#include <stdio.h>
#include <sys/fcntl.h>
#include <linux/input.h>
#include <stdlib.h>
#define USE_FREAD
static void check_keyboard (int fd)
{
static struct input_event event;
#ifdef USE_READ
{
//use read(). it works well.
if (read (fd, &event, sizeof (event)) == -1)
perror ("read()"), exit (EXIT_FAILURE);
}
#else
#ifdef USE_FREAD
{
//use fread(). it gets wrong data
int cloned = dup (fd);
if (cloned == -1)
perror ("dup()"), exit (EXIT_FAILURE);
FILE *file = fdopen (cloned, "r");
if (file == NULL)
perror ("fdopen()"), exit (EXIT_FAILURE);
if (fread (&event, sizeof (event), 1, file) != 1) {
if (feof (file))
fprintf (stderr, "fread() got EOF"), exit (EXIT_FAILURE);
else if (ferror (file))
fprintf (stderr, "fread() failed\n"), exit (EXIT_FAILURE);
}
if (fclose (file) != 0)
perror ("fclose()"), exit (EXIT_FAILURE);
puts ("fread() over");
}
#endif
#endif
if (event.type != EV_KEY)
return;
switch (event.value) {
case 0:
puts ("key released");
break;
case 1:
printf ("key pressed, code:%d\n", event.code);
break;
case 2:
puts ("repeat automatically");
break;
}
}
int main()
{
int fd = open ("/dev/input/event0", O_RDONLY);
if (fd == -1)
perror ("open()"), exit (EXIT_FAILURE);
for (; ;) {
check_keyboard (fd);
}
if (close (fd) != 0)
perror ("close()"), exit (EXIT_FAILURE);
}
如果定义了USE_READ
,则可以检测键盘事件。并且它只在定义了USE_FREAD
的情况下打印“fread()over”。
我尝试使用gdb来查看event
的值。但还有许多其他事件混淆了数据。
我的环境:debian 12,gcc 12.2.0,kernel 6.1.0-7-amd64 .
1条答案
按热度按时间vuktfyat1#
我已经根据评论中的建议解决了。
只需要使用
setvbuf()
禁用缓冲区:顺便说一下,请检查返回值。