Ubuntu下的一次捕捉键盘输入的实验

之前一直奇怪应用程序是如何得到键盘输入的,首先这肯定与键盘的驱动程序有关,但驱动程序是如何把键盘输入传递给用户进程的?这个问题在用了windows下一个按键精灵后达到了顶峰,该案件精灵使用一个脚本表达模拟发送的键盘按键和鼠标移动,之后可以自动进行操作,这说明上层应用有操作鼠标键盘的能力.查找资料后,发现原来对于linux,鼠标和键盘驱动是这样写的:
鼠标\键盘的输入会转为/dev/input下的io事件event*,设备对应的event号可通过cat /proc/bus/input/devices查看.比如我查看该文件的内容:

I: Bus=0019 Vendor=0000 Product=0003 Version=0000
N: Name="Sleep Button"
P: Phys=PNP0C0E/button/input0
S: Sysfs=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0C0E:00/input/input0
U: Uniq=
H: Handlers=kbd event0 
B: PROP=0
B: EV=3
B: KEY=4000 0 0

I: Bus=0019 Vendor=0000 Product=0001 Version=0000
N: Name="Power Button"
P: Phys=PNP0C0C/button/input0
S: Sysfs=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0C0C:00/input/input1
U: Uniq=
H: Handlers=kbd event1 
B: PROP=0
B: EV=3
B: KEY=10000000000000 0

I: Bus=0019 Vendor=0000 Product=0001 Version=0000
N: Name="Power Button"
P: Phys=LNXPWRBN/button/input0
S: Sysfs=/devices/LNXSYSTM:00/LNXPWRBN:00/input/input2
U: Uniq=
H: Handlers=kbd event2 
B: PROP=0
B: EV=3
B: KEY=10000000000000 0

I: Bus=0019 Vendor=0000 Product=0006 Version=0000
N: Name="Video Bus"
P: Phys=LNXVIDEO/video/input0
S: Sysfs=/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/LNXVIDEO:00/input/input3
U: Uniq=
H: Handlers=kbd event3 
B: PROP=0
B: EV=3
B: KEY=3e000b00000000 0 0 0

I: Bus=0003 Vendor=413c Product=2113 Version=0111
N: Name="Dell KB216 Wired Keyboard"
P: Phys=usb-0000:00:14.0-1/input0
S: Sysfs=/devices/pci0000:00/0000:00:14.0/usb1/1-1/1-1:1.0/0003:413C:2113.0001/input/input4
U: Uniq=
H: Handlers=sysrq kbd event4 leds 
B: PROP=0
B: EV=120013
B: KEY=1000000000007 ff9f207ac14057ff febeffdfffefffff fffffffffffffffe
B: MSC=10
B: LED=1f

I: Bus=0003 Vendor=413c Product=2113 Version=0111
N: Name="Dell KB216 Wired Keyboard"
P: Phys=usb-0000:00:14.0-1/input1
S: Sysfs=/devices/pci0000:00/0000:00:14.0/usb1/1-1/1-1:1.1/0003:413C:2113.0002/input/input5
U: Uniq=
H: Handlers=kbd event5 
B: PROP=0
B: EV=1f
B: KEY=300ff 0 0 483ffff17aff32d bf54444600000000 1 130c730b17c000 267bfad941dfed 9e168000004400 10000002
B: REL=40
B: ABS=100000000
B: MSC=10

I: Bus=0003 Vendor=03f0 Product=134a Version=0111
N: Name="PixArt HP USB Optical Mouse"
P: Phys=usb-0000:00:14.0-2/input0
S: Sysfs=/devices/pci0000:00/0000:00:14.0/usb1/1-2/1-2:1.0/0003:03F0:134A.0003/input/input6
U: Uniq=
H: Handlers=mouse0 event6 
B: PROP=0
B: EV=17
B: KEY=ff0000 0 0 0 0
B: REL=103
B: MSC=10

