ubuntu 监测键盘输入

背景

        在项目中使用到了一个windows的钩子函数,主要是键盘钩子,感觉很有意思,于是想看看linux下的钩子函数,也实现一个监测键盘输入的功能,这样就可以屏蔽一些按键的输入。

过程

        手上只有一个ubuntu20.04系统的电脑,所以就用这个来研究一下,刚开始就是去找linux的钩子函数,但是在网上查找了一下没有找到,到目前为止我也不确定linux到底有没有类型windows这样的键盘钩子函数,如果有哪位大神知道请指点我一下。

        没有找到linux下的钩子,但是我看到有的文章说可以使用设备文件,参考了这篇文章,感谢感谢。

Ubuntu下的一次捕捉键盘输入的实验_utt@Delimola的博客-CSDN博客之前一直奇怪应用程序是如何得到键盘输入的,首先这肯定与键盘的驱动程序有关,但驱动程序是如何把键盘输入传递给用户进程的?这个问题在用了windows下一个按键精灵后达到了顶峰,该案件精灵使用一个脚本表达模拟发送的键盘按键和鼠标移动,之后可以自动进行操作,这说明上层应用有操作鼠标键盘的能力.查找资料后,发现原来对于linux,鼠标和键盘驱动是这样写的:鼠标\键盘的输入会转为/dev/input下的io事件event*,设备对应的event号可通过cat /proc/bus/input/devices查看.比如https://blog.csdn.net/weixin_44333998/article/details/117772604        这里需要了解几个路径

         (1)  /dev/input/by-id  你可以看到该路径下有一些设备文件,比如event0,但是现在这样无法知道设备文件对应的设备。

 所以你可以在进入到by-id 目录下再看看,你会发现里面都是软连接,这样你可以清楚的了解设备对应的设备文件。

还有一个by-path目录和这个作用一样。

 

         (2)  /proc/bus/input   --->  有一个devices的文件,里面是设备对应的设备文件,比如你要获取别的设备时可以看看这个文件。比如说摄像头什么的。

        最后,我就是读取设备文件,因此程序也主要是读取设备文件。

代码

#include <stdio.h>
#include <linux/input.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <iostream>
#include <stdlib.h>
#include <string.h>
#include <string>
#include <errno.h>
#include <fstream>

using namespace std;

/*  
 *作用: 找到键盘设备对应的事件文件  例如 event7
 *     linux 插入键盘设备,每一个设备会有一个事件编号,但是目前这个ls -l排序是按照设备名称排,所以
 *     最上面的键盘设备并不会是最新的设备,因此 此函数在键盘设备多的时候 会获取一个不确定的键盘事件文件
        usb-026d_0002-event-if01 -> ../event12
        usb-026d_0002-event-kbd -> ../event6
        usb-413c_Dell_KB216_Wired_Keyboard-event-if01 -> ../event14
        usb-413c_Dell_KB216_Wired_Keyboard-event-kbd -> ../event13     这是最新的键盘设备,但是没有排到最上面
        usb-Logitech_USB_Receiver-if01-event-mouse -> ../event2
        usb-Logitech_USB_Receiver-if01-mouse -> ../mouse0
        usb-SONiX_USB_Keyboard-event-if01 -> ../event4
        usb-SONiX_USB_Keyboard-event-kbd -> ../event3

 */

string FindKdbEvet()
{
    FILE *stream;
    FILE *wstream;
    char buf[20];
    memset( buf, '\0', sizeof(buf) );//初始化buf,以免后面写如乱码到文件中
    //将命令的输出 通过管道读取(“r”参数)到FILE* stream
    stream = popen("cd /dev/input/by-id ; ls -l | grep \"kbd\" | head -1 | cut -d \"/\" -f 2", "r"); 
    fread( buf, sizeof(char), sizeof(buf), stream); //将刚刚FILE* stream的数据流读取到buf中
    pclose(stream);
    string str = buf;
    return str;
}
  
/*  
 *作用: 打开事件文件  
 *输入:  _infile 对应的文件流变量
 *返回值: int 返回0 为打开成功  返回-1 为打开失败
 */
int OpenEventFile(ifstream & _infile)
{
    string kdbevet = FindKdbEvet();   //获取键盘事件例如 event7 
    int isize = kdbevet.size();
    if(isize > 0 && kdbevet[isize-1]) //这里需要去除结尾的换行符号 ascii码是10
    {
        kdbevet = kdbevet.substr(0,kdbevet.size()-1); 
    }
    string shCommand = "/dev/input/" + kdbevet;

    _infile.open(shCommand.c_str(),ios_base::in);
    if(!_infile.is_open())
    {
        cout <<"open Keyboard device error, error code = <<" << errno << "!" <<endl;
        return -1;
    }
    return 0;
}



int main ()  
{  
  struct input_event t;  
  ifstream infile;

  if(OpenEventFile(infile) == -1)
  {
      return 0;
  }

  bool blPressIsCtrl = false;
  bool blPressIsC    = false;

  while (1)  
  {
       if(infile.read((char *)&t,sizeof(t)))
       {//读取文件成功
           if(t.type == EV_KEY)
           {
               if((t.code == KEY_LEFTCTRL || t.code == KEY_RIGHTCTRL) && t.value == 1)
               {
                   blPressIsCtrl = true;
               }

               if ((t.code == KEY_LEFTCTRL || t.code == KEY_RIGHTCTRL) && t.value == 0)
               {
                   blPressIsCtrl = false;
               }

               if(t.code == KEY_C && t.value == 1 && blPressIsCtrl == true)
               {
                   cout<<"press ctrl + c"<<endl;
               }
               
               cout << "you use key value is "<<t.code<<endl;
           }
       }
       else
       {//读取文件失败 需要再次进行一次读取
           cout <<"read file error"<<endl;
           infile.close();  
           if(OpenEventFile(infile) == -1)
           {
              return 0;
           }
       }
  }  
  infile.close();  
  return 0;  
}  

后记

        目前这个小代码,可以实现监测linux系统下键盘设备(USB接口)的按键输入,监测到输入Ctrl+C 就会输出日志。同一个键盘设备插拔程序依旧可以监测。

        不足的地方是不能同时监测多个键盘设备的输入,因为现在就是读取一个设备文件(windows钩子函数就可以)。而且结束程序,插入多个键盘设备,再次执行程序,不一定会继续监测上次监测的键盘设备,这是因为by-id 目录中软链接的排序不是稳定的,shell语句是查询是第一个对应的设备文件。这点还需要完善。

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值