概念
kernel version: 5.13
每个进程在创建时分配了两个栈,一个是用户栈,一个是内核栈。当进程通过系统调用、中断、异常等方式陷入内核时,就不能在使用用户栈,而是使用内核栈。
Linux kernel定义了一个共用体:
union thread_union {
#ifndef CONFIG_ARCH_TASK_STRUCT_ON_STACK
struct task_struct task;
#endif
#ifndef CONFIG_THREAD_INFO_IN_TASK
struct thread_info thread_info;
#endif
unsigned long stack[THREAD_SIZE/sizeof(long)];
};
THREAD_SIZE大致可以分为:32位 8K,64位16K
thread_info的作用
众所周知,进程信息保存在task_struct中,那为什么还需要thread_info呢?
因为不同的体系结构,进程要保存的信息不尽相同,如x86和ARM。task_struct保存通用的信息,而将与体系结构相关的信息保存在thread_info中。
struct task_struct {
#ifdef CONFIG_THREAD_INFO_IN_TASK
/*
* For reasons of header soup (see current_thread_info()), this
* must be the first element of task_struct.
*/
struct thread_info thread_info;
#endif
/* -1 unrunnable, 0 runnable, >0 stopped: */
volatile long state;
......
x86:
struct thread_info {
unsigned long flags; /* low level flags */
u32 status; /* thread synchronous flags */
};
ARM:
struct thread_info {
unsigned long flags; /* low level flags */
int preempt_count; /* 0 => preemptable, <0 => bug */
mm_segment_t addr_limit; /* address limit */
struct task_struct *task; /* main task structure */
… …
};
宏“CONFIG_THREAD_INFO_IN_TASK”决定了thread_info是在thread_union中还是task_struct中。
以下是在我本地的Ubuntu VM中获取的信息:
root@john-virtual-machine:/boot# uname -r
4.15.0-140-generic
root@john-virtual-machine:/boot# grep CONFIG_THREAD_INFO_IN_TASK config-4.15.0-140-generic
CONFIG_THREAD_INFO_IN_TASK=y
CONFIG_THREAD_INFO_IN_TASK=y, 说明thread_info在task_struct中,而不在thread_union。此时thread_info作为task_struct的第一个成员, thread_union只有栈。(借图)
PID: 1 TASK: ffff8ebeb866ae00 CPU: 0 COMMAND: "systemd"
struct task_struct {
thread_info = {
flags = 0,
status = 0
},
current宏
内核通过current宏获得进程的task_Struct,分别通过分析x86和arm架构了解current的具体实现。
ARM32:
register unsigned long current_stack_pointer asm ("sp");
static inline struct thread_info *current_thread_info(void)
{
return (struct thread_info *)
(current_stack_pointer & ~(THREAD_SIZE - 1));
}
把栈指针的低N位清零,即获得栈内存区域底部的struct thread_info地址。
ARM64:使用sp_el0存储task_struct地址。
x86:
使用每CPU变量current_task来保存当前运行进程的task_struct