4. 进程与线程管理:pidin命令详解、进程状态查看、线程优先级与调度策略
说到QNX的进程线程管理,pidin这个命令,我几乎每天都要用上几十次。它就像系统的听诊器,哪里不对劲,一查便知。今天咱们就把它彻底聊透。
4.1 pidin命令:不只是“看进程”那么简单
很多人以为pidin就是ps的QNX版,其实远不止如此。它能看到的东西,比你想象中多得多。
基础用法,直接敲pidin,你会看到类似这样的输出:
pid tid prio STATE BLOCKED NAME
1 1 10 READY procnto
2 1 10 RECEIVE MsgReceive io-pkt
3 1 10 RECEIVE MsgReceive devc-ser8250
4 1 10 RECEIVE MsgReceive pipe
5 1 10 RECEIVE MsgReceive random
6 1 10 RECEIVE MsgReceive devc-con
每一列都有讲究。pid是进程ID,tid是线程ID,prio是优先级,STATE是当前状态,BLOCKED是阻塞原因,NAME是进程名。
4.2 进程状态:读懂每个进程的“心情”
QNX的进程状态,我把它比作人的几种状态——
| 状态 | 含义 | 像什么 |
|---|---|---|
| READY | 就绪,等待CPU调度 | 排队等公交车 |
| RUNNING | 正在运行 | 正在开车 |
| RECEIVE | 阻塞在接收消息 | 等快递 |
| SEND | 阻塞在发送消息 | 敲门等人开门 |
| REPLY | 阻塞在等待回复 | 发完消息等回信 |
| WAITCTX | 等待上下文 | 等红绿灯 |
| WAITPAGE | 缺页中断 | 翻书找内容 |
| STOPPED | 被暂停 | 被叫停 |
| DEAD | 已死亡 | 凉了 |
我曾经遇到过一个诡异的问题:系统偶尔卡顿,但CPU占用率并不高。用pidin一看,发现有个进程频繁在WAITPAGE和READY之间切换。说白了,就是内存不够,频繁换页。加根内存条,问题就解决了。
4.3 线程优先级:谁先跑,谁后跑
QNX的优先级范围是0到255,数字越大优先级越高。0是空闲线程,255是最高优先级的中断服务线程。
查看线程优先级,用pidin -p 进程名:
# pidin -p my_app
pid tid prio STATE BLOCKED NAME
12345 1 50 RECEIVE MsgReceive my_app
12345 2 45 READY my_app
12345 3 30 RECEIVE MsgReceive my_app
你看,同一个进程的不同线程,优先级可以不一样。这很常见——处理紧急数据的线程给高优先级,后台维护的线程给低优先级。
4.4 调度策略:FIFO、RR还是SPORADIC?
QNX支持三种调度策略,我一个个说。
FIFO(先进先出):同优先级的线程,谁先就绪谁先跑,跑完才让下一个跑。适合计算密集型的任务,比如视频编码。
RR(轮转):同优先级的线程,每个跑一个时间片(默认4毫秒),然后换下一个。适合需要公平调度的场景,比如多个用户交互。
SPORADIC(零星调度):这是QNX的特色。给线程一个“预算”,预算用完了就降级到低优先级运行。适合偶发性的高优先级任务,比如按键响应。
查看线程的调度策略,用pidin -m:
# pidin -m
pid tid prio policy NAME
1 1 10 FIFO procnto
2 1 10 RR io-pkt
3 1 10 FIFO devc-ser8250
我个人的经验是:中断处理线程用FIFO,普通应用线程用RR,不确定的用SPORADIC。SPORADIC是个好东西,但很多人不会用,可惜了。
4.5 实战:用pidin定位性能瓶颈
光说不练假把式。咱们来一个真实场景。
假设系统反应迟钝,你怀疑是某个线程占用了太多CPU。怎么做?
第一步,看整体:
pidin -p all -F "%p %c %a"
这个命令会显示每个进程的CPU占用率。找到占用最高的那个进程。
第二步,看线程:
pidin -p 高占用进程ID -t -F "%t %p %c %a"
找到具体是哪个线程在吃CPU。
第三步,看调度:
pidin -p 高占用进程ID -m
看看这个线程的优先级和调度策略是否合理。
避坑指南: 我曾经遇到一个案例,一个线程的优先级设成了200,但它其实只是个日志记录线程。结果每次它一跑,其他所有线程都得等着。把优先级降到50,系统瞬间流畅了。所以,优先级不是越高越好,够用就行。
4.6 动态调整:不用重启也能改
QNX允许你在运行时调整线程的优先级和调度策略。用pidin配合sched_setscheduler或者chrt命令。
比如,把线程12345的优先级从50改成80:
chrt -p 80 12345
或者用C代码:
#include <sys/sched.h>
struct sched_param param;
param.sched_priority = 80;
sched_setscheduler(0, SCHED_RR, ¶m);
嗯,这里要注意:改优先级要谨慎。你想想看,如果把一个普通线程的优先级改得比系统服务还高,那系统服务可能就得不到及时响应了。
4.7 总结一下
pidin这个工具,说简单也简单,说复杂也复杂。关键是你要知道看什么、怎么看。
- 看状态:READY多说明CPU忙,RECEIVE多说明系统闲
- 看优先级:255是最高,0是最低,别乱设
- 看调度策略:FIFO适合中断,RR适合普通任务,SPORADIC适合偶发任务
- 动态调整:用chrt或sched_setscheduler,但别手滑
我个人习惯是,每次调试新系统,第一件事就是跑一遍pidin -p all -F "%p %c %a",看看各个进程的CPU占用。这就像医生看病先量体温一样,基础但有效。
好了,这一章就到这里。下一章咱们聊聊内存管理,那又是一个大坑。