了解从进程内核堆栈获取task_struct指针

mes*_*ngr 5 linux linux-kernel

现在,我正在阅读Robert Love的书“ Linux Kernel Development 3d Edition”。他在那里写了有关thread_info结构的信息,该结构包含指向task_struct结构的指针,并且据我所知,它位于进程的内核堆栈的底部或顶部(取决于体系结构)。直到最近我才对Linux内核API感到陌生,并且不了解current()方法的存在。本书摘录涉及current()方法的实际工作方式:

在x86上,电流是通过屏蔽堆栈指针的13个最低有效位以获得thread_info结构来计算的,这是通过current_thread_info()函数完成的,该程序集如下所示:movl $ -8192,%eax和l% esp,%eax假定堆栈大小为8KB。启用4KB堆栈时,将使用4096代替8192。

我的问题是:

  1. 据我所知,如果我们将十进制值表示为一组位,那么该组中只有一个最低有效位,不是吗?
  2. 神奇的数字13是多少?

对于那些将阅读本主题的人来说,我所说的问题可能会导致结论,即作者对内存分配和管理过程的理解不正确。好的,由于我可以将分配给堆栈的内存表示为充满位(或字节)的功能区,因此这可能是正确的。所有这些字节都可以由表示为十进制值的特定内存地址访问。堆栈的原点是最低的内存地址,堆栈的fin是最高的内存地址值。但是,我们如何才能仅通过屏蔽位于ARBITRARY所在的堆栈指针的13个最低有效位来获得指向位于堆栈末尾的thread_info结构的指针(如果我理解正确,我们就屏蔽掉了堆栈指针ADDRESS表示为十进制值)。

Ily*_*kov 3

内核堆栈的顶部包含一个特殊的结构体——thread_info

 26 struct thread_info {
 27         struct task_struct      *task;          /* main task structure */
 28         struct exec_domain      *exec_domain;   /* execution domain */
 29         __u32                   flags;          /* low level flags */
 30         __u32                   status;         /* thread synchronous flags */
 31         __u32                   cpu;            /* current CPU */
 32         int                     preempt_count;  /* 0 => preemptable,
 33                                                    <0 => BUG */
 34         mm_segment_t            addr_limit;
 35         struct restart_block    restart_block;
 36         void __user             *sysenter_return;
 37 #ifdef CONFIG_X86_32
 38         unsigned long           previous_esp;   /* ESP of the previous stack in
 39                                                    case of nested (IRQ) stacks
 40                                                 */
 41         __u8                    supervisor_stack[0];
 42 #endif
 43         unsigned int            sig_on_uaccess_error:1;
 44         unsigned int            uaccess_err:1;  /* uaccess failed */
 45 };
Run Code Online (Sandbox Code Playgroud)

因此,要获取,task_struct您需要从 ASM 代码中使用GET_THREAD_INFOthread_info获取指针:

183 /* how to get the thread information struct from ASM */
184 #define GET_THREAD_INFO(reg)     \
185         movl $-THREAD_SIZE, reg; \
186         andl %esp, reg
Run Code Online (Sandbox Code Playgroud)

...或者使用C 代码中的current_thread_info :

174 /* how to get the thread information struct from C */
175 static inline struct thread_info *current_thread_info(void)
176 {
177         return (struct thread_info *)
178                 (current_stack_pointer & ~(THREAD_SIZE - 1));
179 }
Run Code Online (Sandbox Code Playgroud)

请注意,对于 x86_32 和 x86_64 THREAD_SIZE,定义为 且(PAGE_SIZE << THREAD_SIZE_ORDER)等于1,因此结果为 8192(2^13 或 1<<13)。THREAD_SIZE_ORDERTHREAD_SIZE