Linux 理解从进程内核堆栈获取任务结构指针

Linux 理解从进程内核堆栈获取任务结构指针,linux,linux-kernel,Linux,Linux Kernel,现在我正在读罗伯特·洛夫的《Linux内核开发3d版》。在那里,他写了关于thread_info struct的文章,其中包含指向task_struct的指针,据我所知,它位于进程内核堆栈的底部或顶部(取决于体系结构)。直到最近我才熟悉Linux内核API,也不知道current()方法的存在。这本书中有一段摘录,与current()方法的实际工作原理有关: 在x86上,通过屏蔽堆栈的13个最低有效位来计算电流 获取线程信息结构的指针。这由 当前_thread_info()函数。程序集如下所示:

现在我正在读罗伯特·洛夫的《Linux内核开发3d版》。在那里,他写了关于thread_info struct的文章,其中包含指向task_struct的指针,据我所知,它位于进程内核堆栈的底部或顶部(取决于体系结构)。直到最近我才熟悉Linux内核API,也不知道current()方法的存在。这本书中有一段摘录,与current()方法的实际工作原理有关:

在x86上,通过屏蔽堆栈的13个最低有效位来计算电流 获取线程信息结构的指针。这由 当前_thread_info()函数。程序集如下所示: movl$-8192,%eax andl%esp,%eax 这假设堆栈大小为8KB。启用4KB堆栈时,将在中使用4096 代替8192

我的问题是:

  • 据我所知,如果我们用一组位来表示一个十进制值,那么这个集合中只有一个最低有效位,不是吗
  • 神奇的数字13是什么

  • 对于将阅读本主题的千人来说,我提出的问题可能会得出结论,即作者没有正确理解内存分配和管理的过程。好的,这可能是正确的,因为在我看来,我可以将分配给堆栈的内存表示为充满位(或字节)的功能区。所有这些字节都可以由一个特定的内存地址访问,该地址表示为某个十进制值。堆栈的原点是最低的内存地址,堆栈的尾端是内存地址的最高值。但是,我们如何才能通过屏蔽掉任意位置堆栈指针的13个最低有效位(如果我理解正确,我们屏蔽掉以十进制值表示的堆栈指针地址位)来获取位于堆栈末尾的thread_info结构的指针。

    每个进程只获得8192字节的内核堆栈,与8192字节边界对齐,因此每当堆栈指针被push或pop更改时,低13位是唯一更改的部分。2**13==8192。

    内核堆栈在顶部包含一个特殊的结构--:

    。。。或从C代码中选择:

    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 }
    
    请注意,
    THREAD\u SIZE
    定义为
    (PAGE\u SIZE
    但是,我们如何,如何仅通过屏蔽位于堆栈指针任意位置的13个最低有效位来获取位于堆栈末尾的thread_info结构的指针呢


    请注意,底部和限制(顶部)地址(假设底部具有较高地址的自下而上堆栈)必须是堆栈大小的倍数。例如,如果堆栈大小为8192(=2^13),对于底部地址和限制地址,13个最低有效位必须全部为0。最低有效13位不是任意的,因为它给出了底部地址和限制地址之间的偏移量,这两个地址都以13 0结尾。因此,屏蔽掉最低有效13位可以得到限制地址的地址,即线程信息结构的位置。

    我的2位:注意,“当前”的实现取决于arch。到目前为止,答案集中在x86上;获取线程信息和任务结构的各种方法被Linux操作系统上的其他arch采用

    例如,显然PPC使用一个寄存器(记住,它是RISC,有大量GPRs)来存储当前值-实际上是将其作为硬件上下文的一部分!这将非常快


    现代x86端口(我查阅了4.1.0内核源代码)使用每个cpu的数据以一种快速且无锁的方式实现电流。依此类推……

    提示:2乘以13=8192的幂(即堆栈的大小),十进制值-8192是十六进制0xFFFFFF000(在2互补平台上以32位表示)。您说“十进制值”有几次-您可能最好考虑二进制值,尤其是尝试了解掩蔽是如何工作的。
    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
    
    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 }