内核模块开发疑问:顶层指针是否应声明为static?
Hey, let's walk through structuring your i8042 keyboard filter kernel module based on what you've outlined so far—this aligns with kernel best practices and the i8042 module's filter integration mechanism:
First, define your single key info data type at the module's top level (outside all functions) so it's visible to all module code. Then declare a pointer to this type to hold data for 128 keys:
// Define the data structure for a single key's metadata typedef struct { bool is_blocked; // Flag to mark if the key should be filtered unsigned int press_count; // Optional: Track how many times the key was pressed // Add other fields as needed (e.g., last press timestamp) } key_info_t; // Top-level pointer to store data for 128 keys // Memory will be allocated dynamically during module init key_info_t *key_database = NULL;
Important note: We only declare the pointer here, not allocate the actual memory. Kernel static memory is limited, so dynamic allocation (done later in init) is the safer approach.
In your module's init function, use kernel memory allocation functions (not user-space malloc) to reserve space for 128 keys, then register your filter with the i8042 module:
static int __init keyboard_filter_init(void) { // Allocate zero-initialized memory for 128 key entries // GFP_KERNEL is the standard flag for kernel-space memory allocation key_database = kzalloc(128 * sizeof(key_info_t), GFP_KERNEL); if (!key_database) { pr_err("Keyboard filter: Failed to allocate memory for key database\n"); return -ENOMEM; } // Set default filter rules (e.g., allow all keys by default) for (int i = 0; i < 128; i++) { key_database[i].is_blocked = false; } // Register your filter with the i8042 module // Replace with the actual i8042 filter registration call for your kernel version // Example: i8042_register_filter(&my_filter_operations); pr_info("Keyboard filter module loaded successfully\n"); return 0; } module_init(keyboard_filter_init);
This is the function that i8042 will call to process keyboard events. It checks if the key should be blocked using your key_database, then returns true to allow the event or false to filter it:
static bool keyboard_event_filter(struct i8042_dev *dev, unsigned char scancode) { // Extract the base key index (ignore the "key released" bit) int key_idx = scancode & 0x7F; bool is_press = !(scancode & 0x80); // Validate the key index is within our 128-key range if (key_idx >= 0 && key_idx < 128) { // Block the key if marked as blocked if (key_database[key_idx].is_blocked) { pr_debug("Keyboard filter: Blocked key with scancode 0x%x\n", scancode); return false; } // Update press count if this is a key-down event if (is_press) { key_database[key_idx].press_count++; pr_debug("Keyboard filter: Key 0x%x pressed %u times\n", scancode, key_database[key_idx].press_count); } } // Allow all unmarked keys or out-of-range events return true; }
Make sure the function signature matches what the i8042 module expects for filters—check your kernel's i8042 header files for the exact prototype.
Always clean up resources when the module is unloaded to avoid memory leaks:
static void __exit keyboard_filter_exit(void) { // Unregister your filter from the i8042 module // Example: i8042_unregister_filter(&my_filter_operations); // Free the dynamically allocated key database if (key_database) { kfree(key_database); key_database = NULL; } pr_info("Keyboard filter module unloaded\n"); } module_exit(keyboard_filter_exit);
内容的提问来源于stack exchange,提问作者ivan

