Linux内核分析之进程管理-06

韩乔落

第6章 进程状态与转换

基于 Linux 6.12.38 源码分析


6.1 进程状态定义

6.1.1 状态列表

位置: include/linux/sched.h:99

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/* Used in tsk->__state: */
#define TASK_RUNNING 0x00000000
#define TASK_INTERRUPTIBLE 0x00000001
#define TASK_UNINTERRUPTIBLE 0x00000002
#define __TASK_STOPPED 0x00000004
#define __TASK_TRACED 0x00000008

/* Used in tsk->exit_state: */
#define EXIT_DEAD 0x00000010
#define EXIT_ZOMBIE 0x00000020

/* Used in tsk->__state again: */
#define TASK_PARKED 0x00000040
#define TASK_DEAD 0x00000080
#define TASK_WAKEKILL 0x00000100
#define TASK_WAKING 0x00000200
#define TASK_NOLOAD 0x00000400
#define TASK_NEW 0x00000800
#define TASK_RTLOCK_WAIT 0x00001000
#define TASK_FREEZABLE 0x00002000
#define TASK_FROZEN 0x00008000

6.1.2 状态详解

TASK_RUNNING (0)

  • 任务就绪或正在运行
  • 在就绪队列中等待 CPU
  • 或正在 CPU 上执行

TASK_INTERRUPTIBLE (1)

  • 可中断睡眠状态
  • 等待某些条件满足
  • 可被信号唤醒

TASK_UNINTERRUPTIBLE (2)

  • 不可中断睡眠状态
  • 等待某些条件满足
  • 不能被信号唤醒

__TASK_STOPPED (4)

  • 任务被停止
  • 收到 SIGSTOP/SIGTSTP 信号

__TASK_TRACED (8)

  • 被 ptrace 跟踪
  • 调试器控制

EXIT_ZOMBIE (32)

  • 僵尸状态
  • 进程已退出,但父进程尚未 wait

EXIT_DEAD (16)

  • 进程最终状态
  • 即将被回收

6.2 状态转换图

6.2.1 完整状态机

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
                fork() / clone()


┌─────────────────────────────────────────┐
│ TASK_NEW │
│ (新创建,尚未运行) │
└──────────────┬──────────────────────────┘
│ wake_up_new_task()

┌─────────────────────────────────────────┐
│ TASK_RUNNING │
│ (就绪队列中,可被调度) │
└───────┬───────────────────────┬─────────┘
│ │
schedule() 选中 等待资源/事件
│ │
↓ ↓
┌──────────────┐ ┌────────────────────┐
│ 运行中 │ │ TASK_INTERRUPTIBLE │
│ │ │ TASK_UNINTERRUPTIBLE│
└──────┬───────┘ └───────────┬────────┘
│ │
time_slice / │
主动 yield │
│ │ 信号/事件到达
│ ↓
│ ┌──────────────┐
│ │ TASK_RUNNING │
│ └──────────────┘

可运行任务重新排队


┌──────────────┐
│ TASK_RUNNING │
│ (重新排队) │
└──────────────┘

特殊状态:
┌──────────────┐ SIGSTOP ┌─────────────┐
│ __TASK_ │ ←─────────────── │ 暂停调试 │
│ STOPPED │ │ │
└──────┬───────┘ └─────────────┘

│ SIGCONT

TASK_RUNNING

┌──────────────┐ SIGKILL ┌─────────────┐
│ __TASK_ │ ←─────────────── │ ptrace │
│ TRACED │ │ 调试 │
└──────────────┘ └─────────────┘

退出路径:
┌──────────────┐ do_exit() ┌─────────────┐
│ TASK_ │ ←─────────────── │ EXIT_ZOMBIE │
│ DEAD │ │ (僵尸进程) │
└──────────────┘ └──────┬──────┘

wait() 等待


┌─────────────┐
│ EXIT_DEAD │
│ (被回收) │
└─────────────┘

6.2.2 状态设置函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// include/linux/sched.h

/*
* 设置当前进程状态
* 使用内存屏障确保状态设置的有序性
*/
#define __set_current_state(state_value) \
do { \
current->task_state_change = _THIS_IP_; \
current->__state = (state_value); \
} while (0)

#define set_current_state(state_value) \
do { \
__set_current_state(state_value); \
smp_mb(); \
} while (0)

/*
* 检查是否应该睡眠
*/
static inline bool signal_pending_state(long state, struct task_struct *p)
{
if (!(state & TASK_INTERRUPTIBLE))
return false;
return signal_pending(p);
}

