2015-05-05 28 views
1

我有一个关于task_struct列表的问题。内核task_struct和同级指针

/* 
* pointers to (original) parent process, youngest child, younger sibling, 
* older sibling, respectively. (p->father can be replaced with 
* p->p_pptr->pid) 
*/ 
task_t *p_opptr, *p_pptr, *p_cptr, *p_ysptr, *p_osptr; 

我正在使用这些指针来运行进程的子进程。 我不明白(并且很难从内核代码中理解),如果最小的子列表结尾为null或是循环的?

我可以穿过所有p_cptr,直到我达到NULL,或者我应该再次回到头部吗?

谢谢。

+0

内核链接列表是[圆形双向链表](http://en.wikipedia.org/wiki/Doubly_linked_list#Circular_doubly-linked_lists)。所以最后一个元素(尾部)指向第一个元素(头部)。看看[for_each_process()](http://lxr.free-electrons.com/source/include/linux/sched.h#L2529)宏。 –

+0

无论你使用的是什么列表。所有列表在内核中都是循环的。它是通过列表函数实现来实现的:他们都在试图在每次操作后使列表循环。你需要为你的任务使用的是'list_for_each()'和'list_entry()'函数。详情请参阅[这个问题](http://stackoverflow.com/questions/8207160/kernel-how-to-iterate-the-children-of-the-current-process)。 –

+0

我不是通过'list_head'指针迭代列表,而是直接通过'task_t'指针进行迭代。 没有'prev','next'我正在经历,所以它不是完全一样的情况。 我正在访问每个进程的'p_cptr'和'p_osptr',我只是不明白对没有孩子/老兄弟的进程期望什么。 –

回答

1

尝试下面的代码。我没有在内核2.4(仅在4.0)上测试过它,但我认为它应该适用于2.4,而且几乎没有修改。例如,我使用kthreadd过程作为父项,因为它有很多子项。

#include <linux/module.h> 
#include <linux/sched.h> 
#include <linux/list.h> 

#define KTHREADD_PID 2 

static int __init ktdf_init(void) 
{ 
    struct task_struct *kthreadd_task; 
    struct list_head *list; 

    /* Find kthreadd task by PID */ 
    kthreadd_task = pid_task(find_vpid(KTHREADD_PID), PIDTYPE_PID); 
    pr_debug("Process name: %s\n", kthreadd_task->comm); 

    /* Iterate over all children of kthreadd_task */ 
    list_for_each(list, &kthreadd_task->children) { 
     struct task_struct *task; 

     /* Get next child */ 
     task = list_entry(list, struct task_struct, sibling); 
     pr_debug(" Child name: %s\n", task->comm); 
    } 

    return 0; 
} 

static void __exit ktdf_exit(void) 
{ 
} 

module_init(ktdf_init); 
module_exit(ktdf_exit); 

MODULE_AUTHOR("Sam Protsenko"); 
MODULE_DESCRIPTION("kthreadd children finder module"); 
MODULE_LICENSE("GPL"); 

因此,大家可以看到,.sibling名单circular doubly-linked list,这意味着这个列表(尾)指向第一个元素(头)的最后一个元素。您可以从list_for_each()宏实现中看到它。

dmesg输出(模块由insmod加载后):

Process name: kthreadd 
    Child name: ksoftirqd/0 
    Child name: ksoftirqd/1 
    Child name: ksoftirqd/2 
    Child name: ksoftirqd/3 
    Child name: kworker/0:0 
    Child name: kworker/0:0H 
    Child name: kworker/0:1 
    Child name: kworker/0:1H 
    Child name: kworker/0:2 
    ... 

您可以通过ps命令来检查:

$ ps auxf 

这给了我同样的进程树:

[kthreadd] 
\_ [ksoftirqd/0] 
\_ [ksoftirqd/1] 
\_ [ksoftirqd/2] 
\_ [ksoftirqd/3] 
\_ [kworker/0:0] 
\_ [kworker/0:0H] 
\_ [kworker/0:1] 
\_ [kworker/0:1H] 
\_ [kworker/0:2] 
... 
+0

这个解决方案正在工作,但不是2.4,因为我没有像更新的内核那样的'children'列表。 我只有在问题中提到的指针。 –

+0

我终于知道你在说什么了:[link](http:// lxr。free-electrons.com/source/include/linux/sched.h?v=2.4.37#L346)。不幸的是,我的机器上没有内核2.4,所以即使我想出了一些代码 - 我也无法测试它。 –

+0

我鼓励你对你的内核进行'grep',并寻找你提到的那些指针的实际用法(也可能是“兄弟”字)。您可能也想为此使用LXR。 –