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

韩乔落

第2章 进程描述符 task_struct

基于 Linux 6.12.38 源码分析


2.1 task_struct 概览

2.1.1 定义位置

struct task_struct 是 Linux 内核中最重要的数据结构之一,定义在 include/linux/sched.h 中。它包含了进程的所有信息,是内核管理进程的核心数据结构。

task_struct

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// include/linux/sched.h:785
struct task_struct {
#ifdef CONFIG_THREAD_INFO_IN_TASK
/*
* For reasons of header soup (see current_thread_info()), this
* must be the first element of task_struct.
*/
struct thread_info thread_info;
#endif
unsigned int __state;

/* saved state for "spinlock sleepers" */
unsigned int saved_state;

// ... 更多字段
};

2.1.2 内存布局

大小与分配:

  • 64位系统:约 8KB(包含内核栈)
  • 32位系统:约 4KB
  • 通过 slab 分配器管理:task_struct_cachep

内存布局:

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
┌─────────────────────────────────────────────────────────────┐
│ 内核栈 + task_struct │
│ (THREAD_SIZE) │
├─────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ 内核栈空间 │ │
│ │ (THREAD_SIZE - sizeof(task_struct)) │ │
│ │ │ │
│ │ ↑ │ │
│ │ 栈增长 │ │
│ └──────────────────────────────────────────────────────┘ │
│ │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ struct task_struct │ │
│ │ │ │
│ │ - thread_info (低地址) │ │
│ │ - __state │ │
│ │ - stack │ │
│ │ - usage │ │
│ │ - flags │ │
│ │ - ptrace │ │
│ │ - ... (更多字段) │ │
│ └──────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘

current 指向这里

THREAD_SIZE 配置:

架构 THREAD_SIZE 配置选项
x86_64 16KB (4页) 或 8KB (2页) CONFIG_4KSTACKS
ARM64 16KB (4页) -
RISC-V 16KB (4页) -

2.1.3 获取当前进程

current 宏的实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// arch/x86/include/asm/current.h
#define current get_current()

static __always_inline struct task_struct *get_current(void)
{
return this_cpu_read_stable(current_task);
}

// ARM64 实现 (arch/arm64/include/asm/current.h)
static __always_inline struct task_struct *get_current(void)
{
return (struct task_struct *)
(read_sysreg(sp_el0) & ~THREAD_MASK);
}

每个 CPU 的 current_task 变量指向当前正在运行的进程的 task_struct。


2.2 进程状态

2.2.1 状态定义

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

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
/* Task state bitmask. NOTE! These bits are also
* encoded in fs/proc/array.c: get_task_state().
*
* We have two separate sets of flags: task->__state
* is about runnability, while task->exit_state are
* about the task exiting. Confusing, but this way
* modifying one set can't modify the other one by
* mistake.
*/

/* 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_FREEZABLE_UNSAFE (0x00004000 * IS_ENABLED(CONFIG_LOCKDEP))
#define TASK_FROZEN 0x00008000
#define TASK_STATE_MAX 0x00010000

2.2.2 状态详解

运行状态 (TASK_RUNNING)

1
2
3
4
5
6
// 实际上表示两种状态:
// 1. 正在 CPU 上执行
// 2. 在就绪队列中等待执行

#define task_is_running(task) \
(READ_ONCE((task)->__state) == TASK_RUNNING)

可中断睡眠 (TASK_INTERRUPTIBLE)

  • 可以被信号唤醒
  • 等待的事件到达时唤醒
  • 常用于可中断的 I/O 操作

不可中断睡眠 (TASK_UNINTERRUPTIBLE)

  • 不能被信号唤醒
  • 只能等待的事件到达时唤醒
  • 用于不可中断的 I/O 操作

停止状态 (__TASK_STOPPED)

1
2
3
4
5
// 进程被 SIGSTOP/SIGTSTP 暂停
#define TASK_STOPPED (TASK_WAKEKILL | __TASK_STOPPED)

#define task_is_stopped(task) \
((READ_ONCE(task->jobctl) & JOBCTL_STOPPED) != 0)

跟踪状态 (__TASK_TRACED)

  • 被 ptrace 跟踪的进程
  • 调试器控制进程执行

僵尸状态 (EXIT_ZOMBIE)

  • 进程已退出,但父进程尚未 wait()
  • 保留退出状态信息

死亡状态 (EXIT_DEAD/TASK_DEAD)

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

2.2.3 组合状态

1
2
3
4
5
6
7
8
9
/* Convenience macros for the sake of set_current_state: */
#define TASK_KILLABLE (TASK_WAKEKILL | TASK_UNINTERRUPTIBLE)
#define TASK_STOPPED (TASK_WAKEKILL | __TASK_STOPPED)
#define TASK_TRACED __TASK_TRACED

