Inside Linux: How the Kernel Represents and Manages Processes with task_struct
This article explains how a user‑level program becomes a Linux process, how the kernel views it through ELF loading, the role of the task_struct data structure, its key fields, task state transitions, and how the kernel stores the descriptor in memory.
From Program to Process in the Kernel
A program becomes a process when the ELF executable is handed to the Linux kernel; the kernel then creates a task_struct to represent that process.
Kernel Representation: task_struct
The kernel uses the task_struct structure to store all information about a process, including identifiers, state, scheduling policy, memory management, file descriptors, signals, and more.
struct task_struct {
volatile long state; // -1 unrunnable, 0 runnable, >0 stopped
unsigned long flags; // process flags, set at fork()
int sigpending; // pending signals
mm_segment_t addr_limit; // address limit (user vs kernel)
volatile long need_resched; // need reschedule flag
int lock_depth; // lock depth
long nice; // nice value (time slice)
unsigned long policy; // scheduling policy (SCHED_FIFO, SCHED_RR, SCHED_OTHER)
struct mm_struct *mm; // memory management info
int processor; // CPU the task is running on
unsigned long cpus_runnable, cpus_allowed;
struct list_head run_list; // pointer to run queue
unsigned long sleep_time; // sleep time
struct task_struct *next_task, *prev_task; // doubly linked list (init_task is root)
struct mm_struct *active_mm;
struct list_head local_pages;
unsigned int allocation_order, nr_local_pages;
struct linux_binfmt *binfmt; // executable format
int exit_code, exit_signal;
int pdeath_signal; // signal sent to children on parent exit
unsigned long personality;
int did_exec:1;
pid_t pid; // process ID
pid_t pgrp; // process group ID
pid_t tty_old_pgrp;
pid_t session; // session ID
pid_t tgid;
int leader; // session leader flag
struct task_struct *p_opptr, *p_pptr, *p_cptr, *p_ysptr, *p_osptr;
struct list_head thread_group; // thread list
struct task_struct *pidhash_next; // hash table linkage
struct task_struct **pidhash_pprev;
wait_queue_head_t wait_chldexit; // for wait4()
struct completion *vfork_done; // for vfork()
unsigned long rt_priority; // real‑time priority
struct timer_list real_timer; // real‑time timer
struct tms times; // CPU time accounting
unsigned long start_time; // creation time
long per_cpu_utime[NR_CPUS], per_cpu_stime[NR_CPUS];
int swappable:1; // can be swapped out?
int ngroups; // number of groups
gid_t groups[NGROUPS];
kernel_cap_t cap_effective, cap_inheritable, cap_permitted;
int keep_capabilities:1;
struct user_struct *user;
struct rlimit rlim[RLIM_NLIMITS];
unsigned short used_math; // uses FPU?
char comm[16]; // executable name
int link_count, total_link_count;
struct tty_struct *tty; // controlling terminal
unsigned int locks;
struct sem_undo *semundo; // semaphore undo info
struct sem_queue *semsleeping; // waiting semaphore queue
struct thread_struct thread; // CPU context
struct fs_struct *fs; // filesystem info
struct files_struct *files; // open files
spinlock_t sigmask_lock;
struct signal_struct *sig; // signal handling
sigset_t blocked; // blocked signals mask
struct sigpending pending; // pending signals
/* ... many more fields omitted for brevity ... */
};Key Information Categories in task_struct
1. Identifier – unique PID and group IDs. 2. State – current task state, exit code, exit signal. 3. Priority – scheduling priority relative to other tasks. 4. Program Counter – address of the next instruction to execute. 5. Memory Pointers – pointers to code, data, and shared memory. 6. Context Data – register contents saved during a context switch. 7. I/O Status – open file list and device information. 8. Accounting – CPU time, clock ticks, limits, and resource usage.
Task State Transitions
The state field uses negative values for non‑runnable, zero for runnable, and positive values for stopped. Common values include:
-1: unrunnable (blocked, sleeping)
0: runnable (ready to run)
>0: stopped (e.g., stopped by a signal)
How the Kernel Stores task_struct
Each process has a user stack and a kernel stack. To save space, Linux places the thread_info structure (which contains a pointer to the task_struct) immediately before the kernel stack, forming a thread_union.
union thread_union {
#ifndef CONFIG_THREAD_INFO_IN_TASK
struct thread_info thread_info;
#endif
unsigned long stack[THREAD_SIZE / sizeof(long)];
};Conclusion
We have seen how a compiled program is transformed into a Linux process, how the kernel describes that process with the massive task_struct, how the structure is organized into logical categories, how task states change, and how the descriptor is stored alongside the kernel stack. Future articles will dive deeper into scheduling, memory management, and other aspects of process control.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Liangxu Linux
Liangxu, a self‑taught IT professional now working as a Linux development engineer at a Fortune 500 multinational, shares extensive Linux knowledge—fundamentals, applications, tools, plus Git, databases, Raspberry Pi, etc. (Reply “Linux” to receive essential resources.)
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.
