Chr*_*ppy 3 c linux linux-kernel
我正在破解 Linux 内核并与struct task_struct current.
当输出pid兄弟的命令名时,似乎存在一个带有pid=的畸形进程0,并且命令名是乱码。
同样的事情也发生在进程的父母身上。
\n为什么pid=0兄弟姐妹之间出现有一个过程?该过程不是为 保留的吗swapper?
// Loop over process and parents using something like:\n\n/*\nprintk("--syscall ## Begin process results ##"); \n\nprintk("--syscall // View children //");\nmy_list_head = &(current->children);\n\nprintk("--syscall // View siblings //");\nmy_list_head = &(current->sibling)\n\nprintk("--syscall results: ...");\n*/\n\n\nif (my_list_head == NULL) {\n return 0;\n}\n\nlist_for_each(tempNode, my_list_head) {\n\xc2\xa0 tempTask = list_entry(tempNode, struct task_struct,\n\xc2\xa0 \xc2\xa0 \xc2\xa0 \xc2\xa0 \xc2\xa0 sibling);\n\xc2\xa0 printk("--syscall The %ld-th process's pid is %d and command %s",\n\xc2\xa0 \xc2\xa0 \xc2\xa0 \xc2\xa0 \xc2\xa0count, tempTask->pid, tempTask->comm);\n\xc2\xa0}\n\nRun Code Online (Sandbox Code Playgroud)\n带空格格式化
\n[ 2938.994084] --syscall ## Begin process results ##\n[ 2938.994089] --syscall // View children //\n[ 2938.994105] --syscall // View siblings //\n[ 2938.994116] --syscall The 1-th process's pid is 0 and command \\x80\xdd\xb6E\\x96\\xff\\xff\n[ 2938.994133] --syscall results: pid=1400 name=process_ancesto state=0 uid=1000 nvcsw=1 nivcsw=0 num_children=0 num_siblings=1\n\n[ 2938.994139] --syscall ## Begin process results ##\n[ 2938.994144] --syscall // View children //\n[ 2938.994149] --syscall The 1-th process's pid is 1400 and command process_ancesto\n[ 2938.994158] --syscall // View siblings //\n[ 2938.994163] --syscall The 1-th process's pid is 0 and command\n[ 2938.994176] --syscall results: pid=1282 name=bash state=1 uid=1000 nvcsw=88 nivcsw=18 num_children=1 num_siblings=1\n\n[ 2938.994180] --syscall ## Begin process results ##\n[ 2938.994185] --syscall // View children //\n[ 2938.994190] --syscall The 1-th process's pid is 1282 and command bash\n[ 2938.994198] --syscall // View siblings //\n[ 2938.994203] --syscall The 1-th process's pid is 1275 and command systemd\n[ 2938.994210] --syscall The 2-th process's pid is 0 and command\n[ 2938.994216] --syscall The 3-th process's pid is 117 and command systemd-journal\n[ 2938.994222] --syscall The 4-th process's pid is 145 and command systemd-udevd\n[ 2938.994227] --syscall The 5-th process's pid is 148 and command systemd-network\n[ 2938.994233] --syscall The 6-th process's pid is 369 and command systemd-resolve\n[ 2938.994239] --syscall The 7-th process's pid is 370 and command systemd-timesyn\n[ 2938.994245] --syscall The 8-th process's pid is 412 and command accounts-daemon\n[ 2938.994321] --syscall The 9-th process's pid is 413 and command dbus-daemon\n[ 2938.994336] --syscall The 10-th process's pid is 417 and command irqbalance\n[ 2938.994346] --syscall The 11-th process's pid is 418 and command rsyslogd\n[ 2938.994352] --syscall The 12-th process's pid is 419 and command snapd\n[ 2938.994359] --syscall The 13-th process's pid is 420 and command systemd-logind\n[ 2938.994365] --syscall The 14-th process's pid is 439 and command cron\n[ 2938.994372] --syscall The 15-th process's pid is 451 and command atd\n[ 2938.994378] --syscall The 16-th process's pid is 456 and command agetty\n[ 2938.994385] --syscall The 17-th process's pid is 461 and command sshd\n[ 2938.994390] --syscall The 18-th process's pid is 491 and command unattended-upgr\n[ 2938.994397] --syscall The 19-th process's pid is 501 and command polkitd\n[ 2938.994413] --syscall results: pid=1200 name=login state=1 uid=0 nvcsw=31 nivcsw=33 num_children=1 num_siblings=19\nRun Code Online (Sandbox Code Playgroud)\n
下面是两个同级子进程如何链接到其父进程的子进程列表的说明:
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.
Run Code Online (Sandbox Code Playgroud)
尽管children和sibling都是类型struct list_head,children但 is 被用作实际的列表头(链接到其子进程列表),而siblingis 被用作列表条目。
父级的children.next链接指向子级 1 的sibling成员,子级 1 的sibling.next链接指向子级 2 的sibling成员,子级 2 的sibling.next链接指向父级的children成员(列表头)。同样,父级的children.prev链接指向子级 2 的sibling成员,子级 2 的sibling.prev链接指向子级 1 的sibling成员,子级 1 的sibling.prev链接指向回父级的children成员。
该list_for_each(pos, head)宏访问pos列表中的每个节点,从head->next, while开始pos != head。
通常,head的参数list_for_each(pos, head)应该是实际的链表头,但该宏无法区分链表头和链表项之间的区别。它们都是同一类型,并且所有节点都循环连接在一起。(整个列表由一个列表头组成,其中零个或多个列表条目以圆圈形式链接。对于空列表,列表头仅链接回其自身。)宏list_for_each将仅围绕双向链表进行迭代,直到返回到从哪里开始。
如果list_for_each(pos, head)通过指向head父级的children成员来调用,则将在第一次迭代中pos指向子级 1 的sibling成员,并在第二次迭代中指向子级 2 的成员,并通过指向回父级的成员sibling来终止循环。在循环内,将正确指向子进程的开头。poschildrenlist_entry(pos, struct task_struct, sibling)struct task_struct
假设子进程 1 是current进程。OP 的代码使用list_for_each(pos, head)withhead指向子 1 的sibling成员。因此,pos将在第一次迭代中指向子级 2 的sibling成员,并在第二次迭代中指向父级的成员,并通过指向回子级 1 的成员children来终止循环。在循环内部,在第一次迭代中将正确指向子级 2 的开头,但在第二次迭代中将指向父级 2 的开头之前的某个位置。这就是OP代码的问题所在。possiblinglist_entry(pos, struct task_struct, sibling)struct task_structposstruct task_struct