跳转至

操作系统基础

概述

操作系统(OS)是机器人软件栈的基础层,负责管理硬件资源、调度任务和提供编程接口。在机器人领域,Linux是主控平台的首选操作系统,而实时扩展则是满足控制需求的关键。

进程与线程

进程(Process)

进程是操作系统资源分配的基本单位:

属性 说明
地址空间 独立的虚拟地址空间
资源 拥有独立的文件描述符、内存映射等
隔离性 进程间相互隔离,一个崩溃不影响其他
开销 创建和切换开销较大
通信 需要IPC(管道、共享内存、套接字等)

线程(Thread)

线程是CPU调度的基本单位:

属性 说明
地址空间 共享所属进程的地址空间
资源 共享进程资源(文件、内存)
独立 拥有独立的栈、寄存器、程序计数器
开销 创建和切换开销较小
通信 可直接读写共享变量(需同步)

在ROS2中的体现

ROS2 节点模型:
├── 节点(Node) = 进程(默认)或线程(组件模式)
├── 进程模式: 每个节点独立进程,隔离性好
│   $ ros2 run perception camera_node
│   $ ros2 run navigation planner_node
└── 组件模式: 多个节点共享一个进程,通信开销低
    $ ros2 run rclcpp_components component_container

ROS2最佳实践

  • 使用组件(Component)模式减少节点间通信开销
  • 在同一进程内的节点可以使用零拷贝(intra-process communication)
  • 计算密集型节点放在独立进程中,避免影响其他节点

调度算法

Linux调度器

Linux使用CFS(Completely Fair Scheduler)作为默认调度器:

调度类 策略 优先级 用途
SCHED_DEADLINE EDF(最早截止期限优先) 最高 硬实时任务
SCHED_FIFO 先进先出实时调度 高(1-99) 实时任务
SCHED_RR 时间片轮转实时调度 高(1-99) 实时任务
SCHED_OTHER CFS公平调度 普通(nice值) 普通任务
SCHED_IDLE 空闲时才运行 最低 后台任务

实时调度设置

# 查看进程的调度策略和优先级
chrt -p <pid>

# 设置进程为SCHED_FIFO,优先级80
sudo chrt -f -p 80 <pid>

# 启动时指定调度策略
sudo chrt -f 80 ./motor_control_node

# 设置CPU亲和性(绑定到特定核心)
taskset -c 3 ./motor_control_node
# Python中设置线程优先级
import os
import ctypes

# 设置实时调度
SCHED_FIFO = 1
param = ctypes.c_int(80)
libc = ctypes.CDLL('libc.so.6')

class sched_param(ctypes.Structure):
    _fields_ = [('sched_priority', ctypes.c_int)]

sp = sched_param(80)
libc.sched_setscheduler(0, SCHED_FIFO, ctypes.byref(sp))

调度延迟

\[ t_{\text{response}} = t_{\text{interrupt}} + t_{\text{schedule}} + t_{\text{context\_switch}} + t_{\text{execution}} \]
系统 典型调度延迟 最坏情况
标准Linux ~100μs ~10ms
PREEMPT_RT Linux ~10μs ~100μs
FreeRTOS <1μs ~10μs
裸机 <100ns ~1μs

Linux内核架构

内核子系统

graph TB
    subgraph 用户空间
        APP[应用程序<br>ROS2节点]
        LIB[C库 glibc]
    end

    subgraph 内核空间
        SCI[系统调用接口<br>System Call Interface]

        subgraph 核心子系统
            PM[进程管理<br>Process Management]
            MM[内存管理<br>Memory Management]
            VFS[虚拟文件系统<br>VFS]
            NET[网络子系统<br>Network Stack]
            IPC_K[进程间通信<br>IPC]
        end

        DD[设备驱动<br>Device Drivers]
        HAL_K[硬件抽象层<br>HAL]
    end

    APP --> LIB
    LIB --> SCI
    SCI --> PM
    SCI --> MM
    SCI --> VFS
    SCI --> NET
    SCI --> IPC_K
    PM --> DD
    MM --> DD
    VFS --> DD
    DD --> HAL_K

