1、ps、top、htop分别干什么?
先记这个区别:
ps = 看“当前这一刻”的进程快照 top = 实时刷新系统进程状态 htop = 更友好的交互式 top所以:
想快速查一个进程有没有启动 → ps 想持续观察 CPU / 内存 → top 想更方便地看线程、排序、搜索 → htopps aux
常见列:
USER PID %CPU %MEM VSZ RSS STAT START COMMAND你不用全背。
现阶段重点:
PID %CPU %MEM RSS STAT COMMANDR = running / runnableS = sleepingD = uninterruptible sleepT = stoppedZ = zombie如果一个网络接收线程对应的进程大多数时间:
S很正常。
因为它可能正在:
recv poll epoll_wait condition_variable等待事件。
zombie
僵尸进程:
Z不是说进程还在正常执行。
而是:
子进程已经退出,但父进程还没有回收它的退出状态。
可以理解:
child 已经死了 ↓ 内核还保留一小份退出信息 ↓ parent 还没 wait()所以 zombie:
通常不占大量 CPU / 内存但如果大量出现:
说明父进程的子进程管理有问题运行:
top通常上面会看到:
load average Tasks CPU Memory Swap下面是进程列表。
你现阶段优先看:
%CPU %MEM RES PID COMMAND比如:
PID %CPU %MEM RES COMMAND 4321 98.5 2.1 300M gmr_node 4500 3.0 1.0 120M robot_output那第一反应:
gmr_node 明显是 CPU 热点然后继续查:
线程 函数如果只关心一个进程:
top -p 4321这样界面干净很多。
特别适合现场:
只盯 robot_controltop -H -p 4321意思:
看这个进程里的线程。
例如:
TID %CPU 4321 5% 4322 95% 4323 1% 4324 3%马上知道:
线程 4322最忙。
然后下一步可以:
perf gdb strace继续看它在干什么。
这就是你之前 perf 那节的链路:
进程高 ↓ top -H ↓ 线程高 ↓ perf ↓ 函数高某线程 100%往往意味着:
这个线程几乎一直在执行,没有怎么阻塞。
如果它本来应该:
等待 UDP结果却 100%,就很可疑。
可能是:
busy loop EAGAIN 重试 轮询错误 while(true)htop的价值
htop比top更友好。
运行:
htop一般可以:
搜索进程 按 CPU 排序 按内存排序 展开线程 树状查看父子关系对初学者很适合。
比如你可以更直观看:
ros2 launch ├── node_a ├── node_b └── node_c这种父子关系。
ps 看线程
例如:
ps -T -p 4321或者:
ps -L -p 4321可以看到线程。
如果想更详细:
ps -L -p 4321 -o pid,tid,psr,pcpu,stat,comm其中:
tid = 线程 IDpsr = 当前/最近运行在哪个 CPU 上pcpu = CPU 占用这会和后面的:
CPU affinity直接连接。
怎么知道进程什么时候启动?
可以:
ps -o pid,lstart,etime,cmd -p 4321其中:
lstart = 启动时间etime = 已运行多久这很适合排查:
程序是不是刚刚自动重启过?例如你以为它运行 8 小时,
结果:
etime = 00:02:15说明:
2 分钟前刚重启那就要继续查:
systemd 崩溃 watchdog查看 CPU 核数?
简单:
nproc例如:
8说明有 8 个逻辑 CPU。
也可以:
lscpu看更详细信息。
查看进程树
常用:
pstree -p你可能看到:
systemd(1) └─ros2(3000) ├─mocap_node(3100) ├─gmr_node(3101) └─robot_output(3102)这对 ROS2 launch/systemd 服务排查非常直观。
pgrep -a robot_control找到 PID。
然后:
ps -o pid,ppid,etime,stat,%cpu,%mem,rss,args -p PID一次看:
PID 父进程 运行时间 状态 CPU 内存 完整启动参数这个非常适合机器人现场。
只看网络相关系统调用
strace -e trace=network -p 4321这样重点看:
socket bind connect accept send recv只看文件系统调用
例如配置文件加载失败:
strace -e trace=file ./robot_control你可能看到:
openat(..., "/etc/robot/config.yaml", ...) = -1 ENOENT这说明:
No such file or directory可能程序其实在错误目录找配置。
这类问题非常常见。
futex
你以后 strace 非常容易看到:
futex(...)先不要怕。
它和:
mutex condition_variable 线程同步密切相关。
可以粗略理解:
Linux 用户态线程在等待锁或条件变化时,底层经常会使用 futex。
所以如果程序卡住,多个线程都:
futex(... FUTEX_WAIT ...)你应该开始怀疑:
是不是在等 mutex / condition_variable甚至可能:
deadlock-T特别适合看谁卡得久
例如:
recvfrom(...) <0.000012> openat(...) <0.000030> connect(...) <10.001234>一看:
connect花了 10 秒。
所以:
strace 不只是看“调用了什么”,还能帮助看“系统调用卡了多久”。
保存 strace 日志
例如:
strace -o trace.log -p 4321日志保存到:
trace.log现场问题特别适合。
还可以:
strace -ff -o trace -p 4321多线程/子进程场景会生成多个 trace 文件。
现在知道即可。
程序崩了 → gdb / core dump程序卡了 → strace + gdbCPU高 → top -H + perf内存涨 → RSS + ASan/Valgrind系统调用异常 → strace线程竞争 → TSan这就是你现在的完整排障工具链。
2、systemd
systemd = Linux 上用来管理系统服务和进程生命周期的服务管理器。
它能帮你做:
开机自启 ↓ 启动程序 ↓ 监控是否退出 ↓ 异常时自动重启 ↓ 统一日志 ↓ 正常 stop ↓ 管理依赖关系所以机器人上的:
robot_driver controller diagnostics network_bridge很适合交给 systemd 管。
& = shell后台运行而:
systemd = 服务生命周期管理完全不是一个层级。
假设文件放在:
/etc/systemd/system/robot_control.service然后:
sudo systemctl daemon-reload告诉 systemd:
unit 文件更新了,重新加载。
启动:
sudo systemctl start robot_control查看:
systemctl status robot_control停止:
sudo systemctl stop robot_control重启:
sudo systemctl restart robot_control这几个非常常用。
Type=simple
先简单理解:
systemd 认为
ExecStart启动的进程就是服务主进程。
对于很多普通机器人程序:
Type=simple已经够用。
以后还会看到:
notify forking oneshot现在不用展开。
对于:
Type=simplesystemd 直接跟踪:
ExecStart启动的进程。
所以:
systemctl status robot_control能看到:
Main PID这也是为什么前面说:
启动脚本里使用 exec会让进程关系更干净。
3、Linux
Linux 权限决定“哪个用户/进程,可以对哪个资源做什么”。
dialout 组
sudo usermod -aG dialout $USER意思:
把当前用户加入
dialout组。
之后重新登录,让组信息生效。
再:
groups确认有:
dialout这时候你的进程就可以:
以普通用户身份 ↓ 访问 /dev/ttyUSB0比:
sudo ./robot_driver更合理。
udev
udev = Linux 用来管理设备节点和设备事件的一套机制。
比如你插入 USB 串口:
USB 设备插入 ↓ Linux 内核识别 ↓ udev 处理 ↓ 创建 /dev/ttyUSB0 ↓ 设置 owner / group / mode ↓ 甚至创建稳定别名所以:
/dev/ttyUSB0不是你手工创建的。
很多时候是:
udev帮你创建和配置。
udev rule 是一组规则:
当某种设备出现时,应该怎么命名、怎么设权限、属于哪个组。
规则一般放在:
/etc/udev/rules.d/例如:
99-robot.rules为什么 udev 比 chmod 更适合工程部署?
因为:
插拔设备 ↓ udev 自动匹配 ↓ 自动应用权限你不需要每次:
sudo chmod ...所以:
chmod = 临时人工操作而:
udev rule = 可重复、可部署、自动化配置这就是工程上的区别。
怎么查 USB 设备的 Vendor/Product ID?
最常用:
lsusb例如:
Bus 001 Device 005: ID 0403:6015 Future Technology Devices...这里:
0403是 vendor ID。
6015是 product ID。
这类信息可以用于写 udev rule。
udevadm info
比如:
udevadm info -a -n /dev/ttyUSB0它会输出设备属性。
你可以找到:
idVendor idProduct serial manufacturer然后选择稳定属性写规则。
udev rule 改完怎么生效?
常见:
sudo udevadm control --reload-rules然后:
sudo udevadm trigger或者直接重新插拔设备。
再:
ls -l /dev/robot_imu确认规则是否生效。如果规则没生效怎么查?
可以:
udevadm info -a -n /dev/ttyUSB0确认你匹配的属性到底在哪一层。
因为:
ATTR和:
ATTRS含义有差别。
现阶段不需要钻语法细节。
你先建立排障流程:
设备存在吗? ↓ ls -l 权限是什么? ↓ udevadm info 看属性 ↓ rule 是否匹配? ↓ reload ↓ 重新插拔capability
Linux 不只有:
普通用户 root两档。
还可以把 root 的能力拆成很多:
capabilities比如:
CAP_NET_ADMIN CAP_SYS_NICE CAP_IPC_LOCK这些以后实时控制也会碰到。
例如:
SCHED_FIFO高实时优先级可能需要:
CAP_SYS_NICEmlockall某些配置下可能涉及:
MEMLOCK limit网络接口配置可能涉及:
CAP_NET_ADMIN所以:
能力可以细分授权,而不是所有事都 sudo root。
目录权限里的 x 是什么意思?
这里很容易踩坑。
对普通文件:
x一般是:
execute但对目录:
x更接近:
允许进入/穿过这个目录。
例如:
/home/robot/config/即使:
robot.yaml本身可读,
但上级目录没有执行权限:
程序还是可能打不开所以权限问题不能只看目标文件。
udev 还能做什么?
除了:
设置权限 创建 symlink它还可以:
根据设备插拔触发规则 设置属性 设备命名不过机器人项目里你现阶段最重要的是:
稳定命名 + 访问权限这两个
4、权限
ip addr:先看网卡和 IP
最常用:
ip addr或者:
ip a你会看到类似:
2: enp3s0: inet 192.168.1.10/24这里:
enp3s0 = 网卡接口名 192.168.1.10 = IP /24 = 子网前缀机器人现场第一步经常就是:
目标网卡到底有没有正确 IP?
ip link:看网卡是不是 UP
执行:
ip link可能看到:
enp3s0: <BROADCAST,MULTICAST,UP,LOWER_UP>重点:
UP表示接口被启用。
LOWER_UP通常说明物理链路也起来了。
如果没有:
LOWER_UP你就要怀疑:
网线 交换机 网口 设备供电而不是先查应用程序。
手工启用网卡
例如:
sudo ip link set enp3s0 up关闭:
sudo ip link set enp3s0 down这只是接口状态控制。
不是配置 IP。
临时设置静态 IP
例如:
sudo ip addr add 192.168.1.10/24 dev enp3s0注意这是:
临时配置重启后通常不会永久保留。
生产系统一般用:
NetworkManager netplan systemd-networkd等做持久配置。
ping到底验证了什么?
例如:
ping 192.168.1.20如果通:
说明 IP 层基本可达但注意:
ping 通 ≠ UDP/TCP 应用一定正常。
因为 ping 用的是:
ICMP不是:
TCP UDP所以只能说明:
网络路径大体可达不能证明:
你的端口打开 程序在监听 防火墙没拦 UDP 应用协议正确为什么 ping 不通,也不一定说明完全不通?
有些设备或防火墙:
禁止 ICMP但:
TCP/UDP 业务端口仍然正常所以:
ping只是网络排查工具之一。
不能作为唯一判断。
ss:查端口最重要
你前面已经见过:
ss -ltnp看 TCP 监听。
拆开:
-l = listening -t = TCP -n = 不解析名字 -p = 显示进程例如:
LISTEN 0 128 0.0.0.0:5555 users:(("robot_server",pid=4321,fd=8))说明:
robot_server PID 4321 fd 8 正在监听 TCP 5555ss -lunp其中:
-u = UDP比如:
0.0.0.0:7014说明程序已经 bind 7014。
这对你的动捕 UDP 排障特别关键。
0.0.0.0是什么意思?
如果服务绑定:
0.0.0.0:7014一般表示:
接受本机多个 IPv4 接口上发到 7014 的流量。
如果绑定:
192.168.1.10:7014那通常只监听这个地址。
所以:
bind 地址也是通信是否正常的重要因素。
127.0.0.1是什么意思?
127.0.0.1是:
localhost 回环地址如果服务只绑定:
127.0.0.1:5555那么:
本机程序可以访问 远端机器通常访问不了这是一个非常常见的配置问题。
TCP 怎么简单测端口?
如果你想确认:
192.168.1.20:5555能不能建立 TCP 连接,可以用:
nc -vz 192.168.1.20 5555成功可能看到:
succeeded这说明:
TCP 路径和服务监听基本正常UDP 为什么不能像 TCP 那么简单验证?
因为 UDP:
没有连接建立过程你发一个包:
不一定有回应所以:
“我 sendto 成功了”只能说明:
本地内核接受了这个数据发送请求。
不代表:
对端一定收到了这就是 UDP 排查为什么更依赖抓包和应用层统计。
ethtool
例如:
sudo ethtool enp3s0可以看:
Link detected Speed Duplex Auto-negotiation例如:
Speed: 1000Mb/s Duplex: Full Link detected: yes对于机器人有线网络很实用。
Full Duplex
简单理解:
Full Duplex = 可以同时收和发现代以太网通常都是全双工。
如果协商异常:
速度或双工不一致可能导致:
大量重传 吞吐下降 奇怪网络问题比如服务:
机器人电脑 192.168.1.10如果你在本机测试:
nc 127.0.0.1 5555成功。
不能证明:
远端 192.168.1.20也能连接。
还需要测试:
nc 192.168.1.10 5555并从另一台机器实际测试。
一个典型 UDP 动捕排障流程
假设:
动捕发送端 → 192.168.10.20:7014你的机器人:
应该接收第一步:
ip addr确认机器人网卡是不是:
192.168.10.x/24第二步:
ip link确认:
UP LOWER_UP第三步:
ss -lunp确认:
7014真的被你的进程 bind。
第四步:
strace -e trace=network -p PID看:
recvfrom有没有数据返回。
这样就能逐层缩小问题。
TCPConnection refused
例如:
connect(...) → Connection refused通常意味着:
目标 IP 可达 但目标端口上没有服务监听或者明确被拒绝。
这和:
Connection timed out不一样。
设备网络 → EtherCAT / CAN / UDP 传感器 机器人内部通信 → ROS2 / ZMQ 外部网络 → SSH / Wi-Fi / 调试 / 远程监控