I: Bus=0000 Vendor=0000 Product=0000 Version=0000
N: Name="HDA Intel PCH Front Mic"
P: Phys=ALSA
S: Sysfs=/devices/pci0000:00/0000:00:1f.3/sound/card0/input7
U: Uniq=
H: Handlers=event7 
B: PROP=0
B: EV=21
B: SW=10

I: Bus=0000 Vendor=0000 Product=0000 Version=0000
N: Name="HDA Intel PCH Rear Mic"
P: Phys=ALSA
S: Sysfs=/devices/pci0000:00/0000:00:1f.3/sound/card0/input8
U: Uniq=
H: Handlers=event8 
B: PROP=0
B: EV=21
B: SW=10

I: Bus=0000 Vendor=0000 Product=0000 Version=0000
N: Name="HDA Intel PCH Line"
P: Phys=ALSA
S: Sysfs=/devices/pci0000:00/0000:00:1f.3/sound/card0/input9
U: Uniq=
H: Handlers=event9 
B: PROP=0
B: EV=21
B: SW=2000

I: Bus=0000 Vendor=0000 Product=0000 Version=0000
N: Name="HDA Intel PCH Line Out Front"
P: Phys=ALSA
S: Sysfs=/devices/pci0000:00/0000:00:1f.3/sound/card0/input10
U: Uniq=
H: Handlers=event10 
B: PROP=0
B: EV=21
B: SW=40

I: Bus=0000 Vendor=0000 Product=0000 Version=0000
N: Name="HDA Intel PCH Line Out Surround"
P: Phys=ALSA
S: Sysfs=/devices/pci0000:00/0000:00:1f.3/sound/card0/input11
U: Uniq=
H: Handlers=event11 
B: PROP=0
B: EV=21
B: SW=40

I: Bus=0000 Vendor=0000 Product=0000 Version=0000
N: Name="HDA Intel PCH Line Out CLFE"
P: Phys=ALSA
S: Sysfs=/devices/pci0000:00/0000:00:1f.3/sound/card0/input12
U: Uniq=
H: Handlers=event12 
B: PROP=0
B: EV=21
B: SW=40

I: Bus=0000 Vendor=0000 Product=0000 Version=0000
N: Name="HDA Intel PCH Front Headphone"
P: Phys=ALSA
S: Sysfs=/devices/pci0000:00/0000:00:1f.3/sound/card0/input13
U: Uniq=
H: Handlers=event13 
B: PROP=0
B: EV=21
B: SW=4

I: Bus=0000 Vendor=0000 Product=0000 Version=0000
N: Name="HDA Intel PCH HDMI/DP,pcm=3"
P: Phys=ALSA
S: Sysfs=/devices/pci0000:00/0000:00:1f.3/sound/card0/input14
U: Uniq=
H: Handlers=event14 
B: PROP=0
B: EV=21
B: SW=140

I: Bus=0000 Vendor=0000 Product=0000 Version=0000
N: Name="HDA Intel PCH HDMI/DP,pcm=7"
P: Phys=ALSA
S: Sysfs=/devices/pci0000:00/0000:00:1f.3/sound/card0/input15
U: Uniq=
H: Handlers=event15 
B: PROP=0
B: EV=21
B: SW=140

I: Bus=0000 Vendor=0000 Product=0000 Version=0000
N: Name="HDA Intel PCH HDMI/DP,pcm=8"
P: Phys=ALSA
S: Sysfs=/devices/pci0000:00/0000:00:1f.3/sound/card0/input16
U: Uniq=
H: Handlers=event16 
B: PROP=0
B: EV=21
B: SW=140

I: Bus=0000 Vendor=0000 Product=0000 Version=0000
N: Name="HDA Intel PCH HDMI/DP,pcm=9"
P: Phys=ALSA
S: Sysfs=/devices/pci0000:00/0000:00:1f.3/sound/card0/input17
U: Uniq=
H: Handlers=event17 
B: PROP=0
B: EV=21
B: SW=140

