Search code examples
clinux-kerneltaskdepth-first-search

Kernel module that iterates over the tree of children of a task using depth first search


So I know how to create a kernel and to iterate over the processes linearly by simply including linux/sched.h and using the following code:

struct task_struct *task;

for_each_process(task)
{
   printk("Name: %s PID: [%d]\n", task->comm, task->pid);
}

How can I print these tasks using a depth first search? I want my output to be similar to the one of ps -eLf.

The following patch of code has been given for reference:

struct task_struct *task;
struct list_head *list;
list_for_each(list, &init_task->children) {
    task = list_entry(list, struct task_struct, sibling);
    /* task points to the next child in the list */
}

and I know that task->comm returns the name and task->pid returns the PID for that task.

What fields are used to for the state and parent PID?


Solution

  • This is a bit old, but I came across it as it seems to be one of the programming projects found in chapter 3 of Operating System Concepts 9th Edition, so others may yet come looking.

    The code you started with is straight from the book, but it is a good starting point. You just need to implement the DFS. Here is the code that will accomplish it, it should be pretty self explanatory:

    #include <linux/module.h>
    #include <linux/kernel.h>
    #include <linux/sched.h>
    #include <linux/init.h>
    
    /**
     * Performs a DFS on a given task's children.
     *
     * @void
     */
    void DFS(struct task_struct *task)
    {   
        struct task_struct *child;
        struct list_head *list;
    
        printk("name: %s, pid: [%d], state: %li\n", task->comm, task->pid, task->state);
        list_for_each(list, &task->children) {
            child = list_entry(list, struct task_struct, sibling);
            DFS(child);
        }
    }
    
    /**
     * This function is called when the module is loaded. 
     *
     * @return 0  upon success
     */ 
    int task_lister_init(void)
    {
        printk(KERN_INFO "Loading Task Lister Module...\n");
        DFS(&init_task);
    
        return 0;
    }
    
    /**
     * This function is called when the module is removed.
     *
     * @void
     */
    void task_lister_exit(void)
    {
        printk(KERN_INFO "Removing Task Lister Module...\n");
    }
    
    // Macros for registering module entry and exit points.
    module_init(task_lister_init);
    module_exit(task_lister_exit);