无法了解“当前”宏如何用于x86体系结构

时间:2018-12-27 06:48:08

标签: c linux process linux-kernel

我试图了解current宏的工作原理,因此开始浏览Linux内核源代码版本4.19。试图了解x86架构

include / asm-generic / current.h:8

#define get_current() (current_thread_info()->task)
#define current get_current()

然后我试图找到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

然后我尝试查找当前定义

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()

get_current()再次返回struct task_struct,为什么我们在current_thread_info()中将其类型转换为struct thread_info。

能请您解释一下如何执行电流。我读到它放在内核堆栈顶部或底部的某个地方

1 个答案:

答案 0 :(得分:0)

要投射指针-struct thread_info thread_infofirst member of the struct task_struct

struct task_struct {
#ifdef CONFIG_THREAD_INFO_IN_TASK
    /*
     * For reasons of header soup (see current_thread_info()), this
     * must be the first element of task_struct.
     */
    struct thread_info      thread_info;
#endif

强制转换是合法的-我们正在返回指向struct的第一个成员的指针。它可能使用类似的&current->thread_info,但是如果在某些情况下struct task_struct的定义是 opaque (即它是不完整的类型),则不能使用它!


关于DECLARE_PER_CPU的工作方式,这取决于。您过去所学的内容可能不再适用于此。使用特殊的宏读取和更新用DECLARE_PER_CPU声明的变量。其他 这是因为在x86上,读取是通过特殊的段寄存器进行的。然后,其他CPU架构必须使用完全不同的方法来访问每CPU值。

通常,应使用this_cpu_read读取per-cpu变量,这不允许GCC以任何方式对其进行缓存,但是当前线程信息是一个例外,因为当前线程始终在当前线程中运行它在什么CPU上。来自arch/x86/include/asm/percpu.h

/*
 * this_cpu_read() makes gcc load the percpu variable every time it is
 * accessed while this_cpu_read_stable() allows the value to be cached.
 * this_cpu_read_stable() is more efficient and can be used if its value
 * is guaranteed to be valid across cpus.  The current users include
 * get_current() and get_thread_info() both of which are actually
 * per-thread variables implemented as per-cpu variables and thus
 * stable for the duration of the respective task.
 */