Linux内核:线程与进程 - task_struct与thread_info

时间:2014-01-26 06:33:21

标签: linux multithreading process kernel

我读到Linux不支持线程或轻量级进程的概念,并且它认为内核线程就像任何其他进程一样。但是这个原则在代码中并没有非常准确地反映出来。我们看到task_struct保存了进程的状态信息(如果错误则纠正我)以及thread_info附加到进程'内核堆栈的底部。

现在的问题是,当linux应该像任何其他进程一样解释线程时,为什么代码通过 thread_info 支持单独线程的概念?

请让我知道我在这里缺少什么 - 我是linux内核开发的新手。

5 个答案:

答案 0 :(得分:14)

Linux中的线程被视为恰好共享某些资源的进程。每个线程都有自己的thread_info(就像你说的那样在栈的底部)和它自己的task_struct。我可以想到为什么将它们作为单独的结构维护的两个原因。

  1. thread_info取决于架构。 task_struct是通用的。
  2. thread_info会削减该进程的内核堆栈大小,因此应保持较小。 thread_info作为微优化放置在堆栈的底部,通过向下舍入保存CPU寄存器的堆栈大小,可以从当前堆栈指针计算其地址。

答案 1 :(得分:4)

正如彼得所说,thread_info是特定于体系结构的,它包含必要的信息,如寄存器,pc,fp等。

在上下文切换期间保存/恢复流程执行需要此信息。

http://lxr.free-electrons.com/source/arch/arm/include/asm/thread_info.h#L33

task_struct - > thread_info - > struct cpu_context_save cpu_context

答案 2 :(得分:3)

旧方法:在较旧的内核中,在2.6之前,进程描述符是静态分配的,因此可以从此结构中的特定偏移量中读取值。

新方法但是在2.6及更高版本中,您可以使用slab分配器动态分配进程描述符。因此,较旧的方法不再有效。因此引入了Thread_info

在Linux内核开发,第3章:

一书中有清楚地提到
  

task_struct结构通过slab分配器分配给   提供对象重用和缓存着色(参见第11章“内存   管理“)。在2.6内核系列之前,struct task_struct是   存储在每个进程的内核堆栈的末尾。这允许   具有很少寄存器的架构,例如x86,来计算   过程描述符的位置通过堆栈指针而不使用   存储位置的额外寄存器。用进程描述符   现在通过slab分配器动态创建一个新的结构,   struct thread_info,创建了再次生活在底部   堆栈(用于堆积的堆栈)和堆栈顶部(用于   成长的堆栈)[4]。见图3.2。新结构也有   它很容易计算其值的偏移量,以便在装配中使用   代码。

答案 3 :(得分:1)

task_struct是一个大型数据结构。因此,存储大型结构的任务非常困难。所以内核引入了thread_info的概念,它比task_struct更加纤细,只指向task_struct结构。

Source

答案 4 :(得分:0)

Linux 支持线程。

线程类似于进程,但每个进程都有自己的地址空间(堆栈、堆、程序代码),线程共享地址空间,因此每个进程都可以访问堆数据。由于地址空间是共享的,因此在上下文切换期间,我们不需要切换用于将虚拟内存转换为物理内存的页表。由于在多线程应用程序中两个线程访问相同的地址空间,因此您将拥有多个堆栈区域,每个线程一个。

是的,进程的状态作为状态存储在 task_struct 中。您可以通过转到 sched.h 文件来探索 task_struct 中存储的内容。

线程和进程非常相似,但有时您想要共享数据,即当您对大型数据集进行操作时(添加两个大型数组等)。

Single-Threaded vs multi-threaded enter image description here enter image description here