参考文章
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 ) { 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 () { 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 ; } 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; OpenCVGStreamerNode opencv_gstreamer_node (nh) ; ros::spin (); return 0 ; }