内核模块

Linux内核是模块化的,驱动可以动态加载:

# 查看已加载的内核模块
lsmod

# 加载模块
sudo modprobe v4l2_common   # V4L2视频驱动
sudo modprobe can_raw        # CAN总线原始套接字

# 卸载模块
sudo rmmod can_raw

# 查看模块信息
modinfo nvidia   # NVIDIA GPU驱动信息

设备驱动

设备类型

类型 接口 示例 访问方式
字符设备 流式读写 串口、IMU、GPIO /dev/ttyUSB0
块设备 随机读写 SSD、eMMC /dev/sda
网络设备 套接字 以太网、WiFi eth0, wlan0

/dev 设备文件

# 机器人常用设备文件
/dev/ttyUSB0     # USB串口(MCU通信)
/dev/ttyTHS0     # Jetson原生串口
/dev/video0      # USB相机(V4L2)
/dev/i2c-1       # I2C总线
/dev/spidev0.0   # SPI设备
/dev/can0        # CAN总线
/dev/input/js0   # 游戏手柄
/dev/nvme0n1     # NVMe SSD

sysfs文件系统

sysfs提供内核对象的用户空间接口:

# GPIO控制
echo 17 > /sys/class/gpio/export
echo out > /sys/class/gpio/gpio17/direction
echo 1 > /sys/class/gpio/gpio17/value

# 查看CPU温度
cat /sys/class/thermal/thermal_zone0/temp
# 输出: 45000 (表示45.000°C)

# 查看CPU频率
cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq
# 输出: 2400000 (表示2.4GHz)

# 设置Jetson功耗模式
sudo nvpmodel -m 0  # 最大性能
sudo nvpmodel -m 1  # 15W模式

# 查看GPU利用率(Jetson)
cat /sys/devices/gpu.0/load

V4L2相机驱动

# 列出视频设备
v4l2-ctl --list-devices

# 查看相机支持的格式
v4l2-ctl -d /dev/video0 --list-formats-ext

# 设置相机参数
v4l2-ctl -d /dev/video0 \
    --set-fmt-video=width=1920,height=1080,pixelformat=MJPG \
    --set-parm=30  # 30fps
# Python读取V4L2相机
import cv2

cap = cv2.VideoCapture(0, cv2.CAP_V4L2)
cap.set(cv2.CAP_PROP_FRAME_WIDTH, 1920)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 1080)
cap.set(cv2.CAP_PROP_FPS, 30)

while True:
    ret, frame = cap.read()
    if ret:
        # 处理帧
        process_frame(frame)

实时补丁(PREEMPT_RT)

为什么需要实时Linux

标准Linux内核的问题:

  • 内核代码段不可抢占(长时间持有锁)
  • 中断处理在硬中断上下文中执行
  • 调度延迟不确定(偶尔出现ms级延迟尖峰)

PREEMPT_RT关键改进

改进 说明 效果
完全可抢占内核 几乎所有内核代码可被抢占 降低调度延迟
中断线程化 硬中断转为内核线程 可以被高优先级任务抢占
自旋锁→互斥锁 改为可休眠的锁 减少不可抢占时间
高精度定时器 hrtimer替代jiffies ns级定时精度

安装和配置

# Ubuntu上安装RT内核
sudo apt install linux-image-rt-amd64  # x86
# 或编译自定义RT内核(Jetson)
# 下载NVIDIA的L4T源码,应用PREEMPT_RT补丁

# 验证RT内核
uname -a
# 输出应包含 "PREEMPT_RT"

