内核如何使用task_struct?

问题描述 投票:0回答:3

我是一名正在研究Linux进程的学生,我需要了解更多关于它们的知识才能继续我的实验。在网上阅读几本书和一些东西时,我遇到了

task_struct
,我不确定我是否完全理解,并且希望确认/纠正我现有的想法。

据我所知,

task_struct
是充当进程描述符的C结构,保存内核可能需要了解的有关进程的所有信息。在进程内核堆栈的末尾有另一个结构体
thread_info
,它有一个指向进程的指针
task_struct

另一个问题:如何访问进程的

task_struct
?有没有计算找到它
thread_info
的位置?内核中有宏/函数吗?

c linux process linux-kernel kernel
3个回答
10
投票

是的,

task_struct
结构包含有关进程的所有信息。您可以使用
current
宏获取指向描述当前进程的结构的指针,如下所示:

struct task_struct *p = current;

如果您想获取描述给定

pid
的流程的结构,您可以使用
find_task_by_vpid
函数,如下所示:

read_lock(&tasklist_lock);
p = find_task_by_vpid(pid);
if (p) get_task_struct(p);
read_unlock(&tasklist_lock);
if (p == NULL) {
    // Task not found.
}

// Later, once you're finished with the task, execute:
put_task_struct(p);

最后,如果你想迭代所有进程,你可以使用

for_each_process
,如下所示:

read_lock(&tasklist_lock);
for_each_process(p) {
    // p is a pointer to a task_struct instance.
}
read_unlock(&tasklist_lock);

如果您希望对任务列表进行独占访问,以便能够更改结构中的一个或多个字段,则必须使用

write_lock_irqsave
而不是
read_lock


1
投票

让我尝试回答第二个问题。

在每个进程内核堆栈的顶部都有一个结构体thread_info

要获取thread_info的地址/指针,不同的架构有不同的解决方案,但在x86上它看起来像这样:

要获取指向 thread_info 的指针,只需屏蔽堆栈指针值的 13 位:

movl $0xFFFFE000, %eax
andl %esp, %eax

现在我们有了指针,并且该结构体具有指向 task_struct 结构体的指针。

为了得到它,有一个 current 宏,看起来像这样:

#define current (current_thread_info()->task)

它给你指针(地址)task_struct


0
投票

这是一个内核模块的示例,它使用

task_struct
来确定在模块插入时是否存在某个特定名称的进程:

/*
 * File Name : test.c
 */
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/mm_types.h>
#include <linux/sched/signal.h>

rwlock_t tasklist_lock;

static int __init Init(void){
    struct task_struct *p = current;
    read_lock(&tasklist_lock);
    for_each_process(p){
        if(!strncmp((const char *)p->comm, "Slay999", 16)){
            printk(KERN_INFO "Found target program\n");

            break;
        }
    }   
    read_unlock(&tasklist_lock);
    return 0;
}

static void __exit Exit(void){
    printk(KERN_INFO "Module removed.\n");
}

MODULE_DESCRIPTION("Experements in privlege escalation.");
MODULE_AUTHOR("a name");
MODULE_LICENSE("GPL");
MODULE_VERSION("0.0");

module_init(Init);
module_exit(Exit);

通过获取指向有效

task_struct
地址的指针,我们可以获得有关进程的信息,然后将其用于统计目的和重新配置目的。

例如,您可以使用以下 bash 命令查看

task_struct
的完整定义(可通过
apt-get install pahole
获得):

pahole -C task_struct

一些简短的旁注;

  1. current
    我相信包含活动内核进程的数据。
  2. 结构变量
    task_struct.comm
    ,显示为
    p->comm
    ,包含正在运行的程序的名称。
  3. 存在一个名为
    pid
    的变量,其中包含进程 ID,还存在一个直接使用
    task_struct
    获取指向
    pid_t
    的指针的函数。
  4. 通过
    task_struct
    结构中的变量,您可以获得诸如
    struct mm_struct *active_mm
    之类的东西,据我了解,它可以为您提供正在运行的进程的当前内存地址。

这是该模块附带的 make 文件:

obj-m += test.o
all:
        make -C /lib/modules/$(shell uname -r)/build/ M=$(PWD) modules
clean:
        make -C /lib/modules/$(shell uname -r)/build/ M=$(PWD) clean
© www.soinside.com 2019 - 2024. All rights reserved.