Linux中写入union作用,Linux进程描述符中union的用法

首先,它是

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_info和init_stack会相应调整,即两者都引用init_thread_union的开头,这样实际的内存布局就不会改变。)

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

完整的推理更复杂。重点是所有体系结构在init/init_task.c中定义了此联合类型的init_thread_union变量,用于启动时的初始内核线程,以及预处理器宏

#define init_thread_info (init_thread_union.thread_info)

#define init_stack (init_thread_union.stack)

在特定于体系结构的头文件中(例如,在x86上的arch/x86/include/asm/thread_info.h中)。这些宏分别引用初始线程(启动内核的线程)及其堆栈。

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

这意味着如果使用结构而不是联合,只要内核运行,struct thread_info部分就会在内存中保持未使用状态。当然,它不是很多字节..但是,使用一个联合 - 记住在Linux中,堆栈增长 - 初始线程信息位于初始堆栈区域的末尾,如果在某些时候有一个深度内核代码中的足够的调用链需要每一位可用的内核堆栈,初始的thread_info将被堆栈数据覆盖。哪个没关系,因为不再需要了。

(如果你非常敏锐,你会发现使用这个结构具有同样的实际效果:init_stack的用完会溢出到init_thread_info成员中,覆盖它。假设,as我在括号中注意到,宏被调整为指向联合的开始。如果未调整宏,则初始线程信息将保留在内存中,未使用,直到重新启动或关闭。)

因此,总而言之,union更合适,因为内核开发人员专门为初始线程信息和初始堆栈(用于启动内核的线程)使用union类型,并且明确希望它们占用相同的记忆区域。尽管使用结构可以实现完全相同的实际效果,但它会使init_thread_info和init_stack宏不必要地复杂化,浪费其他/未来开发人员尝试破译原始意图的时间。

最后,请记住,内核开发人员对实际结果比对理论或标准更感兴趣。例如,C编译器编写者可以指出,根据C标准,访问联合的不同成员而不是最后一次赋值给union,会产生未定义的结果。这没关系:内核依赖于实际的,现实世界的行为,而不是任何标准的文本。这也意味着阅读LKML或与内核相关的其他邮件列表上的代码,注释和讨论,总是比依赖一般的C知识更具指导性和可靠性。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值