2014-03-03 29 views
2

在阅读“了解Linux内核”时我发现联合正在用于进程描述符数据结构。在Linux进程描述符中使用联合的工作

union thread_union { 
    struct thread_info thread_info; 
    unsigned long stack[2048]; /* 1024 for 4KB stacks */ 
}; 

为什么使用这里的工会工会union thread_union这里,在同时使用这两个数据结构?

+0

联合在这里使用可能是因为'thread_info'和'stack'不是同时需要的。 –

+1

或者数据大小需要是某种页面大小的倍数,并且结构位于堆栈顶部。这是我认为的一个填充技巧。 – tangrs

+0

@leeduhem即使我在猜测。但不确定我们怀疑的“需求”! – neeru

回答

2

首先,它是

union thread_union { 
    struct thread_info thread_info; 
    unsigned long stack[THREAD_SIZE/sizeof(long)]; 
}; 

在内核include/linux/sched.h定义)。这一点很重要,因为宏THREAD_SIZE在很多地方都有使用(内核源代码总共有几百次),并且在不同的体系结构中有所不同。

的OP想知道为什么不使用,而不是一个结构:

struct thread_struct { 
    struct thread_info thread_info; 
    unsigned long stack[(THREAD_SIZE - sizeof (struct thread_info))/sizeof (long)]; 
}; 

(我假设相关宏,init_thread_infoinit_stack,进行相应的调整,即都是指init_thread_union的开始,所以那实际的存储器布局没有改变。)

简单的原因是联盟的两个成员是想要驻留在同一个内存区域,因此union更合适。

完整的推理比较复杂。主要的一点是,所有的硬件架构上限定在init/init_task.c此联合类型的init_thread_union变量,用于在启动时的初始内核线程,和预处理宏

#define init_thread_info (init_thread_union.thread_info) 
#define init_stack   (init_thread_union.stack) 

在特定体系结构的头文件(例如,在arch/x86/include/asm/thread_info.h 86)。这些宏分别指向初始线程(启动内核的那个线程)和它的堆栈。

据我所知,union thread_union类型不用于除初始堆栈和线程信息之外的任何其他目的。此外,init_thread_info部分仅在启动时需要,而不是稍后。

这意味着如果使用结构而不是联合,那么只要内核运行,struct thread_info部分就会在内存中保持未使用状态。当然,这不是很多字节..但是,使用联合 - 记住,在Linux中,堆栈变小 - 初始线程信息位于初始堆栈区域的末尾,并且如果在某个时刻有一个深度在内核代码中有足够的调用链需要每一个可用的内核堆栈,初始的thread_info将被堆栈数据覆盖。哪个没关系,因为它不再需要。 (如果你非常尖锐,你会意识到使用这个结构会产生相同的实际效果:用完init_stack会溢出到init_thread_info成员中,覆盖它。假设,正如我在括号中所指出的那样,如果宏未调整,则初始线程信息将保留在内存中,未使用,直到重新启动或关闭。)

所以,总结一下,工会是因为内核开发者专门用于初始线程信息和初始堆栈(用于启动内核的线程)的联合类型,所以更合适,并且明确希望它们占用相同的内存区域。虽然使用结构可以达到完全相同的实际效果,但它会使宏不必要地变得复杂,从而浪费其他/未来开发人员试图破译原始意图的时间。

最后,请记住,内核开发人员比理论或标准更感兴趣的实际结果。例如,C编译器编写者可能会指出,根据C标准,访问联合的另一个成员比联合的最后一个赋值中使用的成员不同,会得到未定义的结果。这并不重要:内核取决于实际的真实世界的行为,而不是任何标准的文本。这也意味着阅读代码,评论以及关于LKML或与内核相关的其他邮件列表的讨论,总是比依靠一般C知识更具启发性和可靠性。

+0

在你看来,初学者应该如何从内核源代码开始。我认为从本书开始很好。 – neeru

+1

@neeru:我认为[kernelnewbies.org](http://kernelnewbies.org/),尤其是[Kernel Hacking](http://kernelnewbies.org/KernelHacking)部分是一个很好的起点。就我个人而言,我所了解的关于内核的一切都是因为我有一些特定的东西需要修复,修改,扩展或理解。我热烈推荐你开始使用一些你觉得特别有趣的驱动程序或功能。如果没有您感兴趣的驱动程序或子系统,请查看[Kernel Janitors](http://kernelnewbies.org/KernelJanitors)项目。潜入,并尽力发挥作用。每个人都有空间。 –

+0

我不确定你的声明'union thread_union'只在启动时用于初始内核线程是真的。 Afaik每个进程都有一个'union thread_union'。 –