thread info - current task 内核栈 关系
图片来自:https://blog.csdn.net/longwang155069/article/details/104346778
threadinfo不在task中-没有配置 CONFIG_THREAD_INFO_IN_TASK
![](https://img-blog.csdnimg.cn/20200216184845777.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2xvbmd3YW5nMTU1MDY5,size_16,color_FFFFFF,t_70)
current 的实现
那如何获取一个进程的task_struct结构呢? 我们获得当前内核栈的sp指针的地址,然后根据THREAD_SIZE对齐就可以获取thread_info结构的基地址,然后从thread_info.task就可以获取当前task_struct结构的地址了。
内核中经常通过current宏来获得当前进程对应的struct task_sturct结构,我们来看下具体的实现。
arch/arm/include/asm/percpu.h
7 8register unsigned long current_stack_pointer asm ("sp"); 9
arch/arm/include/asm/thread_info.h
78/* 79 * how to get the thread information struct from C 80 */ 81static inline struct thread_info *current_thread_info(void) __attribute_const__; 82 83static inline struct thread_info *current_thread_info(void) 84{ 85 return (struct thread_info *) 86 (current_stack_pointer & ~(THREAD_SIZE - 1)); 87}
include/asm-generic/current.h
4 5#include <linux/thread_info.h> 6 7#define get_current() (current_thread_info()->task) 8#define current get_current()
可以看出通过SP的地址通过对齐THREAD_SIZE,然后强转为thread_info结构,然后通过thread_info结构中的task就可以获取task_struct结构的值
ThreadInfo在task_struct结构中
上面的一种方式是thread_info结构和内核栈共用一块存储区域,而另一种方式是thread_info结构存储在task_struct结构中。
-
struct task_struct {
-
-
/*
-
* For reasons of header soup (see current_thread_info()), this
-
* must be the first element of task_struct.
-
*/
-
struct thread_info thread_info;
-
-
/* -1 unrunnable, 0 runnable, >0 stopped: */
-
volatile long state;
-
可以看到必须打开CONFIG_THREAD_INFO_IN_TASK这个配置,这时候thread_info就会在task_struct的第一个成员。而task_struct中依然存在void* stack结构
这时候我们再来看下当thread_info在task_struct结构中时,用一张图描述下。
当thread_info和内核栈是这种关系的时候,内核如何获取当前进程的task_struct结构呢?
current的实现
linux+v5.10/arch/arm64/include/asm/current.h
11/* 12 * We don't use read_sysreg() as we want the compiler to cache the value where 13 * possible. 14 */ 15static __always_inline struct task_struct *get_current(void) 16{ 17 unsigned long sp_el0; 18 19 asm ("mrs %0, sp_el0" : "=r" (sp_el0)); 20 21 return (struct task_struct *)sp_el0; 22} 23 24#define current get_current()
可以看到内核通过读取sp_el0的值,然后将此值强转成task_struct结构就可以获得。那sp_el0是什么东西?