I am trying to traverse all the ancestors of a process to store their info in a static array passed by the user, and I am using the NULL pointer end flag to end traversing. However, this does not seem to work, and will continue looping until the size number (the capacity of the array) passed by the user space matches num_filed number (the number of elements in the array) in all cases, even if I have very little number of processes running. So, what seem to be the ending flag for traversing ancestors? Here is my traversing loop code:
current_process = current;
int i = 0;
while (current_process != NULL && current_num_filled < size) {
temp_info_array[i] = get_process_info(current_process);
++current_num_filled;
++i;
current_process = current_process->parent;
}
You can see the INIT_TASK()
macro used to initialize the struct task_struct
for the init process in /include/linux/init_task.h
. In particular:
#define INIT_TASK(tsk) \
{ \
.state = 0, \
.stack = &init_thread_info, \
\
/* ... */ \
\
.real_parent = &tsk, \
.parent = &tsk, \
\
/* ... */ \
}
So as you can see - the parent
member of init's struct task_struct
is set point to itself, not the null pointer.
It depends on the way your OS encodes the concept of "root process". "NULL" is not the only way to do it. Another common solution in similar cases is to set "parent" field to "current_process" itself. I guess your OS behaves this way. This explains why your loop doesn't end until the buffer space is exhausted.
You can walk the list as follows...
struct task_struct *task = current;
do {
task = task->parent;
printk(KERN_INFO "process=%s, pid=%d", task->comm, task->pid);
} while (task->pid != 0);
Don't do this in interrupt context.