background
In the project, I used a hook function of windows, mainly the keyboard hook, which is very interesting. So I want to see the hook function under linux and realize a function of monitoring keyboard input, so that I can shield the input of some keys.
process
I only have a computer with Ubuntu 20.04 system, so I use this to study. At the beginning, I went to find the hook function of linux, but I found it on the Internet. So far, I'm not sure whether linux has a keyboard hook function such as windows. If any God knows, please give me some advice.
I didn't find the hook under linux, but I saw some articles saying that device files can be used. I refer to this article. Thank you.
(1) / dev/input/by-id You can see that there are some device files under this path, such as event0, but now you can't know the device corresponding to the device file.
So you can go to the by ID directory and look again. You will find that there are soft connections in it, so you can clearly understand the device files corresponding to the device.
There is also a by path directory that works the same way.
(2) / proc/bus/input ---> There is a device file, which is the device file corresponding to the device. For example, you can look at this file when you want to obtain other devices. Like a camera or something.
Finally, I just read the device file, so the program mainly reads the device file.
code
#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; /* *Function: find the event file corresponding to the keyboard device, such as event7 * linux Insert keyboard devices, and each device will have an event number, but at present, the ls -l sorting is arranged according to the device name, so * The top keyboard device will not be the latest device, so this function will get an uncertain keyboard event file when there are many keyboard devices 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 This is the latest keyboard device, but it's not at the top 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) );//Initialize buf to prevent it from being written into the file //Read the output of the command through the pipe (the "r" parameter) to 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); //Read the data stream of FILE* stream into buf pclose(stream); string str = buf; return str; } /* *Function: open event file *Input:_ File rheology corresponding to infile *Return value: int returns 0 as opening success and - 1 as opening failure */ int OpenEventFile(ifstream & _infile) { string kdbevet = FindKdbEvet(); //Get keyboard events, such as event7 int isize = kdbevet.size(); if(isize > 0 && kdbevet[isize-1]) //Here, we need to remove the line feed symbol at the end. The ascii code is 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))) {//Read file successfully 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 {//Failed to read the file. You need to read it again cout <<"read file error"<<endl; infile.close(); if(OpenEventFile(infile) == -1) { return 0; } } } infile.close(); return 0; }
Postscript
At present, this small code can monitor the key input of keyboard equipment (USB interface) under linux system. If you monitor the input of Ctrl+C, you will output the log. The plug-in program of the same keyboard device can still be monitored.
The disadvantage is that you can't monitor the input of multiple keyboard devices at the same time, because now you just read a device file (windows Hook function). Moreover, if you end the program, insert multiple keyboard devices, and execute the program again, you may not continue to monitor the last monitored keyboard device. This is because the sorting of soft links in the by ID directory is not stable, and the shell statement is to query the first corresponding device file. This needs to be improved.