#define TASK_IDLE (TASK_UNINTERRUPTIBLE | TASK_NOLOAD)

/* Convenience macros for the sake of wake_up(): */
#define TASK_NORMAL (TASK_INTERRUPTIBLE | TASK_UNINTERRUPTIBLE)

TASK_KILLABLE - 可杀死睡眠

  • 类似 TASK_UNINTERRUPTIBLE
  • 但可以被致命信号唤醒

TASK_IDLE - 空闲睡眠

  • 不计入系统负载
  • 用于内核线程的空闲等待

2.2.4 状态检查函数

1
2
3
4
5
6
7
8
9
10
11
12
// include/linux/sched.h:144
static inline bool is_special_task_state(long state)
{
return (state & (__TASK_STOPPED | __TASK_TRACED | TASK_PARKED |
TASK_DEAD | TASK_FROZEN));
}

// 检查任务是否在运行
static inline int task_is_running(struct task_struct *p)
{
return READ_ONCE(p->__state) == TASK_RUNNING;
}

2.3 进程标志

2.3.1 标志定义

位置: include/linux/sched.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
/*
* Per process flags
*/
#define PF_EXITING 0x00000004 /* 正在退出 */
#define PF_EXITPIDONE 0x00000008 /* PID 已释放 */
#define PF_VCPU 0x00000010 /* 作为 vCPU 运行 */
#define PF_WQ_WORKER 0x00000020 /* workqueue worker */
#define PF_FORKNOEXEC 0x00000040 /* fork 但未 exec */
#define PF_MCE_PROCESS 0x00000080 /* MCE 正在处理 */
#define PF_SUPERPRIV 0x00000100 /* 需要 superuser 权限 */
#define PF_DUMPCORE 0x00000200 /* 正在 dump core */
#define PF_SIGNALED 0x00000400 /* 被信号杀死 */
#define PF_MEMALLOC 0x00000800 /* 内存分配上下文 */
#define PF_NPROC_EXCEEDED 0x00001000 /* 超过进程数限制 */
#define PF_USED_MATH 0x00002000 /* 使用 FPU */
#define PF_USED_ASYNC 0x00004000 /* 使用异步 */
#define PF_NOFREEZE 0x00008000 /* 不被冻结 */
#define PF_FROZEN 0x00010000 /* 已被冻结 */
#define PF_KSWAPD 0x00020000 /* kswapd 进程 */
#define PF_MEMALLOC_NOIO 0x00080000 /* 内存分配时不做 IO */
#define PF_MEMALLOC_NOFS 0x00100000 /* 内存分配时不做 FS 操作 */
#define PF_MEMALLOC_PIN 0x00200000 /* pinned memory allocation */
#define PF_KTHREAD 0x00200000 /* 内核线程 */
#define PF_RANDOMIZE 0x00400000 /* 地址随机化 */
#define PF_SWAPWRITE 0x00800000 /* 正在写入 swap */
#define PF_UMH 0x02000000 /* user mode helper */
#define PF_SETDPERPID 0x04000000 /* 每进程设置 */

2.3.2 标志检查

1
2
3
4
5
6
7
8
9
10
11
// 检查是否为内核线程
static inline bool is_kthread_kernel_thread(struct task_struct *task)
{
return task->flags & (PF_KTHREAD | PF_IO_WORKER);
}

