Linux 6.12 进程管理概览
基于 Linux 6.12.38 源码,涵盖进程与线程管理的核心机制
1. 概述
1.1 进程与线程的概念
进程 (Process):
- 程序执行的实例
- 拥有独立的地址空间
- 资源分配的基本单位
线程 (Thread):
- 进程内的执行单元
- 共享进程地址空间
- CPU 调度的基本单位
Linux 中的实现:
1.2 进程管理子系统架构
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| ┌─────────────────────────────────────────────────────────────────┐ │ 进程管理子系统 │ ├─────────────────────────────────────────────────────────────────┤ │ │ │ ┌──────────────┐ ┌──────────────┐ ┌─────────────────┐ │ │ │ 进程描述符 │ │ 进程调度器 │ │ 进程创建/退出 │ │ │ │ task_struct │ │ Scheduler │ │ fork/exec/exit │ │ │ └──────────────┘ └──────────────┘ └─────────────────┘ │ │ │ │ ┌──────────────┐ ┌──────────────┐ ┌─────────────────┐ │ │ │ PID 管理 │ │ 等待队列 │ │ 信号处理 │ │ │ │ PID Namespace│ │ wait_queue │ │ signal_frame │ │ │ └──────────────┘ └──────────────┘ └─────────────────┘ │ │ │ └─────────────────────────────────────────────────────────────────┘
|
1.3 关键源码位置
| 功能 |
目录 |
主要文件 |
| 进程核心 |
kernel/ |
fork.c, exit.c, exec.c |
| 调度器 |
kernel/sched/ |
core.c, fair.c, rt.c, deadline.c |
| PID 管理 |
kernel/ |
pid.c, pid_namespace.c |
| 信号处理 |
kernel/ |
signal.c |
| 内核线程 |
kernel/ |
kthread.c |
| 进程统计 |
kernel/ |
acct.c, delayacct.c |
| 头文件 |
include/linux/ |
sched.h, sched/*.h |
| 系统调用 |
kernel/ |
sys.c, sys_ni.c |
| 体系相关 |
arch/*/kernel/ |
process.c, signal.c, entry*.S |
1.4 相关数据结构概览
1 2 3 4 5 6 7 8 9 10 11
| struct task_struct; struct pid; struct pid_namespace; struct signal_struct; struct sighand_struct; struct rq; struct sched_entity; struct sched_rt_entity; struct sched_dl_entity; struct wait_queue_head; struct task_group;
|
2. 进程描述符 task_struct
2.1 task_struct 概览
位置: include/linux/sched.h
大小: 约 8KB (64位系统),包含内核栈
分配方式: 通过 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 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
| struct task_struct { unsigned int __state; int exit_state; unsigned int flags;
void *stack; unsigned long stack_canary;
struct sched_entity se; struct sched_rt_entity rt; struct sched_dl_entity dl; int prio; int static_prio; int normal_prio; unsigned int rt_priority;
pid_t pid; pid_t tgid; struct pid *thread_pid; struct task_struct *group_leader;
struct task_struct __rcu *real_parent; struct task_struct __rcu *parent; struct list_head children; struct list_head sibling;
struct mm_struct *mm; struct mm_struct *active_mm;
struct fs_struct *fs; struct files_struct *files; struct nsproxy *nsproxy;
struct signal_struct *signal; struct sighand_struct *sighand; sigset_t blocked; sigset_t real_blocked;
const struct cred __rcu *real_cred; const struct cred __rcu *cred; char comm[TASK_COMM_LEN];
u64 utime; u64 stime; u64 gtime; unsigned long min_flt; unsigned long maj_flt;
};
|
2.2 进程状态
状态定义: 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
| #define TASK_RUNNING 0x00000000 #define TASK_INTERRUPTIBLE 0x00000001 #define TASK_UNINTERRUPTIBLE 0x00000002 #define __TASK_STOPPED 0x00000004 #define __TASK_TRACED 0x00000008
#define EXIT_DEAD 0x00000010 #define EXIT_ZOMBIE 0x00000020
#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
|
状态转换图:
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
| ┌─────────────┐ │ TASK_NEW │ └──────┬──────┘ │ fork() │ ↓ ┌─────────────────────────────────────────┐ │ TASK_RUNNING │ │ (就绪态或运行态 - 可被调度) │ └───────┬───────────────────────┬─────────┘ │ │ 调度器选择 等待事件 │ │ ↓ ↓ ┌──────────────┐ ┌────────────────────┐ │ 正在运行 │ │ TASK_INTERRUPTIBLE │ │ │ │ TASK_UNINTERRUPTIBLE│ └──────┬───────┘ └───────────┬────────┘ │ │ │ │ 事件到达 │ │ 或信号 │ ↓ │ ┌──────────────┐ │ │ TASK_RUNNING │ │ └──────────────┘ │ time slice / 主动放弃 │ ↓ ┌──────────────┐ │ TASK_RUNNING │ │ (重新排队) │ └──────────────┘
特殊状态转换: ┌──────────────┐ │ __TASK_STOPPED│ ←─ SIGSTOP └──────────────┘ ┌──────────────┐ │ __TASK_TRACED │ ←─ ptrace └──────────────┘
退出状态: ┌──────────────┐ do_exit() ┌─────────────┐ │ TASK_DEAD │ ───────────────→ │ EXIT_ZOMBIE │ └──────────────┘ └──────┬──────┘ │ wait() │ ↓ ┌─────────────┐ │ EXIT_DEAD │ │ (被回收) │ └─────────────┘
|
2.3 进程标志
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
| #define PF_EXITING 0x00000004 #define PF_EXITPIDONE 0x00000008 #define PF_VCPU 0x00000010 #define PF_WQ_WORKER 0x00000020 #define PF_FORKNOEXEC 0x00000040 #define PF_MCE_PROCESS 0x00000080 #define PF_SUPERPRIV 0x00000100 #define PF_DUMPCORE 0x00000200 #define PF_SIGNALED 0x00000400 #define PF_MEMALLOC 0x00000800 #define PF_NPROC_EXCEEDED 0x00001000 #define PF_USED_MATH 0x00002000 #define PF_USED_ASYNC 0x00004000 #define PF_NOFREEZE 0x00008000 #define PF_FROZEN 0x00010000 #define PF_KSWAPD 0x00020000 #define PF_MEMALLOC_NOIO 0x00080000 #define PF_MEMALLOC_NOFS 0x00100000 #define PF_MEMALLOC_PIN 0x00200000 #define PF_MEMALLOC_PIN 0x00200000 #define PF_KTHREAD 0x00200000 #define PF_RANDOMIZE 0x00400000 #define PF_SWAPWRITE 0x00800000 #define PF_UMH 0x02000000 #define PF_SETDPERPID 0x04000000
|
2.4 内核栈与 thread_info
内核栈布局:
1 2 3 4 5 6 7 8 9 10 11 12 13
| ┌────────────────────────────────────────────┐ │ struct thread_info │ │ (ARM64/x86_64 合并到 task_struct) │ ├────────────────────────────────────────────┤ │ │ │ 内核栈空间 │ │ (THREAD_SIZE - 16KB/8KB) │ │ │ │ │ │ ↑ │ │ 栈增长方向 │ └────────────────────────────────────────────┘ struct task_struct *task
|
THREAD_SIZE:
- x86_64: 16KB (4页) 或 8KB (2页)
- ARM64: 16KB (4页)
2.5 current 宏
获取当前进程:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| #define current get_current()
static __always_inline struct task_struct *get_current(void) { return this_cpu_read_stable(current_task); }
static __always_inline struct task_struct *get_current(void) { return (struct task_struct *) (read_sysreg(sp_el0) & ~THREAD_MASK); }
|
3. 进程标识符与命名空间
3.1 进程 ID 类型
定义: include/linux/pid.h
1 2 3 4 5 6 7
| enum pid_type { PIDTYPE_PID, PIDTYPE_TGID, PIDTYPE_PGID, PIDTYPE_SID, PIDTYPE_MAX, };
|
3.2 PID 管理数据结构
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
| struct pid { atomic_t count; unsigned int level; struct hlist_head tasks[PIDTYPE_MAX];
struct { int nr; struct hlist_node pid_chain; } numbers[1]; };
struct pid_namespace { struct kref kref; struct user_namespace *user_ns; struct pid_namespace *parent;
unsigned int level; unsigned int nr_hashed; struct pid *nr_hashed[PID_MAX_HASHED];
struct idr idr;
int last_pid; unsigned int nr_allocated; struct kmem_cache *pid_cachep;
};
|
3.3 PID 命名空间层级
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
| ┌────────────────────────────────────────────────────────────────┐ │ PID Namespace 层级 │ ├────────────────────────────────────────────────────────────────┤ │ │ │ Level 0: 初始命名空间 (init_ns) │ │ ┌──────────────────────────────────────────────────────┐ │ │ │ PID 1: systemd/init │ │ │ │ ├─ 子容器 PID 1 │ │ │ │ └─ 子容器 PID 2 │ │ │ └──────────────────────────────────────────────────────┘ │ │ │ │ Level 1: 容器 A 命名空间 │ │ ┌──────────────────────────────────────────────────────┐ │ │ │ PID 1: containerA_init │ │ │ │ ├─ 子容器 PID 1 │ │ │ │ └─ 子进程 PID 2 │ │ │ └──────────────────────────────────────────────────────┘ │ │ │ │ Level 2: 嵌套容器 A-1 │ │ ┌──────────────────────────────────────────────────────┐ │ │ │ PID 1: containerA1_init │ │ │ │ └─ 子进程 PID 2 │ │ │ └──────────────────────────────────────────────────────┘ │ │ │ └────────────────────────────────────────────────────────────────┘
视图映射: ┌─────────────┬───────────────┬───────────────┬─────────────┐ │ 全局视角 │ Level 0 视角 │ Level 1 视角 │ Level 2 视角│ ├─────────────┼───────────────┼───────────────┼─────────────┤ │ PID 1 │ PID 1 │ - │ - │ │ PID 100 │ PID 100 │ PID 1 │ - │ │ PID 200 │ PID 200 │ PID 2 │ PID 1 │ └─────────────┴───────────────┴───────────────┴─────────────┘
|
3.4 PID 分配 API
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| struct pid *alloc_pid(struct pid_namespace *ns);
struct pid *find_vpid(int nr); struct pid *find_pid_ns(int nr, struct pid_namespace *ns);
pid_t pid_nr(struct pid *pid); pid_t pid_nr_ns(struct pid *pid, struct pid_namespace *ns); pid_t pid_vnr(struct pid *pid);
void get_pid(struct pid *pid); void put_pid(struct pid *pid);
|
3.5 进程组与会话
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
| struct task_struct { pid_t __pgrp; struct pid *thread_pid; };
struct task_struct { struct pid *session; };
|
4. 进程创建
4.1 fork/vfork/clone 系统调用
系统调用入口: kernel/fork.c
1 2 3 4 5 6 7 8 9
| SYSCALL_DEFINE0(fork); SYSCALL_DEFINE0(vfork); SYSCALL_DEFINE5(clone, unsigned long, clone_flags, unsigned long, newsp, int __user *, parent_tidptr, unsigned long, tls, int __user *, child_tidptr);
SYSCALL_DEFINE2(clone3, struct clone_args __user *, uargs, size_t, size);
|
4.2 clone_flags 标志
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
| #define CSIGNAL 0x000000ff #define CLONE_VM 0x00000100 #define CLONE_FS 0x00000200 #define CLONE_FILES 0x00000400 #define CLONE_SIGHAND 0x00000800 #define CLONE_PIDFD 0x00001000 #define CLONE_PTRACE 0x00002000 #define CLONE_VFORK 0x00004000 #define CLONE_PARENT 0x00008000 #define CLONE_THREAD 0x00010000 #define CLONE_NEWNS 0x00020000 #define CLONE_SYSVSEM 0x00040000 #define CLONE_SETTLS 0x00080000 #define CLONE_PARENT_SETTID 0x00100000 #define CLONE_CHILD_CLEARTID 0x00200000 #define CLONE_DETACHED 0x00400000 #define CLONE_UNTRACED 0x00800000 #define CLONE_CHILD_SETTID 0x01000000 #define CLONE_NEWCGROUP 0x02000000 #define CLONE_NEWUTS 0x04000000 #define CLONE_NEWIPC 0x08000000 #define CLONE_NEWUSER 0x10000000 #define CLONE_NEWPID 0x20000000 #define CLONE_NEWNET 0x40000000 #define CLONE_IO 0x80000000
|
4.3 fork() 实现流程
核心函数: kernel/fork.c:do_fork()
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
| long do_fork(unsigned long clone_flags, unsigned long stack_start, unsigned long stack_size, int __user *parent_tidptr, int __user *child_tidptr) { struct task_struct *p; int trace = 0; long nr;
p = copy_process(clone_flags, stack_start, stack_size, child_tidptr, parent_tidptr, trace);
if (!IS_ERR(p)) { struct completion vfork; struct pid *pid;
trace_sched_process_fork(current, p);
pid = get_task_pid(p, PIDTYPE_PID); nr = pid_vnr(pid);
if (clone_flags & CLONE_PARENT_SETTID) put_user(nr, parent_tidptr);
if (clone_flags & CLONE_VFORK) { p->vfork_done = &vfork; init_completion(&vfork); get_task_struct(p); }
wake_up_new_task(p);
if (clone_flags & CLONE_VFORK) { if (!wait_for_vfork_done(p, &vfork)) ptrace_event(PTRACE_EVENT_VFORK_DONE, pid_vnr(pid)); }
put_pid(pid); } else { nr = PTR_ERR(p); }
return nr; }
|
4.4 copy_process() 流程
位置: kernel/fork.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 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 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113
| static struct task_struct *copy_process( unsigned long clone_flags, unsigned long stack_start, unsigned long stack_size, int __user *child_tidptr, int __user *parent_tidptr, unsigned long trace) { int retval; struct task_struct *p;
if ((clone_flags & (CLONE_NEWNS|CLONE_FS)) == (CLONE_NEWNS|CLONE_FS)) return ERR_PTR(-EINVAL);
retval = -EAGAIN; if (atomic_read(&p->user->processes) >= task_rlimit(p, RLIMIT_NPROC)) { if (!capable(CAP_SYS_ADMIN) && !capable(CAP_SYS_RESOURCE)) goto bad_fork_free; }
p = dup_task_struct(current); if (!p) goto bad_fork_free;
retval = copy_creds(p, clone_flags);
shm_init_task(p);
retval = copy_thread(clone_flags, stack_start, stack_size, p); if (retval) goto bad_fork_cleanup_io;
if (clone_flags & CLONE_THREAD) p->exit_signal = -1; else if (clone_flags & CLONE_PARENT_SETTID) p->exit_signal = SIGCHLD; else p->exit_signal = fork_exit_signal;
retval = copy_semundo(clone_flags, p); if (retval) goto bad_fork_cleanup_signal;
retval = copy_files(clone_flags, p); if (retval) goto bad_fork_cleanup_semundo;
retval = copy_fs(clone_flags, p); if (retval) goto bad_fork_cleanup_files;
retval = copy_sighand(clone_flags, p); if (retval) goto bad_fork_cleanup_fs;
retval = copy_signal(clone_flags, p); if (retval) goto bad_fork_cleanup_sighand;
retval = copy_mm(clone_flags, p); if (retval) goto bad_fork_cleanup_signal;
retval = copy_namespaces(clone_flags, p); if (retval) goto bad_fork_cleanup_mm;
retval = copy_io(clone_flags, p); if (retval) goto bad_fork_cleanup_namespaces;
retval = copy_thread(clone_flags, stack_start, stack_size, p); if (retval) goto bad_fork_cleanup_io;
retval = sched_fork(clone_flags, p); if (retval) goto bad_fork_cleanup_cleanup;
p->pid = pid_nr(pid); if (clone_flags & CLONE_THREAD) { p->exit_signal = -1; p->group_leader = current->group_leader; } else { p->group_leader = p; }
retval = alloc_pid(p->nsproxy->pid_ns_for_children, &pid); if (retval) goto bad_fork_cleanup_thread;
p->pid = pid_nr(pid);
return p;
}
|
4.5 写时复制 (Copy-on-Write)
实现原理:
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
| fork() 之前: ┌────────────────────────────────────────────────────────────┐ │ 父进程地址空间 │ │ ┌──────────────────────────────────────────────────────┐ │ │ │ 代码段 (只读) │ │ │ │ 数据段 (可写) ───→ 物理页 A │ │ │ │ 堆段 (可写) ───→ 物理页 B │ │ │ │ 栈段 (可写) ───→ 物理页 C │ │ │ └──────────────────────────────────────────────────────┘ │ └────────────────────────────────────────────────────────────┘
fork() 之后 (exec 之前): ┌───────────────────────────┐ ┌───────────────────────────┐ │ 父进程 │ │ 子进程 │ │ ┌───────────────────────┐ │ │ ┌───────────────────────┐ │ │ │ 代码段 (只读, 共享) │◄┼───┼──►│ 代码段 (只读, 共享) │ │ │ │ 数据段 ──────→ A │ │ │ │ 数据段 ──────→ A │ │ │ │ 堆段 ──────→ B │ │ │ │ 堆段 ──────→ B │ │ │ │ 栈段 ──────→ C │ │ │ │ 栈段 ──────→ C │ │ │ │ (页表: 只读) │ │ │ │ (页表: 只读) │ │ │ └───────────────────────┘ │ │ └───────────────────────┘ │ └───────────────────────────┘ └───────────────────────────┘
子进程写操作触发缺页: ┌───────────────────┐ ┌───────────────────┐ │ 父进程 │ │ 子进程 │ │ 数据段 ──→ A │ │ 数据段 ──→ A' │ │ 堆段 ──→ B │ │ 堆段 ──→ B' │ └───────────────────┘ └───────────────────┘
|
相关代码: mm/memory.c:copy_page_range(), do_wp_page()
4.6 vfork() vs fork() vs clone()
| 特性 |
fork() |
vfork() |
clone() |
| 地址空间 |
复制 (COW) |
共享 |
可选 |
| 页表 |
复制 |
不复制 |
可选 |
| 父进程阻塞 |
否 |
是 (子进程 exec/exit) |
可选 (CLONE_VFORK) |
| 用途 |
创建进程 |
创建后立即 exec |
灵活创建进程/线程 |
| 性能 |
较低 |
高 |
高 |
4.7 execve() 系统调用
位置: fs/exec.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
| static int do_execveat_common(int fd, struct filename *filename, struct user_arg_ptr argv, struct user_arg_ptr envp, int flags) { struct linux_binprm *bprm; int retval;
bprm = alloc_binprm();
retval = bprm_execve(bprm, fd, filename, flags);
retval = copy_string_kernel(bprm->filename, &bprm->exec);
retval = exec_binprm(bprm);
free_bprm(bprm);
return retval; }
|
5. 进程调度
5.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
| ┌────────────────────────────────────────────────────────────────┐ │ 调度器架构 │ ├────────────────────────────────────────────────────────────────┤ │ │ │ ┌──────────────────────────────────────────────────────┐ │ │ │ Core Scheduler (sched/core.c) │ │ │ │ - schedule() 主调度函数 │ │ │ │ - pick_next_task() 选择下一个任务 │ │ │ │ - context_switch() 上下文切换 │ │ │ └──────────────────────────────────────────────────────┘ │ │ │ │ │ ┌──────────────────┼──────────────────┐ │ │ │ │ │ │ │ ↓ ↓ ↓ │ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │ │ stop_sched_class │ │ dl_sched_class │ │ rt_sched_class │ │ │ │ (空闲任务) │ │ (Deadline) │ │ (实时) │ │ │ └─────────────┘ └─────────────┘ └─────────────┘ │ │ │ │ │ ↓ │ │ ┌─────────────┐ │ │ │ fair_sched_class │ │ │ │ (CFS) │ │ │ └─────────────┘ │ │ │ │ │ ↓ │ │ ┌─────────────┐ │ │ │ idle_sched_class │ │ │ │ (idle) │ │ │ └─────────────┘ │ │ │ └────────────────────────────────────────────────────────────────┘
|
调度类优先级:
stop_sched_class - 停机任务 (最高优先级)
dl_sched_class - Deadline 调度
rt_sched_class - 实时调度 (SCHED_FIFO/SCHED_RR)
fair_sched_class - 完全公平调度 (SCHED_NORMAL/SCHED_BATCH)
idle_sched_class - 空闲任务 (最低优先级)
5.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 56
| struct sched_entity { struct load_weight load; unsigned long runnable_weight;
u64 exec_start; u64 sum_exec_runtime; u64 vruntime; u64 vruntime_copy;
struct rb_node run_node;
struct list_head group_node; unsigned int on_rq;
struct cfs_rq *cfs_rq; struct cfs_rq *my_q; };
struct sched_rt_entity { struct list_head run_list; unsigned long timeout; unsigned int time_slice;
struct sched_rt_entity *back; struct sched_rt_entity *parent; struct rt_rq *rt_rq; struct rt_rq *my_q; };
struct sched_dl_entity { struct rb_node rb_node;
u64 dl_runtime; u64 dl_deadline; u64 dl_period; u64 dl_bw;
unsigned int dl_throttled:1; unsigned int dl_boosted:1; unsigned int dl_yielded:1; unsigned int dl_non_contending:1;
struct dl_rq *dl_rq; struct dl_rq *my_q; };
|
5.3 运行队列 (Run Queue)
位置: kernel/sched/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 28 29 30 31 32 33 34 35
| struct rq { raw_spinlock_t lock;
unsigned long nr_running; unsigned long nr_numa_running; unsigned long nr_preferred_running; unsigned long nr_uninterruptible;
u64 nr_switches; u64 nr_load_updates;
struct cfs_rq cfs; struct rt_rq rt; struct dl_rq dl;
struct task_struct *idle; struct task_struct *stop;
u64 clock; u64 clock_task;
unsigned int nr_context_switches;
struct cpu_stop_work stop_work;
};
|
5.4 完全公平调度器 (CFS)
位置: kernel/sched/fair.c
核心思想: 基于 vruntime (虚拟运行时间) 的红-黑树调度
vruntime 计算:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| static void update_curr(struct cfs_rq *cfs_rq) { struct sched_entity *curr = cfs_rq->curr; u64 now = rq_clock_task(rq_of(cfs_rq)); u64 delta_exec;
delta_exec = now - curr->exec_start; if (unlikely((s64)delta_exec <= 0)) return;
curr->exec_start = now;
curr->vruntime += calc_delta_fair(delta_exec, curr);
update_min_vruntime(cfs_rq); }
|
红-黑树结构:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| ┌───────────────────────────────┐ │ CFS 运行队列 │ │ (rb_root_cached) │ └───────────────────────────────┘ │ ↓ ┌────────────────┐ │ 左子树 │ vruntime 小 │ (更早需要CPU) │ └────────────────┘ │ ┌────────────────┐ │ rb_leftmost │ ← 下一个被调度任务 │ (最小vruntime) │ └────────────────┘ │ ┌────────────────┐ │ 右子树 │ vruntime 大 │ (较晚需要CPU) │ └────────────────┘
|
任务选择:
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
| static struct sched_entity * pick_next_entity(struct cfs_rq *cfs_rq, struct sched_entity *curr) { struct sched_entity *left = __pick_first_entity(cfs_rq); struct sched_entity *se;
if (!left || (curr && entity_before(curr, left))) se = curr; else se = left;
if (cfs_rq->skip == se) { struct sched_entity *second; if (se == curr) second = __pick_first_entity(cfs_rq); else second = __pick_next_entity(se); if (second && wakeup_preempt_entity(second, left) < 1) se = second; }
return se; }
|
5.5 实时调度器
位置: kernel/sched/rt.c
策略类型:
SCHED_FIFO - 先进先出,运行直到主动让出
SCHED_RR - 轮转调度,时间片用完重新排队
实时优先级: 0-99 (数值越大优先级越高)
调度逻辑:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| static struct sched_rt_entity *pick_next_rt_entity(struct rq *rq, struct rt_rq *rt_rq) { struct rt_prio_array *array = &rt_rq->active; struct sched_rt_entity *next = NULL;
struct list_head *queue = __sched_pos_from_prio(array, idx);
next = list_entry(queue->next, struct sched_rt_entity, run_list);
return next; }
|
5.6 Deadline 调度器
位置: kernel/sched/deadline.c
调度算法: EDF (Earliest Deadline First)
任务参数:
runtime - 执行时间预算
deadline - 绝对截止时间
period - 任务周期
带宽管理:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
|
static int dl_check_constraints(struct sched_dl_entity *dl_se) { u64 period = dl_se->dl_period; u64 runtime = dl_se->dl_runtime; u64 new_bw = to_ratio(period, runtime);
if (new_bw > to_ratio(global_rt_period(), global_rt_runtime())) return -EBUSY;
return 0; }
|
5.7 上下文切换
位置: kernel/sched/core.c:context_switch()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| static __always_inline struct rq * context_switch(struct rq *rq, struct task_struct *prev, struct task_struct *next, struct rq_flags *rf) { struct mm_struct *mm, *oldmm;
prepare_task_switch(rq, prev, next);
mm = next->mm; oldmm = prev->active_mm;
switch_mm_irqs_off(oldmm, mm, next);
switch_to(oldmm, mm, prev, next);
finish_task_switch(rq, prev);
return rq; }
|
switch_to 宏 (体系相关):
1 2 3 4 5 6 7 8 9 10 11 12
| /* x86_64 */ #define switch_to(prev, next, last) \ asm volatile("pushq %%rbp\n\t" \ "movq %%rsp, %P[thread_rsp](%[prev])\n\t" \ "movq %P[thread_rsp](%[next]), %%rsp\n\t" \ "call __switch_to\n\t" \ "popq %%rbp\n\t" \ : "=a" (last) \ : [prev] "D" (prev), \ [next] "S" (next) \ : "memory", "rcx", "rbx", "r8", "r9", \ "r10", "r11", "r12", "r13", "r14", "r15");
|
5.8 负载均衡
位置: kernel/sched/topology.c
负载均衡时机:
- 周期性负载均衡 (
scheduler_tick)
- CPU 空闲时 (
idle_balance)
- 创建新进程时 (
select_task_rq_fair)
- CPU 热迁移时
负载计算:
1 2 3 4 5 6 7 8 9 10 11 12 13
| static __always_inline u64 ___update_load_sum(u64 now, u64 last_update, u64 period) { long delta = now - last_update;
if (delta > period) { delta = decay_load(last_update, now); }
return delta; }
|
6. 进程状态与转换
6.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
| #define TASK_RUNNING 0x00000000 #define TASK_INTERRUPTIBLE 0x00000001 #define TASK_UNINTERRUPTIBLE 0x00000002 #define __TASK_STOPPED 0x00000004 #define __TASK_TRACED 0x00000008
#define EXIT_DEAD 0x00000010 #define EXIT_ZOMBIE 0x00000020
#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.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 56 57 58 59
| 创建进程 │ ↓ ┌─────────────────────────────────────────────────────┐ │ TASK_NEW │ │ (新创建,尚未运行) │ └──────────────────────┬──────────────────────────────┘ │ wake_up_new_task() ↓ ┌─────────────────────────────────────────────────────┐ │ TASK_RUNNING │ │ (就绪队列中,可被调度) │ └───────────────┬─────────────────────────┬───────────┘ │ │ schedule() 选中 等待资源/事件 │ │ ↓ ↓ ┌──────────────────────┐ ┌──────────────────────────┐ │ 运行中 │ │ TASK_INTERRUPTIBLE │ │ (current = task) │ │ TASK_UNINTERRUPTIBLE │ └─────────┬────────────┘ │ (可中断/不可中断睡眠) │ │ └────────────┬─────────────┘ │ │ │ 时间片用完/主动yield │ 事件到达 │ │ ↓ ↓ ┌──────────────────────┐ ┌──────────────────────────┐ │ TASK_RUNNING │ │ TASK_RUNNING │ │ (重新排队) │ └──────────────────────────┘ └──────────────────────┘
特殊状态: ┌──────────────────┐ SIGSTOP ┌────────────────────┐ │ __TASK_STOPPED │ ←────────────── │ 暂停调试 │ │ (进程被暂停) │ │ │ └─────────┬────────┘ └────────────────────┘ │ │ SIGCONT ↓ TASK_RUNNING
┌──────────────────┐ SIGKILL ┌────────────────────┐ │ __TASK_TRACED │ ←────────────── │ ptrace 调试 │ │ (被跟踪调试) │ │ │ └──────────────────┘ └────────────────────┘
退出路径: ┌──────────────────┐ do_exit() ┌────────────────────┐ │ TASK_DEAD │ ←────────────── │ EXIT_ZOMBIE │ │ (正在退出) │ │ (僵尸进程) │ └──────────────────┘ └─────────┬──────────┘ │ wait()/waitpid() │ ↓ ┌────────────────────┐ │ EXIT_DEAD │ │ (进程描述符回收) │ └────────────────────┘
|
6.3 睡眠与唤醒
睡眠函数:
1 2 3 4 5 6 7 8 9 10 11 12 13
| static inline int signal_pending_state(long state, struct task_struct *p) { if (!(state & TASK_INTERRUPTIBLE)) return 0; return signal_pending(p); }
wait_event_interruptible(wq, condition); wait_event_uninterruptible(wq, condition); wait_event_killable(wq, condition); wait_event_timeout(wq, condition, timeout);
|
唤醒函数:
1 2 3 4 5
| void wake_up(struct wait_queue_head *wq_head); void wake_up_all(struct wait_queue_head *wq_head); void wake_up_interruptible(struct wait_queue_head *wq_head); void wake_up_process(struct task_struct *tsk);
|
6.4 等待队列
位置: 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
| struct wait_queue_head { spinlock_t lock; struct list_head head; };
struct wait_queue_entry { unsigned int flags; void *private; wait_queue_func_t func; struct list_head entry; };
DECLARE_WAIT_QUEUE_HEAD(name); init_waitqueue_head(wq_head);
void add_wait_queue(struct wait_queue_head *wq_head, struct wait_queue_entry *wq_entry);
void remove_wait_queue(struct wait_queue_head *wq_head, struct wait_queue_entry *wq_entry);
|
使用示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| static DECLARE_WAIT_QUEUE_HEAD(wq); static int condition = 0;
static int waiting_thread(void *data) { wait_event_interruptible(wq, condition != 0); return 0; }
static void wake_condition(void) { condition = 1; wake_up(&wq); }
|
7. 进程退出与等待
7.1 进程退出
位置: kernel/exit.c:do_exit()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| void __noreturn do_exit(long code) { struct task_struct *tsk = current;
tsk->exit_code = code;
exit_signals(tsk); exit_notify(tsk); exit_mm(tsk); exit_sem(tsk); __exit_fs(tsk); exit_files(tsk); exit_thread(tsk); exit_creds(tsk);
tsk->state = TASK_DEAD; tsk->flags |= PF_EXITPIDONE;
__schedule(SM_DEAD); }
|
7.2 僵尸进程与孤儿进程
僵尸进程 (Zombie):
- 进程已退出,但父进程尚未 wait()
- 保留进程描述符中的部分信息 (退出码等)
- 进程状态为
EXIT_ZOMBIE
孤儿进程 (Orphan):
- 父进程先于子进程退出
- 被 init 进程 (PID 1) 收养
- init 会定期调用 wait() 回收僵尸
7.3 wait 系列系统调用
系统调用:
1 2 3 4 5 6 7 8 9
| SYSCALL_DEFINE5(waitid, int, which, pid_t, upid, struct siginfo __user *, infop, int, options, struct rusage __user *, ru);
SYSCALL_DEFINE4(wait4, pid_t, upid, int __user *, stat_addr, int, options, struct rusage __user *, ru);
SYSCALL_DEFINE3(waitpid, pid_t, pid, int __user *, stat_addr, int, options);
|
实现位置: kernel/exit.c:do_wait()
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
| static long do_wait(struct wait_opts *wo) { struct task_struct *tsk; int retval;
tsk = current; do { struct task_struct *p;
list_for_each_entry(p, &tsk->children, sibling) { int ret = wait_consider_task(wo, p); if (ret) return ret; }
if (wo->flags & WNOTHREAD) break;
tsk = next_thread(tsk); } while (tsk != current);
retval = wait_task_inactive(wo, tsk);
return retval; }
|
7.4 退出通知
位置: kernel/exit.c:exit_notify()
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
| static void exit_notify(struct task_struct *tsk) { do_notify_parent(tsk, tsk->exit_signal);
if (tsk->exit_signal == SIGCHLD && !do_notify_parent(tsk, tsk->exit_signal)) { tsk->exit_state = EXIT_DEAD; release_task(tsk); return; }
tsk->exit_state = EXIT_ZOMBIE;
if (tsk->parent == tsk->real_parent) { struct task_struct *reaper;
reaper = find_child_reaper(tsk); if (reaper != tsk->parent) { for_each_thread(tsk, p) p->real_parent = reaper; tsk->parent = reaper; } } }
|
8. 内核线程
8.1 内核线程特点
- 运行在内核空间,没有用户地址空间
mm 为 NULL,active_mm 指向前一个进程的 mm (借用)
- 只能调用内核函数,不能访问用户空间
- 直接访问所有内核数据和函数
8.2 kthread_create API
位置: kernel/kthread.c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| struct task_struct *kthread_create(int (*threadfn)(void *data), void *data, const char namefmt[], ...);
struct task_struct *kthread_run(int (*threadfn)(void *data), void *data, const char namefmt[], ...);
int kthread_stop(struct task_struct *k);
bool kthread_should_stop(void);
|
8.3 内核线程实现
创建流程:
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
| static int kthread(void *_create) { struct kthread_create_info *create = _create; int (*threadfn)(void *data) = create->threadfn; void *data = create->data;
complete(&create->started);
if (!threadfn) { set_current_state(TASK_INTERRUPTIBLE); while (!kthread_should_stop()) { schedule(); set_current_state(TASK_INTERRUPTIBLE); } __set_current_state(TASK_RUNNING); return 0; }
return threadfn(data); }
struct task_struct *__kthread_create_on_node(int (*threadfn)(void *data), void *data, int node, const char namefmt[], ...) { struct kthread_create_info create;
create.threadfn = threadfn; create.data = data; init_completion(&create.started); init_completion(&create.done);
pid = kernel_thread(kthread, &create, CLONE_FS | CLONE_FILES | SIGCHLD);
wait_for_completion(&create.started);
return task; }
|
8.4 常见内核线程
| 线程名 |
功能 |
位置 |
ksoftirqd/n |
软中断处理 |
kernel/softirqd.c |
kworker/n:n |
工作队列执行 |
kernel/workqueue.c |
kswapd/n |
页面回收 |
mm/vmscan.c |
kthrotld/n |
磁盘 I/O 限流 |
block/blk-throttle.c |
migration/n |
负载均衡 |
kernel/sched/topology.c |
rcuop/n |
RCU 回调 |
kernel/rcu/tree.c |
rcuog/n |
RCU 强制宽限 |
kernel/rcu/tree.c |
rcu_preempt |
RCU 抢占 |
kernel/rcu/tree.c |
kcompactd/n |
内存压缩 |
mm/compaction.c |
ksmd |
KSM 合并 |
mm/ksm.c |
9. 进程关系与组管理
9.1 进程树结构
1 2 3 4 5 6 7 8
| struct task_struct { struct task_struct __rcu *real_parent; struct task_struct __rcu *parent; struct list_head children; struct list_head sibling; struct task_struct *group_leader; };
|
进程树示例:
1 2 3 4 5 6 7 8 9 10 11 12
| init (PID 1) ├─ systemd (PID 1000, PGID 1000) │ ├─ NetworkManager (PID 1001, PGID 1000) │ ├─ sshd (PID 1002, PGID 1000) │ │ └─ sshd (PID 2000, PGID 2000, SID 2000) │ │ └─ bash (PID 2001, PGID 2000, SID 2000) │ │ └─ command (PID 2002, PGID 2002, SID 2000) │ └─ cron (PID 1003, PGID 1000) └─ containerd (PID 500, PGID 500) └─ dockerd (PID 501, PGID 500) └─ container-init (PID 10000, PGID 10000) └─ app-process (PID 10001, PGID 10000)
|
9.2 线程组
多线程进程结构:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| 进程 (TGID = 1000): ┌─────────────────────────────────────────────────────┐ │ shared: mm, fs, files, signal, sighand │ └─────────────────────────────────────────────────────┘ │ ┌───────────────┼───────────────┐ │ │ │ ┌─────┴─────┐ ┌─────┴─────┐ ┌─────┴─────┐ │ thread 1 │ │ thread 2 │ │ thread 3 │ │ PID=1000 │ │ PID=1001 │ │ PID=1002 │ │ TGID=1000 │ │ TGID=1000 │ │ TGID=1000 │ └───────────┘ └───────────┘ └───────────┘
task_struct 关系: thread 1: group_leader = thread1, thread_pid = PID 1000 thread 2: group_leader = thread1, thread_pid = PID 1001 thread 3: group_leader = thread1, thread_pid = PID 1002
|
9.3 进程组与会话
1 2 3 4
| struct task_struct { struct pid *pgrp; struct pid *session; };
|
会话与进程组:
1 2 3 4 5 6 7 8 9 10 11 12
| Session 1 (SID 1): ┌──────────────────────────────────────────────────────┐ │ Process Group 1000 (PGID 1000): │ │ ├─ bash (PID 1000, leader) │ │ ├─ command1 (PID 1001) │ │ └─ command2 (PID 1002) │ └──────────────────────────────────────────────────────┘ ┌──────────────────────────────────────────────────────┐ │ Process Group 2000 (PGID 2000): │ │ ├─ background_task1 (PID 2000, leader) │ │ └─ background_task2 (PID 2001) │ └──────────────────────────────────────────────────────┘
|
9.4 控制终端
1 2 3
| struct signal_struct { struct tty_struct *tty; };
|
终端相关信号:
SIGINT (Ctrl+C) - 中断
SIGQUIT (Ctrl+) - 退出
SIGTSTP (Ctrl+Z) - 停止
SIGHUP - 挂断 (终端关闭)
10. 实时进程管理
10.1 实时策略
策略类型:
1 2 3 4 5 6
| #define SCHED_NORMAL 0 #define SCHED_FIFO 1 #define SCHED_RR 2 #define SCHED_BATCH 3 #define SCHED_IDLE 5 #define SCHED_DEADLINE 6
|
10.2 实时优先级
1 2 3 4 5 6
| #define MAX_RT_PRIO 100 #define MAX_USER_RT_PRIO 100 #define MAX_PRIO (MAX_RT_PRIO + NICE_WIDTH)
|
10.3 实时调度 API
系统调用:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| int sched_setscheduler(pid_t pid, int policy, const struct sched_param *param);
int sched_getscheduler(pid_t pid);
int sched_setparam(pid_t pid, const struct sched_param *param);
int sched_getparam(pid_t pid, struct sched_param *param);
int sched_yield(void);
|
10.4 优先级继承
用途: 解决优先级反转问题
实现: kernel/locking/rtmutex.c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
|
void rt_mutex_set_prio(struct task_struct *task, int prio) { task->prio = prio; task->rt_priority = prio;
if (task->on_rq) enqueue_task(rq, task, ENQUEUE_RESTORE); }
|
11. 进程资源限制与统计
11.1 资源限制 (rlimit)
位置: 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
| struct task_struct { struct rlimit rlim[RLIM_NLIMITS]; };
enum rlimit_resource { RLIMIT_CPU, RLIMIT_FSIZE, RLIMIT_DATA, RLIMIT_STACK, RLIMIT_CORE, RLIMIT_RSS, RLIMIT_NPROC, RLIMIT_NOFILE, RLIMIT_MEMLOCK, RLIMIT_AS, RLIMIT_LOCKS, RLIMIT_SIGPENDING, RLIMIT_MSGQUEUE, RLIMIT_NICE, RLIMIT_RTPRIO, RLIMIT_RTTIME, RLIMIT_NLIMITS, };
|
11.2 进程统计
位置: kernel/sched/stats.c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| struct task_struct { u64 utime; u64 stime; u64 gtime; unsigned long nvcsw; unsigned long nivcsw; u64 utimescaled; u64 stimescaled; u64 prev_cputime; };
struct task_struct { unsigned long min_flt; unsigned long maj_flt; };
|
11.3 /proc 文件系统
进程相关文件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| /proc/[pid]/ ├── cmdline # 命令行参数 ├── cwd # 当前工作目录链接 ├── environ # 环境变量 ├── exe # 可执行文件链接 ├── fd/ # 文件描述符目录 ├── maps # 内存映射 ├── mem # 进程内存 ├── mounts # 挂载点 ├── stat # 进程状态 ├── statm # 内存统计 ├── status # 详细状态 ├── task/ # 线程子目录 └── ...
|
12. 进程调试与监控
12.1 strace
用途: 追踪系统调用
1 2 3 4 5 6 7 8 9 10 11
| strace ls
strace -p 1234
strace -c ls
strace -f ls
|
12.2 perf
用途: 性能分析
1 2 3 4 5 6 7 8 9 10 11
| perf sched record -- sleep 60
perf sched latency
perf sched map
perf top
|
12.3 ftrace
用途: 函数追踪
1 2 3 4 5 6 7 8 9 10 11
| cat /sys/kernel/debug/tracing/available_tracers
echo function_graph > /sys/kernel/debug/tracing/current_tracer
echo sched_fork > /sys/kernel/debug/tracing/set_ftrace_filter
cat /sys/kernel/debug/tracing/trace
|
12.4 BPF/BCC
用途: 动态追踪
1 2 3 4 5 6 7 8 9 10 11
| bcc execsnoop
bcc exitsnoop
bcc runqlat
bcc profile
|
12.5 /proc/sys/kernel 调优参数
1 2 3 4 5 6 7 8 9
| /proc/sys/kernel/pid_max /proc/sys/kernel/threads-max /proc/sys/kernel/randomize_va_space /proc/sys/kernel/sched_rt_period_us /proc/sys/kernel/sched_rt_runtime_us /proc/sys/kernel/sched_min_granularity_ns /proc/sys/kernel/sched_wakeup_granularity_ns /proc/sys/kernel/sched_latency_ns
|
附录 A: 系统调用参考
fork/vfork/clone
| 系统调用 |
描述 |
头文件 |
fork() |
创建子进程 |
unistd.h |
vfork() |
创建共享地址空间的子进程 |
unistd.h |
clone() |
灵活创建进程/线程 |
sched.h |
clone3() |
新版 clone (Linux 5.3+) |
sched.h |
exec 系列函数
| 函数 |
描述 |
头文件 |
execl() |
执行程序 |
unistd.h |
execlp() |
执行程序 (PATH 搜索) |
unistd.h |
execle() |
执行程序 (指定环境) |
unistd.h |
execv() |
执行程序 (参数数组) |
unistd.h |
execvp() |
执行程序 (PATH + 参数数组) |
unistd.h |
execve() |
系统调用 |
unistd.h |
wait 系列函数
| 函数 |
描述 |
头文件 |
wait() |
等待子进程 |
sys/wait.h |
waitpid() |
等待指定子进程 |
sys/wait.h |
waitid() |
等待子进程状态变化 |
sys/wait.h |
wait3() |
等待并获取资源使用 |
sys/wait.h |
wait4() |
等待指定子进程并获取资源 |
sys/wait.h |
调度相关系统调用
| 系统调用 |
描述 |
头文件 |
sched_setscheduler() |
设置调度策略 |
sched.h |
sched_getscheduler() |
获取调度策略 |
sched.h |
sched_setparam() |
设置优先级 |
sched.h |
sched_getparam() |
获取优先级 |
sched.h |
sched_yield() |
让出 CPU |
sched.h |
sched_getaffinity() |
获取 CPU 亲和性 |
sched.h |
sched_setaffinity() |
设置 CPU 亲和性 |
sched.h |
sched_get_priority_max() |
获取最大优先级 |
sched.h |
sched_get_priority_min() |
获取最小优先级 |
sched.h |
sched_rr_get_interval() |
获取 RR 时间片 |
sched.h |
其他相关系统调用
| 系统调用 |
描述 |
头文件 |
getpid() |
获取进程 ID |
unistd.h |
getppid() |
获取父进程 ID |
unistd.h |
gettid() |
获取线程 ID |
unistd.h |
getpgid() |
获取进程组 ID |
unistd.h |
setpgid() |
设置进程组 ID |
unistd.h |
getsid() |
获取会话 ID |
unistd.h |
setsid() |
创建新会话 |
unistd.h |
getpriority() |
获取优先级 |
sys/resource.h |
setpriority() |
设置优先级 |
sys/resource.h |
getrlimit() |
获取资源限制 |
sys/resource.h |
setrlimit() |
设置资源限制 |
sys/resource.h |
nice() |
调整 nice 值 |
unistd.h |
附录 B: 相关配置选项
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
| # 调度器相关 CONFIG_SCHED_CORE # 核心调度支持 CONFIG_SCHED_AUTOGROUP # 自动进程组 CONFIG_FAIR_GROUP_SCHED # CFS 分组调度 CONFIG_RT_GROUP_SCHED # 实时分组调度 CONFIG_CFS_BANDWIDTH # CFS 带宽控制 CONFIG_RT_GROUP_SCHED # 实时分组调度 CONFIG_UCLAMP_TASK # 任务利用率钳制 CONFIG_UCLAMP_BUCKETS_COUNT # 钳制桶数量
# 进程调试 CONFIG_PROC_FS # /proc 文件系统 CONFIG_PROC_CHILDREN # /proc/[pid]/children CONFIG_PROC_PID_CPUSET # /proc/[pid]/cpuset CONFIG_STACKTRACE # 栈追踪 CONFIG_DEBUG_STACK_USAGE # 栈使用调试
# 进程资源限制 CONFIG_RCU_BOOST # RCU 优先级提升 CONFIG_RCU_NOCB_CPU # RCU 回调离线 CPU
# 其他 CONFIG_MEMCG # 内存 cgroup CONFIG_CPUSETS # CPU 集合 CONFIG_CGROUP_SCHED # cgroup 调度
|
附录 C: 参考文献
Linux 内核源码
kernel/fork.c - 进程创建
kernel/exit.c - 进程退出
kernel/sched/core.c - 调度器核心
kernel/sched/fair.c - CFS 调度
kernel/sched/rt.c - 实时调度
include/linux/sched.h - 进程描述符
Linux 内核文档
Documentation/scheduler/ - 调度器文档
Documentation/admin-guide/ - 管理指南
理解 Linux 内核 (ULK3) - Daniel P. Bovet & Marco Cesati
Linux 内核设计与实现 (LKD3) - Robert Love
Linux Kernel Development - Robert Love