内核如何知道当前线程是什么?

时间:2012-08-30 08:55:39

标签: c linux-kernel kernel arm

有人可以解释一下从Linux内核获取的代码片段here吗?

/*
  * how to get the thread information struct from C
 */
 static inline struct thread_info *current_thread_info(void) __attribute_const__;

 static inline struct thread_info *current_thread_info(void)
 {
        register unsigned long sp asm ("sp");
        return (struct thread_info *)(sp & ~(THREAD_SIZE - 1));
}

问题:

  1. 什么是__attribute_const__
  2. 这是做什么register unsigned long sp asm ("sp");
  3. 为什么(struct thread_info *)(sp & ~(THREAD_SIZE - 1));返回a 指向结构的指针?

2 个答案:

答案 0 :(得分:14)

  1. 属性const表示返回的指针在程序持续时间内保持不变。实际上,只有在一个线程的范围内才是这样,但我想不出编译器甚至会尝试优化线程之间的访问的任何情况。

  2. 使用registerasm("sp")将变量绑定到名为sp的硬件寄存器,即当前堆栈指针。这样,代码就不必用汇编语言来直接访问该寄存器。

  3. THREAD_SIZE是一个常量,它给出了为线程堆栈分配的内存量。我假设它总是必须是2的幂,例如8千字节可能是一个典型值。

    表达式~(THREAD_SIZE - 1)然后给出一个位掩码来删除实际的堆栈地址。对于8 kB堆栈,它将是0xffffe000

    通过按位并使用堆栈指针值,我们得到为堆栈分配的最低地址。在此体系结构中,线程信息存储在那里。这只是一个设计决定,他们可以使用其他一些地方来存储信息。

    堆栈指针对于获取线程信息很有用,因为每个线程总是有自己的堆栈。

答案 1 :(得分:8)

Linux中的内核堆栈具有固定大小(THREAD_SIZE - 2页,或x86上的8KB)。线程的struct thread_info保留在堆栈内存块的底部。请记住堆栈向下工作,因此堆栈指针最初指向内存块的末尾,当数据被推入堆栈时,堆栈指针向内存块的底部移动。当然,其他CPU架构可能会使用其他技术。

因此,如果您获取当前堆栈指针值,并屏蔽掉低位数位,则会使用当前堆栈获得指向线程struct thread_info的指针。

该行:

register unsigned long sp asm ("sp");

告诉GCC将变量sp映射到CPU寄存器sp(我觉得这里使用的是16位寄存器名称 - 这是来自实际的Linux源代码树吗?)。

当GCC是编译器时,

__attribute_const__通常被定义为__attribute__((__const__))(对于Linux内核,它是否还有其他任何东西?)。这告诉GCC该函数没有副作用 - 实际上它比它强一点:函数只使用参数并仅返回基于那些参数的值。这可能为编译器提供了一些优化机会 - 它可以假设没有更改全局变量,甚至没有读取(因此编译器可以自由推迟更新内存,它可能需要更新“正常”函数调用)。