6.3 睡眠与唤醒

6.3.1 睡眠函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
// include/linux/sched.h

/*
* 睡眠直到条件满足
*/
#define wait_event(wq_head, condition) \
do { \
__label__ __label; \
DEFINE_WAIT(__wait); \
long __ret = 0; \
\
for (;;) { \
__set_current_state(TASK_UNINTERRUPTIBLE); \
if (condition) \
break; \
schedule(); \
} \
__set_current_state(TASK_RUNNING); \
__label__; \
} while (0)

/*
* 可中断睡眠
*/
#define wait_event_interruptible(wq_head, condition) \
({ \
long __ret = 0; \
DEFINE_WAIT(__wait); \
\
for (;;) { \
__set_current_state(TASK_INTERRUPTIBLE); \
if (condition) \
break; \
\
if (signal_pending(current)) { \
__ret = -ERESTARTSYS; \
break; \
} \
\
schedule(); \
} \
\
__set_current_state(TASK_RUNNING); \
__ret; \
})

/*
* 带超时的睡眠
*/
#define wait_event_timeout(wq_head, condition, timeout) \
({ \
long __ret = timeout; \
DEFINE_WAIT(__wait); \
\
for (;;) { \
__set_current_state(TASK_UNINTERRUPTIBLE); \
if (condition) \
break; \
\
if (!__ret) \
break; \
\
__ret = schedule_timeout(__ret); \
} \
\
__set_current_state(TASK_RUNNING); \
__ret; \
})

6.3.2 唤醒函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
// include/linux/wait.h

/*
* 唤醒等待队列上的所有任务
*/
static inline void wake_up(struct wait_queue_head *wq_head)
{
__wake_up(wq_head, TASK_NORMAL, 1, 0);
}

/*
* 唤醒可中断睡眠的任务
*/
static inline void wake_up_interruptible(struct wait_queue_head *wq_head)
{
__wake_up(wq_head, TASK_INTERRUPTIBLE, 1, 0);
}

/*
* 唤醒指定进程
*/
int wake_up_process(struct task_struct *p)
{
return try_to_wake_up(p);
}

/*
* 同步唤醒
*/
int wake_up_state(struct task_struct *p, unsigned int state);

6.3.3 try_to_wake_up()

位置: kernel/sched/core.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
/*
* 尝试唤醒进程
* 这是唤醒的核心函数
*/
int try_to_wake_up(struct task_struct *p)
{
struct rq_flags rf;
struct rq *rq;

// 获取进程所在运行队列
rq = __task_rq_lock(p, &rf);

// 检查是否应该唤醒
if (p->on_rq) {
// 已在就绪队列中
goto out;
}

// 检查 CPU 亲和性
if (!task_on_rq(p) &&
!cpumask_test_cpu(smp_processor_id(), p->cpus_ptr) &&
!p->migration_disabled) {
// 任务不在此 CPU 运行
goto out;
}

// 唤醒任务,加入就绪队列
ttwu_queue(p, p->nr_cpus_allowed <= 1 ? ENQUEUE_WAKEUP : 0, rq);

out:
__task_rq_unlock(rq, &rf);

return 1;
}

6.4 等待队列

6.4.1 数据结构

位置: include/linux/wait.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
/*
* 等待队列头
*/
struct wait_queue_head {
spinlock_t lock;
struct list_head head;
};

/*
* 等待队列项
*/
struct wait_queue_entry {
unsigned int flags;
void *private; // 通常是 task_struct
wait_queue_func_t func; // 唤醒回调函数
struct list_head entry;
};

/*
* 初始化等待队列头
*/
#define DECLARE_WAIT_QUEUE_HEAD(name) \
struct wait_queue_head name = __WAIT_QUEUE_HEAD_INITIALIZER(name)

static inline void init_waitqueue_head(struct wait_queue_head *wq_head)
{
spin_lock_init(&wq_head->lock);
INIT_LIST_HEAD(&wq_head->head);
}

6.4.2 等待队列操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
/*
* 添加到等待队列
*/
static inline void
add_wait_queue(struct wait_queue_head *wq_head, struct wait_queue_entry *wq_entry)
{
unsigned long flags;

spin_lock_irqsave(&wq_head->lock, flags);
__add_wait_queue(wq_head, wq_entry);
spin_unlock_irqrestore(&wq_head->lock, flags);
}

