请教Linux内核区分TASK_RUNNING的running/ready状态及当前运行任务查询方法
Hey there! Let's tackle your Linux process state questions one by one—this is a common point of confusion since the kernel's TASK_RUNNING state wraps two distinct scenarios.
First off, it’s important to clarify: Linux’s official process state enum only defines TASK_RUNNING as a single state, but it actually covers two practical sub-states:
- Running: The process is actively executing instructions on a CPU core right now.
- Ready: The process is eligible to run (it’s not blocked on I/O or a signal) but is waiting in the scheduler’s run queue for its turn on a CPU.
You mentioned not finding a direct field in task_struct for this—and that’s intentional! The kernel doesn’t store this sub-state in the process’s own struct. Instead, it tracks it via the process’s position in the scheduler’s data structures.
There are both user-space tools and kernel-space ways to get this info:
User-space methods
top: Press1to view all CPU cores individually. The process listed under each core’s section is the one currently running on that CPU. You can also look for processes marked withR(TASK_RUNNING) and note which ones are actively using CPU (high %CPU values).pswith custom fields: Runps -axo pid,comm,psr,state,%cputo see each process’s PID, name, bound CPU (psr), state, and CPU usage. Processes withRstate and high %CPU are likely running, but to confirm the exact running task on a CPU, combine this withtop’s real-time view./procfilesystem: Check/proc/[pid]/stat—the 39th field (for Linux 5.x+) tells you the CPU the process is currently running on. For the CPU’s current task, you can look at/proc/sched_debug(requires root) which lists the current running task for each CPU undercpu[X]sections.
Kernel-space methods
If you’re writing kernel code, you can:
- Use the
currentmacro: This directly points to thetask_structof the process currently running on the CPU that’s executing your code. - Traverse per-CPU runqueues: Each CPU has a
struct rq(runqueue) structure. Therq->currfield holds the task currently running on that CPU, whilerq->taskslists all ready TASK_RUNNING processes waiting to be scheduled.
The kernel’s scheduler maintains a separate runqueue (struct rq) for each CPU core. Here’s how it tracks the two TASK_RUNNING sub-states:
- When a process is actively running on a CPU, it’s stored in
rq->currfor that CPU’s runqueue. - When a process is ready to run but waiting for a CPU, it’s added to the
rq->taskslinked list (or a more efficient priority queue, depending on the scheduler—like CFS for fair scheduling).
When the scheduler performs a context switch:
- It takes the current process from
rq->currand moves it back to the runqueue’s ready list (if it’s still TASK_RUNNING and hasn’t blocked). - It selects the next process from the ready list and sets it as
rq->curr, then switches the CPU’s execution to this new process.
This means the kernel doesn’t need to store the sub-state in task_struct—it’s determined entirely by where the process resides in the scheduler’s runqueue structures.
内容的提问来源于stack exchange,提问作者Arpeggio91

