Linux内核进程管理子系统有什么第六十七回 —— 进程主结构详解(63)
接前一篇文章:Linux内核进程管理子系统有什么第六十六回 —— 进程主结构详解(62)
本文内容参考:
Linux内核进程管理专题报告_linux rseq-CSDN博客
《趣谈Linux操作系统 核心原理篇:第三部分 进程管理》—— 刘超
《图解Linux内核 基于6.x》 —— 姜亚华 机械工业出版社
https://blog.csdn.net/weixin_45030965/article/details/132734258
特此致谢!
进程管理核心结构 —— task_struct
12. current
前几回讲了current在x86以及ARM上的实现,本回来看本部分剩余的一个知识点:通过task_struct定位内核栈stack和通过内核栈定位task_struct。在其中还会涉及到一个重要的结构体 —— struct pt_regs。
- 通过内核栈stack找task_struct
上一回讲到,对于MIPS、LoongArch等架构来说,其struct thread_info中包含了struct task_struct *task成员,能够通过current_thread_info()->task来获取task_struct,从而实现通过内核栈stack获取task_struct(当然,前提是定义了CONFIG_THREAD_INFO_IN_TASK)。
本回来讲解对于那些struct thread_info中没有struct task_struct的体系结构来说,又该如何通过内核栈stack找到task_struct。
以x86和ARM为例。
x86中struct thread_info的定义
arch/x86/include/asm/thread_info.h中:
struct thread_info {unsigned long flags; /* low level flags */unsigned long syscall_work; /* SYSCALL_WORK_ flags */u32 status; /* thread synchronous flags */
#ifdef CONFIG_SMPu32 cpu; /* current CPU */
#endif
};
ARM中struct thread_info的定义
arch/arm/include/asm/thread_info.h中:
struct thread_info {unsigned long flags; /* low level flags */int preempt_count; /* 0 => preemptable, <0 => bug */__u32 cpu; /* cpu */__u32 cpu_domain; /* cpu domain */struct cpu_context_save cpu_context; /* cpu context */__u32 abi_syscall; /* ABI type and syscall nr */__u8 used_cp[16]; /* thread used copro */unsigned long tp_value[2]; /* TLS registers */union fp_state fpstate __attribute__((aligned(8)));union vfp_state vfpstate;
#ifdef CONFIG_ARM_THUMBEEunsigned long thumbee_state; /* ThumbEE Handler Base register */
#endif
};
ARM64中struct thread_info的定义
arch/arm64/include/asm/thread_info.h中:
struct thread_info {unsigned long flags; /* low level flags */
#ifdef CONFIG_ARM64_SW_TTBR0_PANu64 ttbr0; /* saved TTBR0_EL1 */
#endifunion {u64 preempt_count; /* 0 => preemptible, <0 => bug */struct {
#ifdef CONFIG_CPU_BIG_ENDIANu32 need_resched;u32 count;
#elseu32 count;u32 need_resched;
#endif} preempt;};
#ifdef CONFIG_SHADOW_CALL_STACKvoid *scs_base;void *scs_sp;
#endifu32 cpu;
};
这些体系结构的struct thread_info中没有task_struct相关成员,那又该如何获取当前运行中的task_struct呢?还是得依靠current_thread_info。
上一回讲到过current_thread_info,它一个体系结构相关的,再来回顾一下:

而在这里current_thread_info又有了一个更一般(化)的定义,在include/linux/thread_info.h中,如下:
#ifdef CONFIG_THREAD_INFO_IN_TASK
/** For CONFIG_THREAD_INFO_IN_TASK kernels we need <asm/current.h> for the* definition of current, but for !CONFIG_THREAD_INFO_IN_TASK kernels,* including <asm/current.h> can cause a circular dependency on some platforms.*/
#include <asm/current.h>
#define current_thread_info() ((struct thread_info *)current)
#endif
那current又是什么呢?它实际上也是体系结构相关的,不过各个体系结构中基本都是以下定义:
#define current get_current()
只不过get_current()的定义各不相同。以x86为例,get_current()的定义在arch/x86/include/asm/current.h中,如下:
DECLARE_PER_CPU(struct task_struct *, current_task);static __always_inline struct task_struct *get_current(void)
{return this_cpu_read_stable(current_task);
}#define current get_current()
由代码会发现,在新的机制中,每个CPU运行的task_struct不再是通过thread_info获取了,而是直接放在了Pre CPU变量中。
对于Per CPU变量及机制的讲解,请看下回。
