Understanding the getting of task_struct pointer from process kernel stack
The kernel stack contains a special struct at the top -- thread_info:
26 struct thread_info {
27 struct task_struct *task; /* main task structure */
28 struct exec_domain *exec_domain; /* execution domain */
29 __u32 flags; /* low level flags */
30 __u32 status; /* thread synchronous flags */
31 __u32 cpu; /* current CPU */
32 int preempt_count; /* 0 => preemptable,
33 <0 => BUG */
34 mm_segment_t addr_limit;
35 struct restart_block restart_block;
36 void __user *sysenter_return;
37 #ifdef CONFIG_X86_32
38 unsigned long previous_esp; /* ESP of the previous stack in
39 case of nested (IRQ) stacks
40 */
41 __u8 supervisor_stack[0];
42 #endif
43 unsigned int sig_on_uaccess_error:1;
44 unsigned int uaccess_err:1; /* uaccess failed */
45 };
So, to get the task_struct
you'll need to get a thread_info
pointer with GET_THREAD_INFO from the ASM-code:
183 /* how to get the thread information struct from ASM */
184 #define GET_THREAD_INFO(reg) \
185 movl $-THREAD_SIZE, reg; \
186 andl %esp, reg
... or with current_thread_info from the C-code:
174 /* how to get the thread information struct from C */
175 static inline struct thread_info *current_thread_info(void)
176 {
177 return (struct thread_info *)
178 (current_stack_pointer & ~(THREAD_SIZE - 1));
179 }
Note that THREAD_SIZE
defined as (PAGE_SIZE << THREAD_SIZE_ORDER)
and THREAD_SIZE_ORDER
equals 1 for both x86_32 and x86_64 so THREAD_SIZE
results to 8192 (2^13 or 1<<13).
How does the kernel use task_struct?
Yes, the task_struct
structure contains all the information about a process. You can obtain a pointer to the structure that describes the current process using the current
macro as follows:
struct task_struct *p = current;
If you want to get the structure that describes a process given a pid
, you can use the find_task_by_vpid
function as follows:
read_lock(&tasklist_lock);
p = find_task_by_vpid(pid);
if (p) get_task_struct(p);
read_unlock(&tasklist_lock);
if (p == NULL) {
// Task not found.
}
// Later, once you're finished with the task, execute:
put_task_struct(p);
Finally, if you want to iterate over all processes, you can use for_each_process
as follows:
read_lock(&tasklist_lock);
for_each_process(p) {
// p is a pointer to a task_struct instance.
}
read_unlock(&tasklist_lock);
If you want to an exclusive access to the task list to be able to make changes to one or more fields in the structure, write_lock_irqsave
must be used instead of read_lock
.
kernel stack for linux process
There is just one common kernel memory. In it each process has it's own task_struct + kernel stack (by default 8K).
In a context switch the old stack pointer is saved somewhere and the actual stack pointer is made to point to the top of the stack (or bottom depending on the hardware architecture) of the new process which is going to run.
Linux Kernel task_struct void *stack
In Linux kernel source code you can see the macros task_thread_info():
#define task_thread_info(task) ((struct thread_info *)(task)->stack)
The void *stack
pointer of task_struct
points to thread_info
.
Since 2.6 version Linux uses part of a task's kernel-stack page-frame to store "thread information" (thread_info
). The thread_info
in its turn includes a pointer to the task_struct
:
struct task_struct *task = info->task;
F.e. (for platforms where the stack grows in the direction of decreasing the value of the memory address):
Useful links: 1, 2
where are the pointers to the rest of the process image?
Such info is contained in memory descriptor mm_struct
. F.e.:
struct mm_struct {
//...
unsigned long start_code, end_code, start_data, end_data;
unsigned long start_brk, brk, start_stack;
//...
}
Must-read: How The Kernel Manages Your Memory
How 'task_struct' is accessed via 'thread_info' in linux latest kernel?
Pointer to the current task_struct
object is stored in architecture-dependent way. On x86 it is stored in per-CPU variable:
DECLARE_PER_CPU(struct task_struct *, current_task);
(In arch/x86/include/asm/current.h).
For find out how current task_struct
is stored on particular architecture and/or in particular kernel version just search for implementation of current
macro: exactly that macro is responsible for returning a pointer to the task_struct
of the current process.
Related Topics
Can Linux Flock(Fd, Lock_Ex|Lock_Nb) Fail Spuriously
How to Execute The Vim Commands Through Shell Script
Shell Script to Check Ubuntu Version and Then Copy Files
Linux Async (Io_Submit) Write V/S Normal (Buffered) Write
Prevent Fork() from Copying Sockets
Error Message When Setting Up Adt in Linux
Delete Line from Text File with Line Numbers from Another File
Sdl Configuration in Eclipse Ide
Qxcbconnection: Could Not Connect to Display Aborted, When Installing Qt on Linux
Linux Patch Ignoring Line Numbers
Naming Convention for Posix Flags
How to Build for Linux 32-Bit with Go1.6.2
How to Properly Debug a Bash Script
Default Font Size of Javafx Under Linux Is Larger as on Windows