current宏在Linux 内核中负责获取当前cpu上的task_struct,通常是借助thread_info和内核栈实现
我们需要先找到对应的内核栈,内核栈的栈底位置就是thread_info结构体:
对于x86 64bit平台来说:
DECLARE_PER_CPU(unsigned long, kernel_stack);
212
213 static inline struct thread_info *current_thread_info(void)
214 {
215 struct thread_info *ti;
216 ti = (void *)(percpu_read_stable(kernel_stack) +
217 KERNEL_STACK_OFFSET - THREAD_SIZE);
218 return ti;
219 }
220
内核栈获取是通过读取kernel_stack这个percpu变量来得到的。那么整个过程是如何实现的呢:
定义kernel_stack percpu变量,通过kernel_stack + KERNEL_STACK_OFFSET - THREAD_SIZE即可获得内核栈的起始地址,所以kernel_stack 这个变量就是用来记录进程的内核栈的,在每次进程切换时,更新kernel_stack percpu变量记录当前进程的内核栈位置:
__notrace_funcgraph struct task_struct *
__switch_to(struct task_struct *prev_p, struct task_struct *next_p)
{
percpu_write(kernel_stack,
(unsigned long)task_stack_page(next_p) +
THREAD_SIZE - KERNEL_STACK_OFFSET);