参考文章

Linux的启动过程

桌面端和嵌入式端的启动过程都遵循以下步骤
过程
这里以嵌入式端Linux启动为例子:

硬件上电与BootROM阶段

系统通电后,CPU首先执行固化在芯片内部的BootROM代码。该阶段完成基础硬件初始化(如时钟、片内RAM),并根据引脚配置确定启动设备(如eMMC、TF卡),随后从设备中加载SPL(Secondary Program Loader)到RAM并执行。

二级引导加载程序(SPL + U-Boot)

SPL:作为轻量级引导程序,负责初始化DDR内存,并将完整的U-Boot加载到内存中。
U-Boot:进一步初始化硬件(如网络、存储设备),加载Linux内核镜像(含内核、设备树、根文件系统)到内存,并传递启动参数。

Linux内核启动

内核解压后,执行以下关键操作:
初始化硬件子系统:包括中断控制器、内存管理、设备驱动等。
挂载根文件系统:通过内核参数确定根文件系统位置(如从存储设备或网络),完成挂载。
启动第一个用户进程:内核调用start_kernel()完成初始化后,启动/sbin/init进程。

用户空间初始化

init进程:读取/etc/inittab配置文件,设置默认运行级别(如多用户模式)。
执行启动脚本:依次运行/etc/init.d/rcS及对应运行级别目录(如rc5.d)中的脚本,完成网络配置、服务启动等。
启动应用程序:最终通过getty或自定义脚本启动用户应用程序。

关键补充说明

硬件初始化分层:BootROM和U-Boot的硬件初始化可能被内核覆盖,内核的初始化是最终生效的。
内核解压方式:嵌入式系统常采用运行时解压以节省存储空间。

#include <ros/ros.h>
#include <sensor_msgs/Image.h>
#include <cv_bridge/cv_bridge.h>
#include <opencv2/opencv.hpp>
#include <image_transport/image_transport.h>
#include <thread>
#include <atomic>

class OpenCVGStreamerNode {
public:
OpenCVGStreamerNode(ros::NodeHandle& nh) : it(nh), running(true) {
// 从参数服务器获取 GStreamer 管道配置
nh.param<std::string>("gstreamer_pipeline", gstreamer_pipeline,
"udpsrc port=5600 caps='application/x-rtp, media=(string)video, clock-rate=(int)90000, encoding-name=(string)H265' ! rtph265depay ! h265parse ! nvv4l2decoder ! nv3dsink -e");
nh.param<std::string>("output_topic", output_topic, "/openipc_camera/image");

// 发布图像话题
image_pub_ = it_.advertise(output_topic, 1);

// 启动图像捕获线程
capture_thread = std::thread(&OpenCVGStreamerNode::captureImages, this);
}

~OpenCVGStreamerNode() {
running = false;
if (capture_thread.joinable()) {
capture_thread.join();
}
}

private:
void captureImages() {
// 使用 GStreamer 管道配置初始化 VideoCapture
cv::VideoCapture cap(gstreamer_pipeline, cv::CAP_GSTREAMER);
if (!cap.isOpened()) {
ROS_ERROR("Failed to open video stream using GStreamer pipeline: %s", gstreamer_pipeline.c_str());
return;
}

cv::Mat frame;
while (running) {
cap >> frame; // 从视频流捕获一帧
if (frame.empty()) {
ROS_WARN("Received empty frame from video stream");
continue;
}

// 将 OpenCV 图像转换为 ROS 图像消息
sensor_msgs::ImagePtr msg = cv_bridge::CvImage(std_msgs::Header(), "bgr8", frame).toImageMsg();
image_pub_.publish(msg);
}
}

image_transport::ImageTransport it_;
image_transport::Publisher image_pub_;
std::string gstreamer_pipeline;
std::string output_topic;
std::thread capture_thread;
std::atomic<bool> running;
};

int main(int argc, char** argv) {
ros::init(argc, argv, "opencv_gstreamer_node");
ros::NodeHandle nh;

// 创建 OpenCV GStreamer 节点
OpenCVGStreamerNode opencv_gstreamer_node(nh);
ros::spin();
return 0;
}