// 检查进程是否正在退出
static inline int fatal_signal_pending(struct task_struct *p)
{
return signal_pending(p) && !(p->signal->flags & SIGNAL_GROUP_EXIT);
}

2.4 调度相关字段

2.4.1 优先级

1
2
3
4
5
6
7
8
// include/linux/sched.h:833
struct task_struct {
int prio; // 动态优先级
int static_prio; // 静态优先级
int normal_prio; // 标准优先级(基于策略)
unsigned int rt_priority; // 实时优先级
// ...
};

优先级计算:

1
2
3
4
5
6
7
8
9
10
11
12
13
// kernel/sched/core.c
int effective_prio(struct task_struct *p)
{
p->normal_prio = normal_prio(p);
/*
* If we are RT tasks or we were boosted to RT priority,
* keep the priority unchanged. Otherwise, update priority
* to the normal priority:
*/
if (!rt_prio(p->prio))
return p->normal_prio;
return p->prio;
}

优先级范围:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
实时优先级 (0 - 99)

│ 0 最高实时优先级
│ ...
│ 99 最低实时优先级

├─────────────────────────────────────

│ 100 普通进程最高优先级 (nice -20)
│ ...
│ 120 普通进程默认优先级 (nice 0)
│ ...
│ 139 普通进程最低优先级 (nice +19)

└─────────────────────────────────────

2.4.2 调度实体

1
2
3
4
5
6
7
8
// include/linux/sched.h:838
struct task_struct {
struct sched_entity se; // CFS 调度实体
struct sched_rt_entity rt; // 实时调度实体
struct sched_dl_entity dl; // Deadline 调度实体
const struct sched_class *sched_class; // 调度类
// ...
};

调度类定义:

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
69
70
71
72
73
74
// kernel/sched/sched.h:2360
struct sched_class {
#ifdef CONFIG_UCLAMP_TASK
int uclamp_enabled;
#endif

void (*enqueue_task) (struct rq *rq, struct task_struct *p, int flags);
bool (*dequeue_task) (struct rq *rq, struct task_struct *p, int flags);
void (*yield_task) (struct rq *rq);
bool (*yield_to_task)(struct rq *rq, struct task_struct *p);

void (*wakeup_preempt)(struct rq *rq, struct task_struct *p, int flags);

int (*balance)(struct rq *rq, struct task_struct *prev, struct rq_flags *rf);
struct task_struct *(*pick_task)(struct rq *rq);
/*
* Optional! When implemented pick_next_task() should be equivalent to:
*
* next = pick_task();
* if (next) {
* put_prev_task(prev);
* set_next_task_first(next);
* }
*/
struct task_struct *(*pick_next_task)(struct rq *rq, struct task_struct *prev);

void (*put_prev_task)(struct rq *rq, struct task_struct *p, struct task_struct *next);
void (*set_next_task)(struct rq *rq, struct task_struct *p, bool first);

#ifdef CONFIG_SMP
int (*select_task_rq)(struct task_struct *p, int task_cpu, int flags);

void (*migrate_task_rq)(struct task_struct *p, int new_cpu);

void (*task_woken)(struct rq *this_rq, struct task_struct *task);

void (*set_cpus_allowed)(struct task_struct *p, struct affinity_context *ctx);

void (*rq_online)(struct rq *rq);
void (*rq_offline)(struct rq *rq);

struct rq *(*find_lock_rq)(struct task_struct *p, struct rq *rq);
#endif

void (*task_tick)(struct rq *rq, struct task_struct *p, int queued);
void (*task_fork)(struct task_struct *p);
void (*task_dead)(struct task_struct *p);

/*
* The switched_from() call is allowed to drop rq->lock, therefore we
* cannot assume the switched_from/switched_to pair is serialized by
* rq->lock. They are however serialized by p->pi_lock.
*/
void (*switching_to) (struct rq *this_rq, struct task_struct *task);
void (*switched_from)(struct rq *this_rq, struct task_struct *task);
void (*switched_to) (struct rq *this_rq, struct task_struct *task);
void (*reweight_task)(struct rq *this_rq, struct task_struct *task,
const struct load_weight *lw);
void (*prio_changed) (struct rq *this_rq, struct task_struct *task,
int oldprio);

unsigned int (*get_rr_interval)(struct rq *rq,
struct task_struct *task);

void (*update_curr)(struct rq *rq);

#ifdef CONFIG_FAIR_GROUP_SCHED
void (*task_change_group)(struct task_struct *p);
#endif

#ifdef CONFIG_SCHED_CORE
int (*task_is_throttled)(struct task_struct *p, int cpu);
#endif
};