/*
* 从等待队列移除
*/
static inline void
remove_wait_queue(struct wait_queue_head *wq_head, struct wait_queue_entry *wq_entry)
{
unsigned long flags;

spin_lock_irqsave(&wq_head->lock, flags);
__remove_wait_queue(wq_head, wq_entry);
spin_unlock_irqrestore(&wq_head->lock, flags);
}

/*
* 准备等待
*/
static inline void
prepare_to_wait(struct wait_queue_head *wq_head, struct wait_queue_entry *wq_entry, int state)
{
unsigned long flags;

wq_entry->flags &= ~WQ_FLAG_EXCLUSIVE;
spin_lock_irqsave(&wq_head->lock, flags);
if (list_empty(&wq_entry->entry))
__add_wait_queue(wq_head, wq_entry);
set_current_state(state);
spin_unlock_irqrestore(&wq_head->lock, flags);
}

/*
* 完成等待
*/
static inline void
finish_wait(struct wait_queue_head *wq_head, struct wait_queue_entry *wq_entry)
{
unsigned long flags;

__set_current_state(TASK_RUNNING);
spin_lock_irqsave(&wq_head->lock, flags);
list_del_init(&wq_entry->entry);
spin_unlock_irqrestore(&wq_head->lock, flags);
}

6.4.3 使用示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// 等待队列和条件
static DECLARE_WAIT_QUEUE_HEAD(wq);
static int condition = 0;

/* 等待进程 */
static int waiting_thread(void *data)
{
// 等待条件满足
wait_event_interruptible(wq, condition != 0);

if (condition > 0)
return 0; // 成功
else
return -ERESTARTSYS; // 被信号中断
}

/* 唤醒进程 */
static void wake_condition(void)
{
condition = 1;
wake_up_interruptible(&wq);
}

6.5 特殊状态

6.5.1 TASK_STOPPED

进程收到 SIGSTOP、SIGTSTP、SIGTTIN 或 SIGTTOU 信号时进入此状态:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
static int do_signal_stop(int signr)
{
struct signal_struct *sig = current->signal;
int stop_count;

// 设置停止状态
current->jobctl |= JOBCTL_STOP_DEQUEUED;

// 设置任务状态
if (signr)
current->exit_signal = signr;

set_current_state(TASK_STOPPED);

// 调度出去
schedule();

return 0;
}

6.5.2 TASK_TRACED

进程被 ptrace 跟踪时的状态:

1
2
3
4
5
6
7
// 被 ptrace 时设置此状态
static void ptrace_notify(int exit_code)
{
// ... 设置 __TASK_TRACED
set_current_state(__TASK_TRACED);
schedule();
}

6.5.3 TASK_KILLABLE

组合状态,类似于不可中断睡眠但可被致命信号唤醒:

1
2
3
4
#define TASK_KILLABLE   (TASK_WAKEKILL | TASK_UNINTERRUPTIBLE)

// 使用示例
wait_event_killable(wq, condition);

6.6 状态检查工具

6.6.1 /proc/[pid]/status

1
2
3
$ cat /proc/1234/status
Name: sleep
State: S (sleeping)

状态码对应:

  • R (Running)
  • S (Sleeping)
  • D (Disk sleep /不可中断睡眠)
  • T (Stopped / 被跟踪)
  • Z (Zombie)

6.6.2 ps 命令

1
2
3
4
5
6
7
8
9
10
11
# 查看所有进程状态
ps aux

# 查看特定进程状态
ps -o pid,stat,comm -p 1234

# 状态码解析:
# Ss: 睡眠的主进程
# S+: 睡眠的前台进程组
# Sl: 睡眠的多线程进程
# R+: 运行中的前台进程

6.7 本章小结

本章介绍了 Linux 进程状态与转换机制:

  1. 进程状态定义:TASK_RUNNING、TASK_INTERRUPTIBLE、TASK_UNINTERRUPTIBLE 等
  2. 状态转换图:从创建到退出的完整状态机
  3. 睡眠机制:wait_event 系列宏的使用
  4. 唤醒机制:wake_up 和 try_to_wake_up
  5. 等待队列:等待队列头和队列项的操作
  6. 特殊状态:TASK_STOPPED、TASK_TRACED、TASK_KILLABLE
  7. 状态查看:/proc 和 ps 工具

下一章将介绍进程退出与等待机制。

  • Title: Linux内核分析之进程管理-06
  • Author: 韩乔落
  • Created at : 2026-01-14 19:20:11
  • Updated at : 2026-01-19 13:40:19
  • Link: https://jelasin.github.io/2026/01/14/Linux内核分析之进程管理-06/
  • License: This work is licensed under CC BY-NC-SA 4.0.
Comments