I read that Linux does not support the concept of threads or light-weight processes and that it considers kernel threads just like any other process. However this principle is not very accurately reflected inside the code. We see task_struct that holds state information of a process (correct me if wrong) and also thread_info appended to the bottom of a process' kernel stack.
Now the question is why does the code support the concept of individual threading through thread_info when linux is supposed to interpret threads like any other process?
Please let me know what I am missing here - I am a newbie to linux kernel dev.
From what I think I've understood, task_struct is the C structure that acts as the process descriptor, holding everything the kernel might need to know about a processes. At the end of the process kernel stack lives another struct, thread_info , which has a pointer to the processes task_struct .
So that Linux can manage the processes in the system, each process is represented by a task_struct data structure (task and process are terms that Linux uses interchangeably). The task vector is an array of pointers to every task_struct data structure in the system.
struct thread_info is stored at the bottom of stack if stack grows down and up if stack grows up. Let, Kernel Stack is 8KB of size. Also, it should have struct thread_info in it. This gives the remaining size of 8192-52 = 8140 Bytes.
A kernel process controls directly the kernel threads. Because kernel processes are always in the kernel protection domain, threads within a kernel process are kernel-only threads. For more information on kernel threads, see Understanding Kernel Threads.
Threads in Linux are treated as processes that just happen to share some resources. Each thread has its own thread_info
(at the bottom of the stack like you said) and its own task_struct
. I can think of two reasons why they are maintained as separate structures.
thread_info
is architecture dependent. task_struct
is generic.thread_info
cuts into the size of the kernel stack for that process, so it should be kept small. thread_info
is placed at the bottom of the stack as a micro-optimization that makes it possible to compute its address from the current stack pointer by rounding down by the stack size saving a CPU register.Older approach: In the older kernel, prior to 2.6, process descriptors were allocated statically, hence it was possible to read the value from a particular offset from this struct.
New approach: But in 2.6 and later version, you could allocate process descriptors dynamically using slab allocator. Hence, the older approach no longer worked. Hence Thread_info
was introduced .
It is mentioned clearly in the book Linux Kernel Development, Chapter 3:
The task_struct structure is allocated via the slab allocator to provide object reuse and cache coloring (see Chapter 11, "Memory Management"). Prior to the 2.6 kernel series, struct task_struct was stored at the end of the kernel stack of each process. This allowed architectures with few registers, such as x86, to calculate the location of the process descriptor via the stack pointer without using an extra register to store the location. With the process descriptor now dynamically created via the slab allocator, a new structure, struct thread_info, was created that again lives at the bottom of the stack (for stacks that grow down) and at the top of the stack (for stacks that grow up)[4]. See Figure 3.2. The new structure also makes it rather easy to calculate offsets of its values for use in assembly code.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With