ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

【linux内核专栏 03】进程管理与调度

【linux内核专栏 03】进程管理与调度 本篇定位:Linux 内核的宇宙中心是task_struct——所有子系统都围绕它。对于有过轻量级实时操作系统如FreeRTOS TCB 到 port 层经验的工程师,本篇把Linux 进程对你 FreeRTOS 任务的增量讲清:task_struct 比 TCB 胖十倍(含 mm/fs/files/signals)、调度从优先级抢占跳到CFS 公平 EEVDF、上下文切换从切栈跳到切地址空间 切栈 切 fs/files。读完能写内核线程、能调调度问题、能讲清 CFS vs FreeRTOS 优先级调度的本质差异。目录一、task_struct:宇宙中心的数据结构1.1 task_struct 有多大1.2 task_struct 核心字段(分组)1.3 对照 FreeRTOS TCB二、进程状态2.1 Linux 进程状态2.2 状态机2.3 关键状态解读2.4 ps 看状态2.5 对照 FreeRTOS 状态三、进程 vs 线程 vs 内核线程3.1 Linux 不区分进程线程(都是 task_struct)3.2 fork / clone / vfork3.3 内核线程(kthread)3.4 PID vs TGID vs TID四、上下文切换(对照 RISC-V trap)4.1 两种切换4.2 进程上下文切换做什么4.3 switch_to:切寄存器(架构相关)4.4 对照你 RISC-V trap 切栈4.5 为什么只存 callee-saved五、CFS 调度器(Completely Fair Scheduler)⭐ 核心5.1 CFS 的核心思想5.2 vruntime 怎么算5.3 nice 值与权重5.4 CFS 数据结构:红黑树5.5 调度时序5.6 sched_latency 与 min_granularity5.7 对照 FreeRTOS 优先级调度六、EEVDF(新调度器,Linux 6.6)6.1 为什么 CFS 升级到 EEVDF6.2 EEVDF 核心思想6.3 对你影响七、调度策略(Scheduling Policy)7.1 三类调度策略7.2 RT 优先级7.3 chrt 改策略7.4 SCHED_DEADLINE(硬实时)八、抢占(Preemption)8.1 抢占点8.2 抢占等级(CONFIG)8.3 关抢占 vs 关中断九、fork / exec / wait(进程生命周期)9.1 fork()9.2 exec()9.3 wait()9.4 孤儿进程与僵尸十、进程关系与会话10.1 进程组 / 会话10.2 守护进程(daemon)十一、常用进程调试11.1 工具11.2 关键 /proc 字段十二、本篇小结速查表一、task_struct:宇宙中心的数据结构1.1 task_struct 有多大FreeRTOS TCB:几百字节(栈指针/优先级/状态/链表节点)Linuxtask_struct:约 8000 字节(ARM64/RISC-V 64)为什么这么大?因为 Linux 进程要独立地址空间 文件上下文 信号 cgroup namespace 审计…全挂这里。1.2 task_struct 核心字段(分组)structtask_struct{// 标识 pid_tpid;// 进程 ID(线程组里是线程 ID)pid_ttgid;// 线程组 ID(进程 ID,用户看到的)structtask_struct*group_leader;// 线程组首领charcomm[TASK_COMM_LEN];// 可执行文件名(16 字符)// 状态 volatilelongstate;// 进程状态(见 §二)intexit_state;intprio,static_prio,normal_prio;// 优先级unsignedintpolicy;// 调度策略(SCHED_NORMAL/FIFO/RR)// 调度 conststructsched_class*sched_class;// 调度类structsched_entityse;// CFS 调度实体(vruntime 等)structsched_rt_entityrt;// RT 调度实体unsignedintrt_priority;cpumask_tcpus_allowed;// 允许跑的 CPU// 家族 structtask_struct*parent;// 父进程structlist_headchildren;// 子进程链表structlist_headsibling;// 内存(★对照 FreeRTOS 最大差异)structmm_struct*mm;// 进程地址空间(线程共享)structmm_struct*active_mm;// 内核线程用(借来的 mm)// 文件 structfiles_struct*files;// 打开的文件表structfs_struct*fs;// 文件系统根/root// 信号 structsignal_struct*signal;structsighand_struct*sighand;sigset_tblocked,real_blocked;// 栈 void*stack;// 内核栈(union with thread_info)// 时间统计 u64 utime,stime;// 用户态/内核态时间u64 nvcsw,nivcsw;// 自愿/非自愿切换次数// namespace/cgroup(容器)structnsproxy*nsproxy;structcss_set__rcu*cgroups;// ... 还有几百个字段};1.3 对照 FreeRTOS TCB字段FreeRTOS TCBLinux task_struct差异栈指针pxTopOfStacksp(在 stack 里)同优先级uxPriorityprio/static_prioLinux 更复杂(多套)状态eTaskStatestateLinux 状态更多链表xStateListItem 等list_head 多个同思路地址空间❌ 无mm_struct ★Linux 最大增量文件表❌ 无files_struct ★Linux 最大增量信号❌ 无signal/sighand ★Linux 有时间统计❌ 无utime/stimeLinux 有嵌入式视角:Linux task_struct 是胖版 TCB——多了 mm(地址空间)/files(文件)/signals(信号)/namespace(容器)。因为 Linux 进程要独立地址空间和文件上下文,FreeRTOS 任务全在一个地址空间共享一切。字段虽多,核心思路同(标识/状态/调度/栈),增量在 mm 和 files。二、进程状态2.1 Linux 进程状态#define TASK_RUNNING 0 // 可运行(就绪或正在跑) #define TASK_INTERRUPTIBLE 1 // 可中断睡眠(信号能唤醒) #define TASK_UNINTERRUPTIBLE 2 // 不可中断睡眠(信号不唤醒,等 IO) #define __TASK_STOPPED 4 // 停止(信号 SIGSTOP) #define __TASK_TRACED 8 // 被跟踪(gdb) #define EXIT_ZOMBIE 16 // 僵尸(死了等父收尸) #define EXIT_DEAD 32 // 最终死亡2.2 状态机fork() │ ▼ ┌─────────┐ 调度选中 ┌─────────┐ │ RUNNING │ ───────── │ RUNNING │ │ (就绪) │ ───────── │ (运行) │ └────┬────┘ 时间片到 └────┬────┘ │ │ │ 等 IO/信号量 │ 信号/IO 完成 ▼ ▼ ┌──────────────┐ ┌─────────┐ │INTERRUPTIBLE │ ───────│ RUNNING │ │ (可中断睡) │ 唤醒 │ (就绪) │ └──────────────┘ └─────────┘ │ │ 等 磁盘 IO(D 状态) ▼ ┌────────────────┐ │UNINTERRUPTIBLE │ 信号唤不醒,只能 IO 完成 │ (不可中断睡) │ └────────────────┘2.3 关键状态解读TASK_RUNNING:就绪(在运行队列)或正在跑(单 CPU 同时只有一个跑)TASK_INTERRUPTIBLE:可中断睡眠,等事件(信号量/IO/信号),信号能打断TASK_UNINTERRUPTIBLE:D状态,等磁盘 IO 等,信号唤不醒——这是杀不掉的进程(kill -9 也没用)TASK_ZOMBIE:死了但父没wait(),占 PID 和退出码,等收尸2.4 ps 看状态ps-eopid,stat,comm# STAT 列:# Rrunning Sinterruptible sleep Duninterruptible sleep# Tstopped Zzombie Xdead# 前台 s 会话首 l 多线程 高优先级 N 低优先级2.5 对照 FreeRTOS 状态FreeRTOSLinux差异RunningRUNNING(运行)同ReadyRUNNING(就绪)Linux 不分就绪/运行(都 RUNNING)BlockedINTERRUPTIBLE/UNINTERRUPTIBLELinux 分两种睡眠SuspendedSTOPPED类似DeletedZOMBIELinux 要父收尸D 状态是 Linux 的杀不掉FreeRTOS 任务阻塞 等 signal/queue,能被删。LinuxD状态(等磁盘 IO)信号唤不醒,kill -9 也杀不掉——因为杀它要它响应信号,它在 D 不响应。这是 Linux 比 FreeRTOS 复杂的点:IO 等待有不可打断语义,防止 IO 中途被打断导致数据不一致。你调进程杀不掉先看是不是 D 状态。三、进程 vs 线程 vs 内核线程3.1 Linux 不区分进程线程(都是 task_struct)概念mm 是否共享files 是否共享创建方式进程不共享(独立)不共享fork()线程共享共享clone(CLONE_VM|CLONE_FILES|…)内核线程无 mm(借 active_mm)共享 init_fileskthread_create()3.2 fork / clone / vforkLinux 进程创建底层都是clone系统调用,靠 flag 控制共享什么:// fork:不共享(子独立)clone(SIGCHLD);// pthread_create:共享 mm/files/信号等clone(CLONE_VM|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|...);// vfork:共享 mm,父阻塞到子 exec/exitclone(CLONE_VM|CLONE_VFORK);3.3 内核线程(kthread)内核线程:只在内核态跑,没用户态地址空间。用途:后台活(kworker/ksoftirqd/kthreadd/migration)。// 创建内核线程structtask_struct*kkthread_create(my_thread_fn,arg,mythread);wake_up_process(k);// 唤醒让它跑// 或一步到位structtask_struct*kkthread_run(my_thread_fn,arg,mythread);内核线程的mm为 NULL,跑时active_mm借前一个进程的 mm(省切页表)。嵌入式视角:内核线程 FreeRTOS 任务你 FreeRTOS 任务 函数死循环。Linux内核线程最像 FreeRTOS 任务——一个函数在内核态循环跑。你写驱动要后台活(轮询/处理),用kthread_run起一个,和 FreeRTOSxTaskCreate同构。区别:内核线程在内核态(全权),FreeRTOS 任务在内核态(FreeRTOS 无分层)。用户态线程( pthread)是另一回事,在 U 态跑。3.4 PID vs TGID vs TIDPID(Process ID):用户看到的进程号,实际是TGID(线程组 ID)TID(Thread ID):线程 ID,内核task_struct-pid(每个 task_struct 唯一)单线程进程:PID TID多线程进程:同组 task_struct 共享 TGID,各 TID 不同ps-eLf# 看 PID(TGID)/ TID# 多线程进程:N 行同 PID,不同 TID(LWP)四、上下文切换(对照 RISC-V trap)4.1 两种切换切换是什么频率用户态↔内核态syscall/中断,同进程内高(每次 syscall)进程上下文切换从进程 A 切到进程 B中(调度时)4.2 进程上下文切换做什么context_switch()(kernel/sched/core.c):staticvoidcontext_switch(structrq*rq,structtask_struct*prev,structtask_struct*next){structmm_struct*mmnext-mm;structmm_struct*oldmmprev-active_mm;// 1. 切地址空间(若不同)if(unlikely(!mm)){// next 是内核线程next-active_mmoldmm;// 借 prev 的 mm}elseif(prev-mm!mm){// 不同进程switch_mm(oldmm,mm,next);// 切页表(写 satp flush TLB)}// 2. 切寄存器(栈指针/ra/...)- switch_to()switch_to(prev,next,prev);}4.3 switch_to:切寄存器(架构相关)switch_to最终调__switch_to(arch/riscv/kernel/entry.S 或类似):// 简化的 RISC-V 版 __switch_to: # 1. 保存 prev 的 callee-saved 寄存器到 prev 栈 addi sp, sp, -FRAME sd ra, 0(sp) sd s0, 8(sp) sd s1, 16(sp) ... # s2-s11 sd sp, TASK_THREAD_SP(a0) # 存 prev-thread.sp # 2. 切栈:加载 next 的 sp ld sp, TASK_THREAD_SP(a1) # next-thread.sp # 3. 切 TP(percpu 指针) ld tp, TASK_THREAD_TP(a1) # 4. 切 CSR(thread.fcsr 浮点 CSR 等) ... # 5. 恢复 next 的 callee-saved ld s1, 16(sp) ld s0, 8(sp) ld ra, 0(sp) addi sp, sp, FRAME ret # 跳到 next 上次被切走的地方(ra)4.4 对照你 RISC-V trap 切栈你 mscratch 切栈(中断栈)Linux switch_to(进程切换)触发中断/trap调度器决定切什么sp(中断栈↔任务栈)sp 页表 percpu CSR保存啥全部通用寄存器(中断可能破坏)只存 callee-saved(s0-s11/ra)返回mretret频率每次中断每次调度你的 mscratch 切栈是 Linux switch_to 的简化版你 [[04-trap 机制详解]] 的 mscratch 切栈:trap 时 swap sp 和 mscratch。Linux switch_to 同构——切 prev/next 的 sp。增量是:① 还切页表(mm);② 只存 callee-saved(调度点已知 caller-saved 不重要);③ 还切 percpu(tp)。你已经懂切栈,Linux 是放大版,加了切地址空间。4.5 为什么只存 callee-saved调度点是自愿的(调度器在明确位置调用 schedule),不是中断打断。所以调度点之后,编译器只保证 callee-saved 寄存器(s0-s11/ra/sp)跨函数调用保留,caller-saved(t0-t6/a0-a7)编译器已处理。只存 callee-saved 足够——比中断保存全部寄存器省。五、CFS 调度器(Completely Fair Scheduler)⭐ 核心5.1 CFS 的核心思想不是按优先级抢,是按谁跑得少轮。每个进程有vruntime(虚拟运行时间):表示它已经跑了多少调度器选vruntime最小的跑(跑得最少的优先)跑一会儿,vruntime 增加,变成不是最小,换别人跑结果:每个进程公平分享 CPU5.2 vruntime 怎么算vruntime 实际运行时间 × (NICE_0_LOAD / 进程权重)权重(weight):由 nice 值算出,nice 0 权重 1024,nice -1 权重 1171(高 10%),nice 1 权重 920(低 10%)高权重进程(nice 低):vruntime 增长慢 → 更久保持跑得少 → 更多 CPU低权重进程(nice 高):vruntime 增长快 → 很快被换下 → 少 CPU5.3 nice 值与权重nice权重CPU 占比(nice 0 为基准)-2088761极高-109548~10x010241x(基准)10110~0.1x1915极低nice 范围 -20 ~ 19,默认 0nice 不是优先级,是权重——影响 vruntime 增长率,进而影响 CPU 份额普通用户只能调高 nice(降权),root 能调低(升权)5.4 CFS 数据结构:红黑树每个 CPU 一个运行队列struct rqCFS 部分用红黑树(rbtree),按 vruntime 排序最左节点 vruntime 最小 下一个跑进程入队:插入红黑树(O(log n))进程出队:取最左(O(log n))CPU0 rq.cfs │ 红黑树(按 vruntime) │ [vruntime100] ← 最左,下一个跑 / \ [200] [150] / \ / [180][210] [130]5.5 调度时序1. tick 中断 → scheduler_tick() 2. 当前进程 vruntime 更新 3. 检查:当前 vruntime 是否 红黑树最左 sched_latency? - 否:继续跑 - 是:设 need_resched,稍后 schedule() 4. schedule(): - 当前进程入队(回红黑树) - 取最左 next - context_switch(prev, next)5.6 sched_latency 与 min_granularitysched_latency(目标延迟,~6ms):在这个窗口内,所有进程都应跑一遍min_granularity(最小粒度,~0.75ms):每个进程至少跑这么久,避免频繁切换时间片 sched_latency / 进程数,但不小于 min_granularity4 个进程,sched_latency6ms: 每个时间片 6ms / 4 1.5ms( min_granularity 0.75ms,OK) 每 6ms 每进程跑 1.5ms,公平5.7 对照 FreeRTOS 优先级调度FreeRTOS 优先级抢占Linux CFS选谁跑最高优先级vruntime 最小同优先级轮转(time slicing)自然公平(vruntime 趋同)高优先级抢占低优先级(可能饿死低)权重高 CPU 多,但不饿死饥饿低优先级可能饿死不会(都跑)实时性高(优先级绝对)低(公平,延迟不定)适合实时控制交互/吞吐CFS 不会饿死进程,但实时性弱FreeRTOS 高优先级任务永远先跑,低优先级可能饿死——对实时控制是优点(关键任务必须先跑)。CFS 不让任何进程饿死——对交互/吞吐是优点(都响应),但实时性弱。Linux 实时需求用 SCHED_FIFO/RR(见 §六),或 RT-Linux 补丁。这是你 MCU 转 Linux 要适应的:Linux 默认不硬实时。六、EEVDF(新调度器,Linux 6.6)6.1 为什么 CFS 升级到 EEVDFCFS 用了十几年,问题:公平性在某些场景不完美(特别是延迟敏感任务)启发式多,难调EEVDF(Earliest Eligible Virtual Deadline First)是 6.6 引入的新算法,理论更扎实。6.2 EEVDF 核心思想每个进程有lag(滞后量):应得 CPU - 实得 CPUEligible(合格):lag ≤ 0(没多占)的进程才能跑在合格进程里,选虚拟截止时间(vdeadline)最早的跑结果:比 CFS 更精确的公平 更好的延迟控制6.3 对你影响接口不变(还是 nice/policy)行为更公平,延迟敏感任务响应更好你看 6.6 内核代码,kernel/sched/fair.c是 EEVDF 实现了嵌入式视角:EEVDF 是 CFS 的演进,不是革命CFS → EEVDF ——核心思路(公平/vruntime)保留,机制优化(加 lag/vdeadline)。七、调度策略(Scheduling Policy)7.1 三类调度策略策略调度类适合行为SCHED_NORMAL(SCHED_OTHER)CFS/EEVDF普通进程公平调度,nice 加权SCHED_BATCHCFS/EEVDF批处理CPU 密集,少交互,降优先级SCHED_IDLECFS/EEVDF极低优先级只在空闲跑(nice 比所有都低)SCHED_FIFORT实时优先级抢占,无时间片,跑到让/阻塞SCHED_RRRT实时优先级抢占 同优先级轮转SCHED_DEADLINEDL硬实时EDF(最早截止期优先),指定周期/运行时间/截止期7.2 RT 优先级RT 优先级范围 1-99(99 最高)RT 优先级 普通进程(任何 RT 都抢普通)SCHED_FIFO/RR 的优先级 rt_priorityRT 进程能饿死普通进程(全占 CPU)→ 内核有rt_throttling默认让 RT 最多占 95%,留 5% 给普通7.3 chrt 改策略chrt-f80./my_realtime_app# SCHED_FIFO 优先级 80chrt-r50./my_rr_app# SCHED_RR 优先级 50chrt-o0./my_normal_app# SCHED_OTHERchrt-p$(pidof myapp)# 查看策略7.4 SCHED_DEADLINE(硬实时)structsched_attrattr{.sizesizeof(attr),.sched_policySCHED_DEADLINE,.sched_runtime10000000,// 每周期需 10ms.sched_period100000000,// 周期 100ms.sched_deadline20000000,// 截止期 20ms};sched_setattr(0,attr,0);内核保证每 period 内给 runtime,在 deadline 前完成用 EDF 算法调度比 FIFO/RR 更精确的实时保证嵌入式视角:Linux 实时性FreeRTOS 是硬实时(优先级抢占,us 级响应)。Linux 默认(SCHED_NORMAL)不是实时,ms 级延迟。要用 Linux 做实时:SCHED_FIFO/RR:内核抢占,软实时,但可能被中断/驱动阻塞SCHED_DEADLINE:更精确,但仍非硬实时PREEMPT_RT 补丁(主线化中):全内核抢占,接近硬实时Xenomai:双核(Linux 实时核),硬实时边缘 AI/控制若要硬实时,选 PREEMPT_RT 或 Xenomai。八、抢占(Preemption)8.1 抢占点Linux 内核可抢占(CONFIG_PREEMPT),在安全点检查need_resched,调schedule():抢占点何时中断返回内核态IRQ 返回,检查 need_resched系统调用返回syscall 返回用户态前显式 schedule()主动睡眠/阻塞preempt_enable() 后临界区退出互斥锁释放mutex_unlock 后8.2 抢占等级(CONFIG)配置抢占性用途PREEMPT_NONE不抢占(除非阻塞)服务器(吞吐)PREEMPT_VOLUNTARY自愿抢占(显式点)桌面(平衡)PREEMPT全内核抢占低延迟(嵌入式/桌面)PREEMPT_RT实时(几乎全可抢占)硬实时8.3 关抢占 vs 关中断preempt_disable();// 关抢占(本 CPU 不切走)// 临界区(不能睡!)preempt_enable();// 开抢占(检查 need_resched)local_irq_save(flags);// 关中断(本 CPU 中断不来)// 临界区local_irq_restore(flags);spinlock_tlock;spin_lock(lock);// 自旋锁隐含关抢占(SMP) 可能关中断spin_unlock(lock);关抢占:本核不切走,但中断还来(中断里可能 schedule)关中断:中断不来,绝对安静自旋锁:隐含关抢占(07 篇详讲)关抢占/持锁时不能睡眠FreeRTOS 临界区里能调阻塞 API(会切走)。Linux 关抢占/持自旋锁时绝对不能睡眠——睡眠会 schedule(),但你关了抢占,schedule 切不出去,死锁/panic。这是 Linux 比 FreeRTOS 严格的点。能睡的临界区用 mutex(07 篇详讲)。九、fork / exec / wait(进程生命周期)9.1 fork()pid_tpidfork();if(pid0){// 子进程}elseif(pid0){// 父进程}fork()创建子进程,复制父的 task_struct用COW(Copy-On-Write):页表复制,物理页共享,写时才复制(惰性,01 篇哲学)子继承父的 mm/files/signals 副本9.2 exec()execl(/bin/ls,ls,-l,NULL);替换当前进程的代码/数据/堆/栈(丢弃旧 mm,建新 mm)PID 不变,但变成新程序file_operations 保持(打开的 fd 默认保留,除 FD_CLOEXEC 标记的)9.3 wait()pid_tpidwait(status);// 等任一子进程父 wait 收尸子进程子 exit 后变 ZOMBIE,父 wait 才彻底释放父不 wait → 子变僵尸,占 PID;父死了 → init 收养收尸9.4 孤儿进程与僵尸孤儿:父死了,子被 init(PID1)收养,init wait 收尸僵尸:子死了父没 wait,占 PID 和退出码,父 wait 或父死后 init 收尸嵌入式视角:fork 比 FreeRTOS 创建任务重FreeRTOSxTaskCreate立即分配栈和 TCB。Linuxfork用 COW,看似复制 mm,实际只复制页表(快),物理页写时才复制。但 fork 仍比 xTaskCreate 重——要复制 files/signals/页表。所以 Linux 服务器用进程池/线程,不频繁 fork。你写服务别无脑 fork。十、进程关系与会话10.1 进程组 / 会话进程组:相关进程集合(如 pipeline),组 ID PGID会话:进程组集合,会话首控制终端,会话 ID SID用途:信号广播(kill -PGID)、作业控制10.2 守护进程(daemon)// daemon 化典型步骤pidfork();if(pid0)exit(0);// 父退出setsid();// 子建新会话,脱离控制终端fork();// 再 fork,防再获控制终端if(pid0)exit(0);chdir(/);// 改根umask(0);// 关标准 fd,重定向到 /dev/null守护进程:后台运行,无控制终端BSP 启动后台服务常 daemon 化十一、常用进程调试11.1 工具工具看什么ps aux/ps -ef进程列表top/htop实时进程状态/CPUpstree进程树cat /proc/pid/status进程详情(状态/内存/信号)cat /proc/pid/sched调度信息(vruntime/policy)cat /proc/pid/maps地址空间布局cat /proc/pid/stack内核栈(WARNING)strace -p pid跟踪系统调用perf top热点函数chrt/nice/renice改调度策略/优先级11.2 关键 /proc 字段# /proc/pid/status State: R (running) Pid: 1234 PPid: 1 Uid: 0 voluntary_ctxt_switches: 1500 # 主动睡眠切换 nonvoluntary_ctxt_switches: 30 # 被抢占切换voluntary 多 频繁等 IO/睡眠(正常)nonvoluntary 多 频繁被抢占(可能 CPU 紧张)嵌入式视角:Linux 的perf统计任意函数/CPU 周期。/proc/pid/sched看 vruntime 判断进程是否被公平调度。16 篇详讲 perf/ftrace。十二、本篇小结task_struct是宇宙中心,比 FreeRTOS TCB 胖十倍(mm/files/signals/namespace)进程状态:RUNNING/INTERRUPTIBLE/UNINTERRUPTIBLE(D,杀不掉)/ZOMBIE 等Linux 不区分进程线程(都 task_struct,clone flag 控制共享);内核线程无 mm上下文切换context_switch:切页表(switch_mm) 切寄存器(switch_to,只存 callee-saved),对照你 mscratch 切栈是放大版CFS:vruntime 最小优先跑,红黑树,权重由 nice 决定;不会饿死进程但实时性弱EEVDF(6.6):CFS 演进,加 lag/vdeadline,更公平调度策略:SCHED_NORMAL(CFS)/SCHED_FIFO/RR(RT)/SCHED_DEADLINE(硬实时)抢占:关抢占/持自旋锁时不能睡眠(FreeRTOS 临界区能睡,Linux 不能,严格)fork 用 COW(惰性),exec 换程序,wait 收尸;孤儿归 init,僵尸等收尸PREEMPT_RT 补丁让 Linux 接近硬实时速查表想干啥怎么做看进程列表ps aux / top / htop看进程详情cat /proc//status看地址空间cat /proc//maps看调度信息cat /proc//sched改优先级nice -n 10 ./app / renice -n -5 -p PID改调度策略chrt -f 80 ./app创建内核线程kthread_run(fn, arg, “name”)跟踪 syscallstrace -p PID看进程树pstree -p杀进程kill -9 PID(D 状态杀不掉)看僵尸ps aux | grep Z实时性SCHED_FIFO/RR/DEADLINE 或 PREEMPT_RT关抢占preempt_disable(不能睡)睡眠等待TASK_INTERRUPTIBLE(可被信号唤醒)技术之路漫漫分享是为了更好地交流。如果本文的内容对你有启发希望能得到你的点赞 和收藏 ⭐。如果你在调试过程中遇到了其他问题欢迎在评论区 留言我们一起探讨。也欢迎关注 我一起交流底层开发的那些事儿。
返回列表