I: Bus=0000 Vendor=0000 Product=0000 Version=0000
N: Name="HDA Intel PCH HDMI/DP,pcm=10"
P: Phys=ALSA
S: Sysfs=/devices/pci0000:00/0000:00:1f.3/sound/card0/input18
U: Uniq=
H: Handlers=event18 
B: PROP=0
B: EV=21
B: SW=140

I: Bus=0019 Vendor=0000 Product=0000 Version=0000
N: Name="Eee PC WMI hotkeys"
P: Phys=eeepc-wmi/input0
S: Sysfs=/devices/platform/eeepc-wmi/input/input19
U: Uniq=
H: Handlers=rfkill kbd event19 
B: PROP=0
B: EV=100013
B: KEY=7e40000 0 800000000000 0 0 1400b00100000 300180001100800 e000000000000 2
B: MSC=10

I: Bus=0000 Vendor=0000 Product=0000 Version=0000
N: Name="HDA NVidia HDMI/DP,pcm=3"
P: Phys=ALSA
S: Sysfs=/devices/pci0000:00/0000:00:01.0/0000:01:00.1/sound/card1/input20
U: Uniq=
H: Handlers=event20 
B: PROP=0
B: EV=21
B: SW=140

I: Bus=0000 Vendor=0000 Product=0000 Version=0000
N: Name="HDA NVidia HDMI/DP,pcm=7"
P: Phys=ALSA
S: Sysfs=/devices/pci0000:00/0000:00:01.0/0000:01:00.1/sound/card1/input21
U: Uniq=
H: Handlers=event21 
B: PROP=0
B: EV=21
B: SW=140

I: Bus=0000 Vendor=0000 Product=0000 Version=0000
N: Name="HDA NVidia HDMI/DP,pcm=8"
P: Phys=ALSA
S: Sysfs=/devices/pci0000:00/0000:00:01.0/0000:01:00.1/sound/card1/input22
U: Uniq=
H: Handlers=event22 
B: PROP=0
B: EV=21
B: SW=140

I: Bus=0000 Vendor=0000 Product=0000 Version=0000
N: Name="HDA NVidia HDMI/DP,pcm=9"
P: Phys=ALSA
S: Sysfs=/devices/pci0000:00/0000:00:01.0/0000:01:00.1/sound/card1/input23
U: Uniq=
H: Handlers=event23 
B: PROP=0
B: EV=21
B: SW=140

鼠标对应event6比较明显,键盘可能是event4或event5,应用程序试了两次发现event5无效,event4有效,至于为什么有2个event对应键盘就不知道了.
应用程序如下:

//读取键盘输入
#include <stdio.h>
#include <linux/input.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

int main()
{
    int fd_kb;

    struct input_event event_kb;

    fd_kb = open("/dev/input/event4", O_RDONLY); //键盘输入
    if (fd_kb <= 0)
    {
        printf("open device error\n");
        return 0;
    }

    while (1)
    {
        if (read(fd_kb, &event_kb, sizeof(event_kb)) == sizeof(event_kb))
        {
            if (event_kb.type == EV_KEY)
            {
                //if (event_kb.value == 0 || event_kb.value == 1)//1表示按下,0表示释放,会检测到两次
                if (event_kb.value == 1) //键按下
                {
                    //printf("key %d %s\n", event_kb.code, (event_kb.value) ? "Pressed" : "Released");
                    if (event_kb.code == KEY_ESC)
                        break;
                    if (event_kb.code == KEY_Q)
                        printf("q\n");
                    if (event_kb.code == KEY_W)
                        printf("w\n");
                    if (event_kb.code == KEY_E)
                        printf("e\n");
                    if (event_kb.code == KEY_R)
                        printf("r\n");
                }
            }
        }
    }
    close(fd_kb);
    return 0;
}

以上程序不管是不是在前台输入,程序都能捕捉到Q\W\E\R按键,并且多个进程居然可以同时捕捉到事件;推测只让前台进程获取到事件是内核的职责,前台进程是与终端绑定的概念,内核的终端调度程序(不是调度器!)负责把信号传给前台进程,并清掉信号,这就和我们平时看到的现象一致了.按键精灵是通过模拟键盘\鼠标事件实现的,demo程序如下:

