Deep Dive into Linux Kernel task_struct: Structure, Fields, and Usage
This article provides a comprehensive analysis of the Linux kernel's task_struct data structure, detailing its members such as task IDs, parent‑child relationships, state flags, credentials, scheduling information, signal handling, memory and file management, kernel stack layout, and its role in process creation via system calls like fork.
In the complex world of the Linux kernel, the task_struct structure serves as the central repository for all information about a task (process or thread). Understanding this structure is essential for performance analysis, debugging, and grasping how the kernel schedules and manages thousands of tasks.
1. Introduction
Every process or thread in Linux is represented by a task_struct instance. The kernel uses this unified structure to store identifiers, resource usage, scheduling data, and more.
2. task_struct Structure
2.1 Task IDs
The unique identifiers for a task are stored as:
pid_t pid;
pid_t tgid;
struct task_struct *group_leader;pid is the process ID, tgid is the thread‑group ID, and group_leader points to the leader of the thread group. If a process has only one thread, pid and tgid are equal and group_leader points to itself; otherwise they differ, allowing the kernel to distinguish processes from threads.
2.2 Parent‑Child Relationships
Each task maintains pointers to its parent and children:
struct task_struct __rcu *real_parent; /* real parent process */
struct task_struct __rcu *parent; /* recipient of SIGCHLD */
struct list_head children; /* list of my children */
struct list_head sibling; /* linkage in my parent's children list */parent receives signals when the child exits, while children and sibling form the process tree.
2.3 Task State
State information is stored in:
volatile long state; /* -1 unrunnable, 0 runnable, >0 stopped */
int exit_state;
unsigned int flags;The state field uses bit‑defined constants (e.g., TASK_RUNNING , TASK_INTERRUPTIBLE , TASK_UNINTERRUPTIBLE , etc.) defined in include/linux/sched.h . These values determine whether a task is runnable, sleeping, stopped, or being traced.
2.4 Flags (PF_*)
Additional status bits are stored in flags :
#define PF_EXITING 0x00000004
#define PF_VCPU 0x00000010
#define PF_FORKNOEXEC 0x00000040Examples include PF_EXITING (task is exiting) and PF_VCPU (running on a virtual CPU).
2.5 Credentials
Permission information is kept in:
const struct cred __rcu *real_cred; /* real credentials */
const struct cred __rcu *cred; /* effective credentials */The cred structure contains UID/GID, saved IDs, filesystem IDs, and capability sets, which the kernel checks for permission enforcement.
2.6 Run Statistics
Runtime accounting fields include:
u64 utime; /* user‑mode CPU time */
u64 stime; /* kernel‑mode CPU time */
unsigned long nvcsw; /* voluntary context switches */
unsigned long nivcsw; /* involuntary context switches */
u64 start_time; /* start time (excluding sleep) */
u64 real_start_time; /* start time (including sleep) */2.7 Scheduling Information
Key scheduling members are:
int on_rq; /* on run‑queue flag */
int prio; /* dynamic priority */
int static_prio;
int normal_prio;
unsigned int rt_priority;
const struct sched_class *sched_class;
struct sched_entity se;
struct sched_rt_entity rt;
struct sched_dl_entity dl;
unsigned int policy;
int nr_cpus_allowed;
cpumask_t cpus_allowed;
struct sched_info sched_info;2.8 Signal Handling
Signal‑related members:
struct signal_struct *signal;
struct sighand_struct *sighand;
sigset_t blocked;
sigset_t real_blocked;
sigset_t saved_sigmask;
struct sigpending pending;
unsigned long sas_ss_sp;
size_t sas_ss_size;
unsigned int sas_ss_flags;Signals are categorized as blocked, pending, or currently being handled.
2.9 Memory Management
Memory descriptors are referenced via:
struct mm_struct *mm;
struct mm_struct *active_mm;2.10 Filesystem Information
Filesystem and open‑file structures:
struct fs_struct *fs; /* filesystem info */
struct files_struct *files;/* open file table */2.11 Kernel Stack
The kernel stack is linked through:
struct thread_info thread_info;
void *stack;On 32‑bit systems THREAD_SIZE is 8 KB; on 64‑bit it is 16 KB (or larger with KASAN). The stack layout includes a padding area, register save area, and the thread_info structure.
2.12 Accessing task_struct from Stack and Vice‑versa
Utility functions:
static inline void *task_stack_page(const struct task_struct *task) {
return task->stack;
}
#define task_pt_regs(task) ({
unsigned long __ptr = (unsigned long)task_stack_page(task);
__ptr += THREAD_SIZE - TOP_OF_KERNEL_STACK_PADDING;
((struct pt_regs *)__ptr) - 1;
})Per‑CPU variable current_task holds the pointer to the currently running task, allowing fast access without traversing thread_info .
3. task_struct and System Calls
3.1 Fork Example
When fork() is invoked, the kernel allocates a new task_struct for the child, copies most fields from the parent, and sets up copy‑on‑write (COW) for memory pages. The child receives a new pid , its ppid is set to the parent’s PID, and other attributes such as process group, session, signal handlers, and file descriptors are adjusted.
3.2 Impact on Process Management
The COW mechanism reduces memory overhead during process creation, while the independent task_struct instances allow the scheduler to make decisions based on each task’s state, priority, and other metrics, ensuring fair CPU allocation and isolation between parent and child processes.
Deepin Linux
Research areas: Windows & Linux platforms, C/C++ backend development, embedded systems and Linux kernel, etc.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.