task_struct 线程节点
task_struct node for threads
很抱歉,如果我重复了别人多次问过的同一个问题,但我找不到满意的答案。因此,再次发布这个简单的查询。
问题:据我了解,Linux中的每个线程在内核任务link列表中都有一个'task_struct'节点。
Linux Version :
#lsb_release -a
Distributor ID: Ubuntu
Description: Ubuntu 20.04.3 LTS
Release: 20.04
Codename: focal
我写了一个 linux 内核模块来遍历 'task_struct' 的完整列表,并找出哪些 'task_struct' 节点属于我的简单程序(它有一个主线程和使用 pthread_create() 函数创建了 4 个线程,总共 5 个线程)。
下面是我的模块的核心逻辑,用于找出列表中属于特定 'tgid'(线程组 ID)的所有 'task_struct' 成员。
mymodule.c
#include <linux/module.h>
#include <linux/init.h>
#include <linux/sched/signal.h>
MODULE_LICENSE("GPL");
MODULE_AUTHOR("MY_NAME");
MODULE_DESCRIPTION("Print a task details");
char * get_task_state(long state)
{
switch (state) {
case TASK_RUNNING:
return "TASK_RUNNING";
case TASK_INTERRUPTIBLE:
return "TASK_INTERRUPTIBLE";
case TASK_UNINTERRUPTIBLE:
return "TASK_UNINTERRUPTIBLE";
case __TASK_STOPPED:
return "__TASK_STOPPED";
case __TASK_TRACED:
return "__TASK_TRACED";
default:
return "UNKNOWN TYPE";
}
}
static void print_task_info(unsigned int tgid)
{
struct task_struct *task_list;
for_each_process(task_list) {
if (task_list->tgid == tgid) {
pr_info("task_struct node : %p\t Name: %s\t PID:[%d]\t TGID:[%d]\t State:%s\n",
task_list, task_list->comm, task_list->pid, task_list->tgid,
get_task_state(task_list->state));
}
}
return;
}
unsigned int arg;
static int notify_param(const char *val, const struct kernel_param *kp)
{
int res = param_set_int(val, kp);
pr_info("notify_param() called.\n");
if (!res) {
print_task_info(arg);
return 0;
}
return -1;
}
const struct kernel_param_ops my_module_param_ops =
{
.set = notify_param,
.get = param_get_int,
};
module_param_cb(arg, &my_module_param_ops, &arg, S_IRUSR|S_IWUSR);
static int __init my_module_init(void)
{
printk("Hello, Linux Kernel");
return 0;
}
static void __exit my_module_exit(void)
{
printk("Bye, Linux Kernel");
return;
}
module_init(my_module_init);
module_exit(my_module_exit);
下面是 Makefile:
obj-m += mymodule.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
编译并加载它:
#make
#insmode mymodule.ko
在内核中插入这个模块后,我为 tgid 传递了一个参数,如下所示。
echo 7196 > /sys/module/mymodule/parameters/arg
'7196' 是一个用户程序的 pid,它总共有 5 个线程(如前所述)。
在这里,我希望我应该得到'task_struct'的5个条目,但实际上它只显示一个,如下所示:
#dmesg | tail
[ 4432.971557] task_struct node : 000000007bede576 Name: a.out PID:[7196] TGID:[7196] State:TASK_RUNNING
请帮助我理解这种行为,就线程在 Linux 中的表示方式而言,我的理解可能是错误的。
我的理解是,Linux所有的执行程序都以线程的形式存在,有些线程共享内存区域(也有相同的'tgid'(线程组id,称为相同的线程过程)).
进程和线程都使用struct task_struct
,但是你需要两个嵌套循环来遍历所有线程。外循环遍历进程,内循环遍历该进程的线程。
例如:
static void print_task_info(unsigned int tgid)
{
struct task_struct *the_process;
struct task_struct *the_thread;
char comm[TASK_COMM_LEN];
rcu_read_lock();
for_each_process(the_process) {
if (task_tgid_nr(the_process) == tgid) {
for_each_thread(the_process, the_thread) {
pr_info("thread node: %p\t Name: %s\t PID:[%d]\t TGID:[%d]\n",
the_thread, get_task_comm(comm, the_thread),
task_pid_nr(the_thread), task_tgid_nr(the_thread));
}
break;
}
}
rcu_read_unlock();
}
很抱歉,如果我重复了别人多次问过的同一个问题,但我找不到满意的答案。因此,再次发布这个简单的查询。
问题:据我了解,Linux中的每个线程在内核任务link列表中都有一个'task_struct'节点。
Linux Version :
#lsb_release -a
Distributor ID: Ubuntu
Description: Ubuntu 20.04.3 LTS
Release: 20.04
Codename: focal
我写了一个 linux 内核模块来遍历 'task_struct' 的完整列表,并找出哪些 'task_struct' 节点属于我的简单程序(它有一个主线程和使用 pthread_create() 函数创建了 4 个线程,总共 5 个线程)。
下面是我的模块的核心逻辑,用于找出列表中属于特定 'tgid'(线程组 ID)的所有 'task_struct' 成员。 mymodule.c
#include <linux/module.h>
#include <linux/init.h>
#include <linux/sched/signal.h>
MODULE_LICENSE("GPL");
MODULE_AUTHOR("MY_NAME");
MODULE_DESCRIPTION("Print a task details");
char * get_task_state(long state)
{
switch (state) {
case TASK_RUNNING:
return "TASK_RUNNING";
case TASK_INTERRUPTIBLE:
return "TASK_INTERRUPTIBLE";
case TASK_UNINTERRUPTIBLE:
return "TASK_UNINTERRUPTIBLE";
case __TASK_STOPPED:
return "__TASK_STOPPED";
case __TASK_TRACED:
return "__TASK_TRACED";
default:
return "UNKNOWN TYPE";
}
}
static void print_task_info(unsigned int tgid)
{
struct task_struct *task_list;
for_each_process(task_list) {
if (task_list->tgid == tgid) {
pr_info("task_struct node : %p\t Name: %s\t PID:[%d]\t TGID:[%d]\t State:%s\n",
task_list, task_list->comm, task_list->pid, task_list->tgid,
get_task_state(task_list->state));
}
}
return;
}
unsigned int arg;
static int notify_param(const char *val, const struct kernel_param *kp)
{
int res = param_set_int(val, kp);
pr_info("notify_param() called.\n");
if (!res) {
print_task_info(arg);
return 0;
}
return -1;
}
const struct kernel_param_ops my_module_param_ops =
{
.set = notify_param,
.get = param_get_int,
};
module_param_cb(arg, &my_module_param_ops, &arg, S_IRUSR|S_IWUSR);
static int __init my_module_init(void)
{
printk("Hello, Linux Kernel");
return 0;
}
static void __exit my_module_exit(void)
{
printk("Bye, Linux Kernel");
return;
}
module_init(my_module_init);
module_exit(my_module_exit);
下面是 Makefile:
obj-m += mymodule.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
编译并加载它:
#make
#insmode mymodule.ko
在内核中插入这个模块后,我为 tgid 传递了一个参数,如下所示。
echo 7196 > /sys/module/mymodule/parameters/arg
'7196' 是一个用户程序的 pid,它总共有 5 个线程(如前所述)。 在这里,我希望我应该得到'task_struct'的5个条目,但实际上它只显示一个,如下所示:
#dmesg | tail
[ 4432.971557] task_struct node : 000000007bede576 Name: a.out PID:[7196] TGID:[7196] State:TASK_RUNNING
请帮助我理解这种行为,就线程在 Linux 中的表示方式而言,我的理解可能是错误的。
我的理解是,Linux所有的执行程序都以线程的形式存在,有些线程共享内存区域(也有相同的'tgid'(线程组id,称为相同的线程过程)).
进程和线程都使用struct task_struct
,但是你需要两个嵌套循环来遍历所有线程。外循环遍历进程,内循环遍历该进程的线程。
例如:
static void print_task_info(unsigned int tgid)
{
struct task_struct *the_process;
struct task_struct *the_thread;
char comm[TASK_COMM_LEN];
rcu_read_lock();
for_each_process(the_process) {
if (task_tgid_nr(the_process) == tgid) {
for_each_thread(the_process, the_thread) {
pr_info("thread node: %p\t Name: %s\t PID:[%d]\t TGID:[%d]\n",
the_thread, get_task_comm(comm, the_thread),
task_pid_nr(the_thread), task_tgid_nr(the_thread));
}
break;
}
}
rcu_read_unlock();
}