# 测试实时性能
sudo cyclictest -p 80 -t 4 -n -m -l 1000000
# -p 80: 优先级80
# -t 4: 4个线程
# -n: 使用nanosleep
# -m: 锁定内存
# 结果: Min/Avg/Max 延迟(μs)

实时性能调优

# 1. 隔离CPU核心给实时任务
# 在/boot/cmdline.txt中添加:
isolcpus=2,3 nohz_full=2,3 rcu_nocbs=2,3

# 2. 禁用CPU频率调节
echo performance | sudo tee /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor

# 3. 锁定内存(防止页面交换)
# 在程序中:
mlockall(MCL_CURRENT | MCL_FUTURE);

# 4. 设置实时线程优先级
# 在ROS2中:
# ros2 run --prefix "chrt -f 80" my_package my_node

启动过程

Linux启动流程

graph LR
    A[上电] --> B[Bootloader<br>U-Boot/UEFI]
    B --> C[内核加载<br>vmlinuz]
    C --> D[initramfs<br>临时根文件系统]
    D --> E[init/systemd<br>PID 1]
    E --> F[系统服务启动]
    F --> G[用户空间就绪]

机器人自启动配置

# 使用systemd创建开机自启服务
sudo tee /etc/systemd/system/robot.service << 'EOF'
[Unit]
Description=Robot ROS2 Launch
After=network.target

[Service]
Type=simple
User=robot
WorkingDirectory=/home/robot/ros2_ws
ExecStart=/bin/bash -c "source install/setup.bash && ros2 launch robot_bringup robot.launch.py"
Restart=always
RestartSec=5

# 实时优先级设置
Nice=-10
CPUSchedulingPolicy=fifo
CPUSchedulingPriority=50

[Install]
WantedBy=multi-user.target
EOF

sudo systemctl enable robot.service
sudo systemctl start robot.service

启动时间优化

优化方法 节省时间 说明
精简initramfs 2-5s 只保留必要驱动
并行启动服务 3-10s systemd并行化
禁用不必要服务 2-5s 关闭蓝牙、打印等
压缩内核 1-2s 使用LZ4压缩
使用轻量级发行版 5-10s Ubuntu Core

IPC(进程间通信)

Linux IPC机制

机制 延迟 吞吐量 适用场景
管道(Pipe) 父子进程通信
消息队列 结构化消息传递
共享内存 大量数据共享
信号(Signal) 简单通知
Unix Socket 本地进程通信
TCP/UDP Socket 跨机器通信

ROS2 DDS通信

ROS2使用DDS(Data Distribution Service)作为通信中间件:

ROS2 DDS通信栈:
├── 同一进程内: 零拷贝(指针传递)
├── 同一主机: 共享内存(Fast-DDS SHM transport)
└── 跨主机: UDP多播

参见:实时系统 了解更多关于实时部署的内容。

常用Linux命令

系统监控

# CPU和内存使用
htop                    # 交互式进程监控
top -H -p <pid>         # 查看进程的线程

# 系统资源
free -h                 # 内存使用
df -h                   # 磁盘使用
nvidia-smi              # GPU使用(Jetson用jtop)
sudo jtop               # Jetson系统监控

# 实时性分析
trace-cmd record -p function_graph -l schedule
kernelshark             # 图形化内核跟踪分析

性能分析

# CPU性能分析
sudo perf record -g ./robot_node
sudo perf report

# 系统调用跟踪
strace -f -e trace=read,write ./robot_node

# I/O分析
iostat -x 1             # I/O统计
iotop                   # I/O进程监控

小结

  1. 进程提供隔离线程提供并发,ROS2组件模式是最佳实践
  2. Linux CFS适合一般任务,SCHED_FIFO用于实时控制
  3. 设备驱动通过/devsysfs提供用户空间接口
  4. PREEMPT_RT将Linux最坏延迟从~10ms降低到~100μs
  5. systemd管理机器人服务的自启动
  6. 合理使用CPU隔离内存锁定提升实时性能

参考资料


评论 #