banner
按时间整理的学习笔记。

文章归档

Scroll down
所有归档

一、发布不只是复制文件

很多程序本地能跑,但上线后容易出问题,原因通常不是代码本身,而是发布流程不规范。

一个可靠发布流程要解决:

  • 发布哪个版本。
  • 发布哪些文件。
  • 配置放在哪里。
  • 日志怎么看。
  • 失败怎么回滚。
  • 依赖库是否齐全。
  • 启动和停止是否可控。

一、为什么要规范工程结构

小 demo 可以一个 main.c 加一条 gcc 命令解决,但真实项目会有多个模块、多个库、测试、安装和部署。工程结构不清晰,后期会很难维护。

一个比较常见的 C/C++ 项目结构:

1
2
3
4
5
6
7
8
9
10
11
my_app/
├── CMakeLists.txt
├── include/
│ └── my_app/
│ └── version.h
├── src/
│ ├── main.c
│ └── version.c
├── tests/
│ └── test_version.c
└── README.md

一、为什么要重视内存

Linux 应用运行时间越长,内存问题越容易暴露。短时间测试正常,不代表长期运行稳定。内存泄漏、越界访问、重复释放、use-after-free 都可能导致崩溃、性能下降或系统被 OOM killer 杀死。

常见内存问题:

  • 内存泄漏。
  • 空指针访问。
  • 数组越界。
  • 重复释放。
  • 释放后继续使用。
  • 栈空间不足。
  • 内存碎片。

一、嵌入式调试的层次

嵌入式调试比普通应用复杂,因为问题可能出在硬件、启动链路、内核、驱动、文件系统或应用。

常见调试手段:

  • 串口日志。
  • LED 状态灯。
  • JTAG/SWD。
  • OpenOCD。
  • GDB。
  • gdbserver。
  • 逻辑分析仪。
  • 示波器。

一、RootFS 是什么

RootFS 是根文件系统,是 Linux 用户态运行的基础。内核启动后,必须挂载 RootFS,然后启动第一个用户态进程。

RootFS 里通常包含:

  • Shell。
  • 基础命令。
  • 动态库。
  • 配置文件。
  • 设备节点。
  • 启动脚本。
  • 应用程序。

一、为什么要理解启动流程

嵌入式 Linux 出问题时,经常不是应用代码的问题,而是系统还没正常启动。比如串口没有输出、内核卡住、根文件系统挂载失败、应用没有自启动。

理解启动流程可以帮助你定位问题发生在哪一层:

1
BootROM -> SPL -> U-Boot -> Kernel -> RootFS -> Init -> App

一、为什么要服务化

一个程序能在终端运行,不代表适合部署。真正部署到 Linux 设备或服务器时,需要解决:

  • 开机自动启动。
  • 异常退出自动重启。
  • 统一查看日志。
  • 使用非 root 用户运行。
  • 控制启动顺序。
  • 优雅停止。

Linux 现代发行版通常使用 systemd 管理服务。

一、为什么需要 epoll

阻塞 socket 服务端一次只能等待一个连接或一个读写事件。客户端数量少时问题不大,但连接数变多后,多进程和多线程模型会带来上下文切换、内存占用和调度开销。

Linux 下高并发网络服务常用 epoll

epoll 适合:

  • 大量连接。
  • 多数连接空闲。
  • 事件驱动服务端。
  • 长连接服务。

一、什么是 IPC

IPC 是 Inter-Process Communication,也就是进程间通信。Linux 中每个进程默认有独立地址空间,一个进程不能直接访问另一个进程的内存。如果多个进程需要协作,就需要 IPC。

常见 IPC 方式:

  • 管道 pipe。
  • 命名管道 FIFO。
  • 信号 signal。
  • 共享内存 shared memory。
  • 消息队列 message queue。
  • Unix Domain Socket。
  • TCP/UDP socket。

一、为什么需要设备树

在嵌入式 Linux 中,内核需要知道硬件板子上有什么设备、这些设备接在哪些总线上、使用哪些 GPIO、中断、时钟和寄存器地址。

这些硬件描述不适合全部写死在驱动代码里,所以 Linux 使用设备树描述硬件。

设备树的作用:

  • 描述硬件资源。
  • 把板级差异从驱动中分离出来。
  • 让同一个驱动适配不同板子。
  • 让内核启动时创建设备。
191011121321
请输入关键词进行搜索