0

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;
}
falhumai
  • 163
  • 15

3 Answers3

3

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.

Michael Burr
  • 333,147
  • 50
  • 533
  • 760
  • Ok thanks. So, check if parent == itself, then terminate. – falhumai Apr 12 '16 at 05:59
  • One thing though, and this is really confuses me, is the init_thread_info (I don't know if this is the right thing that I should refer to - I mean the last task that points to itself) is the grand GRAND parent (which is swapper/0 in my case - or maybe in all cases), or the task before it (or swapper/0's child)? I.e. is, say, swapper/0 a real task, or it's meant to be an ending flag? – falhumai Apr 14 '16 at 04:29
0

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.

Giuseppe Guerrini
  • 4,274
  • 17
  • 32
  • I am using the current latest stable Linux OS (v4.5) downloaded from the original website (www.kernel.org), and running under Qemu. So you are suggesting something like every time I iterate through the loop, I set my "current" to "current"'s parent? If so, am I still doing the same thing? or you are suggesting I change the end of loop condition? – falhumai Apr 11 '16 at 16:51
  • No, I an suggesting to try "current_process->parent != current_process" as termination test instead of "current_process==NULL". At the moment I can't check the actual implementation of process parent's chain in Linux, but if I did I'd have a look in source file "init/main.c" to see how "init" process is created at startup. "init" is indeed the ultimate parent of all other processes. – Giuseppe Guerrini Apr 11 '16 at 22:38
  • So, I should check if parent == itself, then terminate the loop. – falhumai Apr 12 '16 at 05:59
  • Yes (see also Michael Burr's answer, where you can see that parent field is initalized to tsk structure itself). – Giuseppe Guerrini Apr 12 '16 at 06:50
0

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.

Harry
  • 11,298
  • 1
  • 29
  • 43