Linux list_for_each_entry()宏参数及模块插入报错咨询
Hey there! Let's break down your issues step by step—first with the list_for_each_entry() parameter confusion, then why you're seeing that "Killed" error when inserting the module.
1. Fixing list_for_each_entry() Parameters
First, let's clarify what each parameter in list_for_each_entry() is supposed to do. The macro's signature is:
list_for_each_entry(pos, head, member)
Where:
pos: A pointer to the struct you're iterating over (e.g.,struct task_struct *task)head: The head of the linked list you want to traverse (e.g.,&init_task.tasksfor the global process list, or&some_task->childrenfor a parent's child processes)member: The name of thestruct list_headmember inside your target struct (e.g.,tasksorchildreninstruct task_struct)
Your Initial Code's Parameter Mistake
In your first code snippet, you wrote:
list_for_each_entry(type, struct task_struct, children)
The second parameter is wrong here—you passed the struct type (struct task_struct) instead of a valid list head pointer. This would cause compilation or runtime errors because the macro expects a pointer to a struct list_head.
Your Modified Code's Parameter Mistake
In the revised code, you used:
list_for_each_entry(type, listHead, sibling)
Here, listHead is an uninitialized global pointer—you never set it to point to a valid list head (like &init_task.children). When the macro tries to dereference this null/garbage pointer, it triggers an illegal memory access in the kernel.
2. Why You're Seeing "Killed"
When your kernel module accesses invalid memory (like an uninitialized pointer), the kernel detects this as a critical error. To protect the system from crashing, it terminates the user-space process that triggered the issue—in this case, insmod, hence the "Killed" message. This is a safety mechanism to prevent kernel panics caused by buggy modules.
3. Correct Implementation
The easiest way to traverse all active processes is to use the for_each_process() macro (a wrapper around list_for_each_entry() that handles the global process list for you). Here's a fixed version of your module:
#include <linux/module.h> #include <linux/kernel.h> #include <linux/sched.h> #include <linux/init_task.h> static int __init process_traverse_init(void) { int processCount = 0; struct task_struct *task; printk(KERN_INFO "Jared Rathbun\n"); // Traverse every active process using the helper macro for_each_process(task) { printk(KERN_INFO "Name: %-20s| PID: %-5d| State: %-4ld| Priority: %-5d| Policy: %-5d| Parent Name: %-20s| PPID: %-5d\n", task->comm, task->pid, task->state, task->prio, task->policy, task->parent->comm, task->parent->pid); processCount++; } printk(KERN_INFO "TOTAL PROCESS COUNT: %d\n", processCount); return 0; } static void __exit process_traverse_exit(void) { printk(KERN_INFO "Module unloaded successfully\n"); } // Use modern module init/exit macros instead of init_module/cleanup_module module_init(process_traverse_init); module_exit(process_traverse_exit); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Kernel Module that traverses the list of running processes on the OS"); MODULE_AUTHOR("Jared Rathbun");
If you want to use list_for_each_entry() directly (e.g., to only traverse init's children), you'd do something like this:
// Traverse only init's child processes list_for_each_entry(task, &init_task.children, sibling) { printk(KERN_INFO "Child of init: %s (PID: %d)\n", task->comm, task->pid); processCount++; }
Key Notes
- Avoid uninitialized global pointers—always assign them to valid kernel memory before use.
- Use
for_each_process()for full process list traversal; it's cleaner and less error-prone. - Check kernel logs with
dmesgorjournalctlafter module operations to see detailed error messages (they'll help debug issues like invalid memory accesses).
内容的提问来源于stack exchange,提问作者JaredRathbun