调度类优先级顺序:

1
2
3
4
5
6
7
8
// kernel/sched/core.c
const struct sched_class stop_sched_class;
const struct sched_class dl_sched_class;
const struct sched_class rt_sched_class;
const struct sched_class fair_sched_class;
const struct sched_class idle_sched_class;

// 链表顺序定义了优先级:stop > dl > rt > fair > idle

2.4.3 CPU 亲和性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// include/linux/sched.h:882
struct task_struct {
unsigned int policy;
unsigned long max_allowed_capacity;
int nr_cpus_allowed;
const cpumask_t *cpus_ptr;
cpumask_t *user_cpus_ptr;
cpumask_t cpus_mask;
void *migration_pending;
#ifdef CONFIG_SMP
unsigned short migration_disabled;
#endif
unsigned short migration_flags;
// ...
};

2.5 进程标识符

2.5.1 PID 字段

1
2
3
4
5
6
7
8
9
// include/linux/sched.h:1026
struct task_struct {
pid_t pid; // 进程 ID (线程 ID)
pid_t tgid; // 线程组 ID (主线程 PID)
struct pid *thread_pid; // PID 结构
struct hlist_node pid_links[PIDTYPE_MAX];
struct list_head thread_node;
// ...
};

2.5.2 PID 类型

1
2
3
4
5
6
7
8
// include/linux/pid.h
enum pid_type {
PIDTYPE_PID, // 进程 ID
PIDTYPE_TGID, // 线程组 ID
PIDTYPE_PGID, // 进程组 ID
PIDTYPE_SID, // 会话 ID
PIDTYPE_MAX,
};

2.6 进程关系

2.6.1 家族关系字段

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// include/linux/sched.h:1039
struct task_struct {
/*
* Pointers to the (original) parent process, youngest child, younger sibling,
* older sibling, respectively. (p->father can be replaced with
* p->real_parent->pid)
*/

/* Real parent process: */
struct task_struct __rcu *real_parent;

/* Recipient of SIGCHLD, wait4() reports: */
struct task_struct __rcu *parent;

/*
* Children/sibling form the list of natural children:
*/
struct list_head children;
struct list_head sibling;
struct task_struct *group_leader;
// ...
};

2.6.2 进程树结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
init (PID 1)

├─ systemd (PID 1000)
│ │ real_parent = init
│ │ parent = init
│ │ children = [NetworkManager, sshd, cron]
│ │ group_leader = systemd
│ │
│ ├─ NetworkManager (PID 1001)
│ │ real_parent = systemd
│ │ parent = systemd
│ │
│ ├─ sshd (PID 1002)
│ │
│ └─ cron (PID 1003)

└─ containerd (PID 500)

└─ dockerd (PID 501)

2.6.3 线程组关系

1
2
3
4
5
6
struct task_struct {
struct task_struct *group_leader; // 线程组首领
struct list_head thread_group; // 线程组成员
struct list_head thread_node; // PID 哈希节点
// ...
};

多线程进程结构:

1
2
3
4
5
进程 (TGID = 1000)

├─ thread1 (PID = 1000, group_leader = thread1)
├─ thread2 (PID = 1001, group_leader = thread1)
└─ thread3 (PID = 1002, group_leader = thread1)

2.7 内存管理

2.7.1 内存描述符

1
2
3
4
5
6
7
// include/linux/sched.h:928
struct task_struct {
struct mm_struct *mm; // 进程地址空间
struct mm_struct *active_mm; // 活跃地址空间 (内核线程)
struct address_space *faults_disabled_mapping;
// ...
};