#include <string.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <linux/input.h>
#include <linux/uinput.h>
#include <stdio.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>

void simulate_key(int fd, int kval)
{
    struct input_event event;
    event.type = EV_KEY;
    event.value = 1;
    event.code = kval;

    gettimeofday(&event.time, 0);
    write(fd, &event, sizeof(event));

    event.type = EV_SYN;
    event.code = SYN_REPORT;
    event.value = 0;
    write(fd, &event, sizeof(event));

    memset(&event, 0, sizeof(event));
    gettimeofday(&event.time, NULL);
    event.type = EV_KEY;
    event.code = kval;
    event.value = 0;
    write(fd, &event, sizeof(event));
    event.type = EV_SYN;
    event.code = SYN_REPORT;
    event.value = 0;
    write(fd, &event, sizeof(event));
}
void simulate_mouse(int fd)
{
    struct input_event event;
    memset(&event, 0, sizeof(event));
    gettimeofday(&event.time, NULL);
    event.type = EV_REL;
    event.code = REL_X;
    event.value = 10;
    write(fd, &event, sizeof(event));

    event.type = EV_REL;
    event.code = REL_Y;
    event.value = 10;
    write(fd, &event, sizeof(event));

    event.type = EV_SYN;
    event.code = SYN_REPORT;
    event.value = 0;
    write(fd, &event, sizeof(event));
}
int main()
{
    int fd_kbd;
    int fd_mouse;
    fd_kbd = open("/dev/input/event4", O_RDWR);
    if (fd_kbd <= 0)
    {
        printf("error open keyboard:\n");
        return -1;
    }
    fd_mouse = open("/dev/input/event6", O_RDWR);
    if (fd_mouse <= 0)
    {
        printf("error open mouse\n");
        return -2;
    }
    int i = 0;
    for (i = 0; i < 10; i++)
    {
        simulate_key(fd_kbd, KEY_A + i);
        simulate_mouse(fd_mouse);
        sleep(1);
    }
    close(fd_kbd);
}

以上程序居然可以让键盘\鼠标自己输出,自己移动,可以明显看到现象!

参考了:

linux 处理键盘 鼠标事件
Linux如何查看与/dev/input目录下的event对应的设备
linux c语言 模拟键盘输入

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
Ubuntu系统中,你可能会遇到键盘输入延迟的问题。有几个可能的原因可以解释这个问题。 首先,引用提到了你使用的键盘型号和输入法系统。Logitech K580作为无线蓝牙键盘,可能会在连接或传输数据时出现延迟。这是因为无线蓝牙设备在传输数据时可能会受到干扰或信号弱导致延迟。如果你的键盘信号不稳定,可能会出现输入延迟的情况。 另外,引用指出,切换到英文键盘时延迟问题消失了。这可能表明输入法系统的设置存在问题。iBus是一种输入法系统,它可能在处理中文输入时导致延迟。尝试在输入时切换到英文键盘,可能可以解决延迟的问题。 此外,引用中描述了键盘输入延迟的问题。这可能是由于系统资源不足或其他后台进程导致的。如果你的系统负荷过重,或者有其他应用程序在后台运行,可能会导致键盘输入延迟。你可以尝试关闭一些不必要的应用程序,释放系统资源,以减轻延迟问题。 综上所述,解决Ubuntu键盘输入延迟的方法可以包括: 1. 确保无线蓝牙键盘的信号稳定,尽量减少干扰或信号弱的情况。 2. 尝试切换到英文键盘,看是否可以解决延迟问题。 3. 关闭一些不必要的应用程序,以释放系统资源,减轻延迟问题。 希望这些方法能够帮助你解决键盘输入延迟的问题。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [「Ubuntuubuntu18.04键盘输入卡顿、延迟输入](https://blog.csdn.net/Liiipseoroinis/article/details/125811379)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值