struct task_struct current的同级始终包含pid = 0的进程 [英] Siblings of `struct task_struct current` always include a process with `pid = 0`
问题描述
我正在破解 linux 内核并与 struct task_struct current
的兄弟姐妹和孩子一起玩.
I'm hacking the linux kernel and playing with siblings and children of the struct task_struct current
.
输出同胞的 pid
和命令名称时,似乎存在格式错误的进程,其中 pid
= 0
,命令名称为乱七八糟的.
When outputting the pid
and command name of siblings, there appears to be a malformed process with pid
= 0
and the command name is gibberish.
进程的父进程也会发生同样的事情.
The same thing occurs with the process' parents.
为什么在同级兄弟中出现 pid = 0
的进程?
Why is there a process with pid=0
showing up among the siblings? Isn't that process reserved for swapper
?
// Loop over process and parents using something like:
/*
printk("--syscall ## Begin process results ##");
printk("--syscall // View children //");
my_list_head = &(current->children);
printk("--syscall // View siblings //");
my_list_head = &(current->sibling)
printk("--syscall results: ...");
*/
if (my_list_head == NULL) {
return 0;
}
list_for_each(tempNode, my_list_head) {
tempTask = list_entry(tempNode, struct task_struct,
sibling);
printk("--syscall The %ld-th process's pid is %d and command %s",
count, tempTask->pid, tempTask->comm);
}
输出
带空格的格式
[ 2938.994084] --syscall ## Begin process results ##
[ 2938.994089] --syscall // View children //
[ 2938.994105] --syscall // View siblings //
[ 2938.994116] --syscall The 1-th process's pid is 0 and command \x80ݶE\x96\xff\xff
[ 2938.994133] --syscall results: pid=1400 name=process_ancesto state=0 uid=1000 nvcsw=1 nivcsw=0 num_children=0 num_siblings=1
[ 2938.994139] --syscall ## Begin process results ##
[ 2938.994144] --syscall // View children //
[ 2938.994149] --syscall The 1-th process's pid is 1400 and command process_ancesto
[ 2938.994158] --syscall // View siblings //
[ 2938.994163] --syscall The 1-th process's pid is 0 and command
[ 2938.994176] --syscall results: pid=1282 name=bash state=1 uid=1000 nvcsw=88 nivcsw=18 num_children=1 num_siblings=1
[ 2938.994180] --syscall ## Begin process results ##
[ 2938.994185] --syscall // View children //
[ 2938.994190] --syscall The 1-th process's pid is 1282 and command bash
[ 2938.994198] --syscall // View siblings //
[ 2938.994203] --syscall The 1-th process's pid is 1275 and command systemd
[ 2938.994210] --syscall The 2-th process's pid is 0 and command
[ 2938.994216] --syscall The 3-th process's pid is 117 and command systemd-journal
[ 2938.994222] --syscall The 4-th process's pid is 145 and command systemd-udevd
[ 2938.994227] --syscall The 5-th process's pid is 148 and command systemd-network
[ 2938.994233] --syscall The 6-th process's pid is 369 and command systemd-resolve
[ 2938.994239] --syscall The 7-th process's pid is 370 and command systemd-timesyn
[ 2938.994245] --syscall The 8-th process's pid is 412 and command accounts-daemon
[ 2938.994321] --syscall The 9-th process's pid is 413 and command dbus-daemon
[ 2938.994336] --syscall The 10-th process's pid is 417 and command irqbalance
[ 2938.994346] --syscall The 11-th process's pid is 418 and command rsyslogd
[ 2938.994352] --syscall The 12-th process's pid is 419 and command snapd
[ 2938.994359] --syscall The 13-th process's pid is 420 and command systemd-logind
[ 2938.994365] --syscall The 14-th process's pid is 439 and command cron
[ 2938.994372] --syscall The 15-th process's pid is 451 and command atd
[ 2938.994378] --syscall The 16-th process's pid is 456 and command agetty
[ 2938.994385] --syscall The 17-th process's pid is 461 and command sshd
[ 2938.994390] --syscall The 18-th process's pid is 491 and command unattended-upgr
[ 2938.994397] --syscall The 19-th process's pid is 501 and command polkitd
[ 2938.994413] --syscall results: pid=1200 name=login state=1 uid=0 nvcsw=31 nivcsw=33 num_children=1 num_siblings=19
推荐答案
以下是两个兄弟级子进程如何链接到其父级进程的子级列表中的说明:
Here is an illustration of how two sibling child processes are linked into their parent process's list of children:
PARENT CHILD 1 CHILD 2
====== ======= =======
task_struct task_struct
+-------------+ +-------------+
| | | |
task_struct ~ ~ ~ ~
+-------------+ | | | |
| | |-------------| |-------------|
~ ~ | children | | children |
| | | | | |
. . |-------------| . . |-------------| . . |-------------| . .
| children | | sibling | | sibling |
X==>| prev | next |<===>| prev | next |<===>| prev | next |<==X
. . |-------------| . . |-------------| . . |-------------| . .
| sibling | | | | |
| | ~ ~ ~ ~
|-------------| | | | |
| | +-------------+ +-------------+
~ ~
| | 'X's are joined together, making
+-------------+ a doubly linked, circular list.
尽管 children
和兄弟姐妹
均为 struct list_head
类型,但 children
被用作实际列表头(链接到其子进程列表),而 sibling
被用作列表项.
Although children
and sibling
are both of type struct list_head
, children
is being used as an actual list head (linking to its list of child processes), whereas sibling
is being used as a list entry.
父级的 children.next
链接指向子级1的 sibling
成员,子级1的 sibling.next
链接指向子级2的同级
成员,子级2的 sibling.next
链接指向父级的 children
成员(列表头).同样,父级的 children.prev
链接指向子级2的 sibling
成员,子级2的 sibling.prev
链接指向子级1的 sibling
成员,并且子级1的 sibling.prev
链接指向父级的 children
成员.
The parent's children.next
link points to child 1's sibling
member, child 1's sibling.next
link points to child 2's sibling
member, and child 2's sibling.next
link points back to the parent's children
member (the list head). Similarly, the parent's children.prev
link points to child 2's sibling
member, child 2's sibling.prev
link points to child 1's sibling
member, and child 1's sibling.prev
link points back to the parent's children
member.
list_for_each(pos,head)
宏从 head-> next
开始访问列表中的每个节点 pos
,而 pos!= head
.
The list_for_each(pos, head)
macro visits each node pos
in the list, starting at head->next
, while pos != head
.
通常, list_for_each(pos,head)
的 head
参数应该是实际的列表头,但是宏无法区分列表头和列表之间的区别入口.它们都是相同的类型,并且所有节点都循环链接在一起.(整个列表由一个带有零个或多个列表项的列表头组成,这些列表项链接成一个圆圈.对于一个空列表,列表头仅链接回其自身.) list_for_each
宏将仅在双向链表,直到它回到起点为止.
Normally, the head
parameter of list_for_each(pos, head)
should be an actual list head, but the macro cannot tell the difference between a list head and a list entry. They are both the same type and all the nodes are linked together circularly. (The whole list consists of a list head with zero or more list entries linked in a circle. For an empty list, the list head just links back to itself.) The list_for_each
macro will just iterate around the doubly linked list until it get back to where it started.
如果调用 list_for_each(pos,head)
并用 head
指向父母的 children
成员,则 pos
将在第一次迭代中指向子1的 sibling
成员,并在第二次迭代中指向子2的 sibling
成员,并使用 pos终止循环
指向父母的 children
成员.在循环内部, list_entry(pos,struct task_struct,sibling)
会正确指向子进程的 struct task_struct
的开头.
If list_for_each(pos, head)
was called with head
pointing to the parent's children
member, then pos
would point to child 1's sibling
member in the first iteration, and would point to child 2's sibling
member in the second iteration, and would terminate the loop with pos
pointing back to the parent's children
member. Inside the loop, list_entry(pos, struct task_struct, sibling)
would correctly point to the beginning of the struct task_struct
for the child process.
让我们说孩子1是 current
进程.OP的代码使用 list_for_each(pos,head)
,其中 head
指向子级1的 sibling
成员.因此, pos
将在第一次迭代中指向子代2的 sibling
成员,并在第二次迭代中指向父代的 children
成员,并且将以 pos
指向子1的 sibling
成员终止循环.在循环内, list_entry(pos,struct task_struct,sibling)
将在第一次迭代中正确指向子代2的 struct task_struct
的开头,但是 pos 在第二次迭代中,code>会指向父对象的
struct task_struct
开头之前的某个位置.那就是问题出在OP的代码中.
Let us say that child 1 is the current
process. OP's code is using list_for_each(pos, head)
with head
pointing to child 1's sibling
member. Therefore, pos
would point to child 2's sibling
member in the first iteration, and would point to the parent's children
member in the second iteration, and would terminate the loop with pos
pointing back to child 1's sibling
member. Inside the loop, list_entry(pos, struct task_struct, sibling)
would correctly point to the beginning of child 2's struct task_struct
in the first iteration, but pos
would point to somewhere before the beginning of the parent's struct task_struct
in the second iteration. That is the where the problem lies in OP's code.
这篇关于struct task_struct current的同级始终包含pid = 0的进程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!