mm vs active_mm:

1
2
3
4
5
6
7
8
9
10
// 内核线程:mm = NULL,active_mm = 借用的 mm
// 用户进程:mm = active_mm = 自己的 mm

static inline void mmdrop(struct mm_struct *mm)
{
if (mm->owner == NULL) // 内核线程借用的 mm
mmdrop_lazy_tlb(mm);
else
__mmdrop(mm);
}

2.7.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
用户空间 (TASK_SIZE)

│ ┌─────────────────────────────────────┐
│ │ 参数和环境变量 │
│ ├─────────────────────────────────────┤
│ │ 栈 (向下增长) │
│ ├─────────────────────────────────────┤
│ │ (空洞) │
│ ├─────────────────────────────────────┤
│ │ 堆 (向上增长) │
│ ├─────────────────────────────────────┤
│ │ BSS 段 │
│ ├─────────────────────────────────────┤
│ │ 数据段 │
│ ├─────────────────────────────────────┤
│ │ 代码段 │
│ └─────────────────────────────────────┘

├─────────────────────────────────────

内核空间

│ ┌─────────────────────────────────────┐
│ │ 直接映射区 │
│ ├─────────────────────────────────────┤
│ │ vmalloc/ioremap 区 │
│ ├─────────────────────────────────────┤
│ │ 永久映射区 │
│ ├─────────────────────────────────────┤
│ │ 固定映射区 │
│ └─────────────────────────────────────┘

2.8 文件系统

2.8.1 文件系统相关字段

1
2
3
4
5
6
7
8
9
// include/linux/sched.h:1148
struct task_struct {
/* Filesystem information: */
struct fs_struct *fs;

/* Open file information: */
struct files_struct *files;
// ...
};

fs_struct: 文件系统信息(根目录、当前工作目录)

1
2
3
4
5
6
7
8
9
// include/linux/fs_struct.h
struct fs_struct {
int users;
spinlock_t lock;
seqcount_spinlock_t seq;
int umask;
int in_exec;
struct path root, pwd;
};

files_struct: 打开的文件描述符表

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// include/linux/fdtable.h
struct files_struct {
/*
* read mostly part
*/
atomic_t count;
bool resize_in_progress;
struct fdtable __rcu *fdt;
struct fdtable fdtab;
/*
* written part on a separate cache line in SMP
*/
spinlock_t file_lock ____cacheline_aligned_in_smp;
unsigned int next_fd;
unsigned long close_on_exec_init[1];
unsigned long open_fds_init[1];
unsigned long full_fds_bits_init[1];
struct file __rcu * fd_array[NR_OPEN_DEFAULT];
};

2.9 信号处理

2.9.1 信号相关字段

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// include/linux/sched.h:1161
struct task_struct {
/* Signal handlers: */
struct signal_struct *signal;
struct sighand_struct __rcu *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;
// ...
};

2.9.2 信号标志

1
2
3
4
5
6
7
8
9
10
11
// include/linux/sched.h:736
/* Used in tsk->jobctl: */
#define JOBCTL_STOP_SIGMASK 0xffff /* signr of the last group stop */
#define JOBCTL_STOPPED (1 << 16) /* ->signal->group_stop_count > 0 */
#define JOBCTL_STOP_CONSUME (1 << 17) /* group stop consuming */
#define JOBCTL_TRAP_STOP (1 << 18) /* trap for STOP */
#define JOBCTL_TRAP_NOTIFY (1 << 19) // trap for NOTIFY
#define JOBCTL_TRAPPING (1 << 20) // ptracer is waiting for SIGTRAP
#define JOBCTL_LISTENING (1 << 21) // listening for events
#define JOBCTL_TRAP_FREEZE (1 << 22) // trap for cgroup freeze
#define JOBCTL_TASK_WORK (1 << 23) // task_work_add() pending

2.10 统计信息

2.10.1 CPU 时间统计

1
2
3
4
5
6
7
8
9
10
11
12
// include/linux/sched.h:1077
struct task_struct {
u64 utime; // 用户态时间
u64 stime; // 内核态时间
#ifdef CONFIG_ARCH_HAS_SCALED_CPUTIME
u64 utimescaled; // 缩放的用户时间
u64 stimescaled; // 缩放的内核时间
#endif
u64 gtime; // Guest 时间
struct prev_cputime prev_cputime;
// ...
};

2.10.2 缺页统计

1
2
3
4
5
6
struct task_struct {
/* MM fault and swap info: */
unsigned long min_flt; // 次要缺页
unsigned long maj_flt; // 主要缺页
// ...
};

2.10.3 上下文切换统计

1
2
3
4
5
6
struct task_struct {
/* Context switch counts: */
unsigned long nvcsw; // 自愿上下文切换
unsigned long nivcsw; // 非自愿上下文切换
// ...
};

2.10.4 时间信息

1
2
3
4
5
6
7
8
struct task_struct {
/* Monotonic time in nsecs: */
u64 start_time;

/* Boot based time in nsecs: */
u64 start_boottime;
// ...
};

2.11 证书与安全

2.11.1 证书字段

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// include/linux/sched.h:1113
struct task_struct {
/* Process credentials: */

/* Tracer's credentials at attach: */
const struct cred __rcu *ptracer_cred;

/* Objective and real subjective task credentials (COW): */
const struct cred __rcu *real_cred;

/* Effective (overridable) subjective task credentials (COW): */
const struct cred __rcu *cred;
// ...
};

2.11.2 安全模块

1
2
3
4
5
struct task_struct {
struct seccomp seccomp;
struct syscall_user_dispatch syscall_dispatch;
// ...
};

2.12 进程名

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// include/linux/sched.h:1135
struct task_struct {
/*
* executable name, excluding path.
*
* - normally initialized setup_new_exec()
* - access it with [gs]et_task_comm()
* - lock it with task_lock()
*/
char comm[TASK_COMM_LEN];
// ...
};

// TASK_COMM_LEN = 16

获取和设置进程名:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// include/linux/sched.h:483
static inline void get_task_comm(char *buf, struct task_struct *tsk)
{
task_lock(tsk);
strscpy_pad(buf, tsk->comm, TASK_COMM_LEN);
task_unlock(tsk);
}

static inline void set_task_comm(struct task_struct *tsk, const char *buf)
{
task_lock(tsk);
strscpy_pad(tsk->comm, buf, TASK_COMM_LEN);
task_unlock(tsk);
}

2.13 锁与同步

2.13.1 分配锁

1
2
3
4
5
6
7
8
9
// include/linux/sched.h:1190
struct task_struct {
/* Protection against (de-)allocation: mm, files, fs, tty, keyrings: */
spinlock_t alloc_lock;

/* Protection of the PI data structures: */
raw_spinlock_t pi_lock;
// ...
};

2.13.2 优先级继承

1
2
3
4
5
6
7
8
#ifdef CONFIG_RT_MUTEXES
/* PI waiters blocked on a rt_mutex held by this task: */
struct rb_root_cached pi_waiters;
/* Updated under owner's pi_lock and rq lock */
struct task_struct *pi_top_task;
/* Deadlock detection and priority inheritance handling: */
struct rt_mutex_waiter *pi_blocked_on;
#endif

2.14 本章小结

本章详细介绍了 Linux 内核中进程描述符 task_struct 的结构:

  1. 基本结构:约 8KB,包含内核栈,通过 slab 分配器管理
  2. 进程状态__state 字段包含运行、睡眠、停止、僵尸等状态
  3. 进程标志flags 字段包含各种进程属性
  4. 调度信息:优先级、调度实体、调度类等
  5. 进程标识:PID、TGID、命名空间相关
  6. 进程关系:父进程、子进程、线程组
  7. 资源管理:内存、文件、信号等
  8. 统计信息:CPU 时间、缺页、上下文切换等

task_struct 是 Linux 进程管理的核心数据结构,理解其结构对于深入理解内核进程管理至关重要。

下一章将介绍进程标识符与命名空间的管理。

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