嵌入式驱动开发 Linux/C 核心知识点汇总含内核、驱动、网络、并发本文汇总了Linux操作系统、C/C编程、内核驱动、网络通信、并发编程等核心知识点梳理清晰、重点突出适合嵌入式、后端开发人员查阅和复习内容涵盖基础概念、实操要点及常见问题解决方案。一、内存管理堆与栈1.1 栈Stack默认大小Linux下默认8MBWindows下默认1MB数据结构遵循“后进先出LIFO”原则用途存储局部变量、函数参数、返回地址等管理方式操作系统自动管理无需手动操作响应速度快缺点空间有限生命周期与函数作用域绑定函数执行结束后自动释放栈溢出原因递归过深、局部变量过大解决方案限制递归层数、优化数据结构、改用堆内存1.2 堆Heap管理方式手动管理需动态分配如malloc、new和手动释放如free、delete分配方向由操作系统运行库函数实现从低地址向高地址分配缺点分配/释放速度慢容易造成内存泄漏、内存碎片化1.3 堆与栈的存储与运用对比堆存储动态分配的对象、大型数据结构动态数组、链表、树从低到高生长栈存储局部变量、函数参数由高到低生长二、进程通信IPC2.1 管道Pipe2.1.1 匿名管道适用场景仅用于具有亲属关系父子、兄弟的进程间通信结构由一对文件描述符组成一端写入、一端读取通信方式单向管道半双工通信同一时刻只能单向传输2.1.2 命名管道适用场景用于无亲属关系的进程间通信创建方式使用mkfifo()或mknod()系统调用创建通信方式支持双向通信全双工通信2.2 信号Signal本质软件中断用于通知进程发生某个特定事件如异常、用户指令使用进程可以捕获信号并自定义信号处理函数也可选择忽略、默认处理2.3 消息队列功能允许进程之间发送和接收消息实现数据传递特点消息具有独立性可按类型、优先级处理无需进程同步等待2.4 共享内存地位最快的IPC机制无需数据拷贝原理多个进程共享同一个内存段直接读写该内存段的数据注意需配合同步机制信号量、互斥锁、条件变量避免数据竞争2.5 套接字Socket通信方式提供双向通信支持全双工适用场景既支持同一主机内进程间通信也支持不同主机间进程通信特性支持TCP、UDP等多种协议是客户端-服务端架构的核心通信方式2.6 文件映射原理将磁盘文件映射到进程的地址空间通过内存操作直接读写文件内容用途实现进程间通信共享映射文件也可提升文件读写效率2.7 消息队列与管道的对比对比维度消息队列管道适用进程不相关进程、亲属进程均可主要用于亲属进程数据保留消息读取后仍保留需显式删除数据读取后立即消失数据大小可存储更多数据限制宽松有明确大小限制消息管理支持按类型、优先级选择性接收只能默认顺序接收持久性随内核持续进程终止后仍可访问进程终止后数据丢失补充消息队列通常与信号量、互斥锁结合使用确保数据一致性和互斥访问更适用于复杂消息传递、多进程大量数据传输、需要高级消息管理的场景。三、Linux进程相关3.1 进程类型3.1.1 守护进程特点在后台运行不与任何终端或shell会话关联生命周期系统启动时开始运行直至系统关闭用途执行系统任务、提供后台服务如httpd、sshd3.1.2 僵尸进程定义已完成执行但父进程未获取其退出状态的进程特性进程控制块PCB仍存在仅占用PCB资源不占用其他系统资源解决方案父进程调用wait()或waitpid()获取退出状态父进程终止后僵尸进程会被init进程收养并清理3.1.3 孤儿进程定义父进程先于子进程退出子进程会被祖进程通常是init进程收养特性被收养后由收养进程负责回收其资源不会变成僵尸进程3.1.4 普通用户进程与内核进程用户进程运行在用户态权限低不能直接操作内核资源需通过系统调用请求服务内核进程运行在内核态权限高负责管理系统资源如进程调度、内存分配3.2 程序执行过程用户通过命令行或图形界面请求执行某个程序当前进程调用fork()系统调用创建子进程子进程复制父进程的资源子进程调用execve()系统调用加载并执行指定的ELF文件替换子进程的代码和数据操作系统解析ELF文件的程序头将各段代码段、数据段等加载到内存动态链接器加载程序所需的动态链接库.so文件从入口点_start跳转到main()函数开始执行用户代码如计算、I/O操作程序执行过程中通过系统调用如read、write请求操作系统服务main()函数返回或调用exit()时程序终止操作系统清理程序占用的资源程序返回退出状态给父进程父进程处理子进程退出状态后继续执行四、远程通信序列化与反序列化4.1 序列化定义将内存中的数据结构或对象状态转换为可存储如文件或可传输如网络字节流的格式核心作用允许进程将内存中的数据通过网络或存储介质传递给其他进程/设备注意事项需处理字节序大端、小端确保不同设备/进程间的数据兼容性4.2 反序列化定义序列化的逆过程将接收到的字节流或存储的格式重新转换为原始的数据结构或对象状态核心要求需与序列化格式完全匹配否则会导致数据解析错误五、SDK开发静态库与动态库5.1 静态库后缀Linux下为.aWindows下为.lib特点编译时被直接链接到目标程序中成为程序的一部分优点代码直接嵌入程序无需额外加载响应快、性能好不依赖外部库文件兼容性好简化部署缺点程序体积大包含静态库代码更新静态库需重新编译整个程序更新困难多个程序使用同一静态库会造成内存浪费重复加载5.2 动态库后缀Linux下为.soWindows下为.dll特点运行时才被加载和链接不嵌入程序本身多个程序可共享同一动态库优点节省磁盘空间和内存共享加载易于更新替换动态库文件即可无需重新编译程序内存高效缺点部署复杂需确保目标环境存在对应的动态库可能出现库不存在、版本不兼容问题运行时加载需额外开销性能略低于静态库六、Socket编程6.1 Socket编程效率提升方法缓冲区优化合理设置接收和发送缓冲区大小匹配读写操作的数据量减少缓冲区溢出或空读非阻塞模式将TCP Socket设置为非阻塞模式读取操作立即返回不阻塞等待提高系统并发处理能力多路复用使用I/O多路复用机制select、poll、epoll同时监控多个TCP Socket减少系统调用次数提升效率批量操作使用readv/recvmsg进行批量读取writev/sendv进行批量发送一次处理多个缓冲区数据减少系统调用零拷贝技术使用sendfile等零拷贝函数数据直接从内核缓冲区拷贝到用户空间或网络接口避免数据多次拷贝减少系统调用开销6.2 TCP服务器Socket编程流程创建套接字调用socket()函数创建TCP套接字SOCK_STREAM绑定地址调用bind()函数将服务器的IP地址和端口号绑定到套接字上监听连接调用listen()函数设置服务器同一时刻允许接收的最大连接请求数等待连接调用accept()函数阻塞函数等待客户端连接连接成功后返回客户端套接字收发数据通过send()函数发送数据recv()函数接收客户端数据关闭套接字通信结束后调用close()函数关闭客户端套接字和服务器套接字6.3 TCP客户端Socket编程流程创建套接字调用socket()函数创建TCP套接字连接服务器调用connect()函数指定服务器的IP地址和端口号建立连接收发数据通过send()函数向服务器发送数据recv()函数接收服务器返回的数据关闭套接字通信结束后调用close()函数关闭客户端套接字6.4 多路I/O复用核心作用同时监控多个文件描述符如Socket、管道一旦某个描述符发生变化如可读、可写立即执行对应操作提升并发处理能力6.4.1 epollLinux常用头文件sys/epoll.h核心操作epoll_create创建epoll句柄用于管理监控的文件描述符epoll_ctl注册、修改、删除需要监控的事件如EPOLLIN、EPOLLOUTepoll_wait等待监控的事件发生返回发生变化的文件描述符6.4.2 poll特点与select功能类似但没有最大连接数限制select默认最大1024个适用场景连接数较多的场景但效率略低于epoll6.4.3 select特点轮询所有监控的文件描述符调用一次只能监控一组描述符效率较低核心函数操作文件描述符集合FD_ZERO清空文件描述符集合FD_SET将指定文件描述符添加到集合中FD_CLR将指定文件描述符从集合中删除FD_ISSET判断指定文件描述符是否在集合中是否发生变化七、Linux内核相关7.1 内核核心内容进程管理负责进程的创建、调度、终止以及进程间的同步与通信内存管理负责内存的分配与回收支持虚拟内存、分页机制管理进程地址空间文件系统通过VFS虚拟文件系统抽象层统一不同文件系统如ext4、xfs的接口实现文件的读写、创建、删除等操作设备驱动控制硬件设备支持驱动的动态加载和卸载为用户程序提供操作硬件的接口网络协议栈支持TCP、UDP、IP等多种网络协议负责数据包的处理、路由、转发内核模块可动态加载的程序代码.ko文件用于扩展内核功能无需重启内核7.2 内核启动流程加载内核BIOS/UEFI引导后加载内核镜像到内存初始化硬件内核初始化CPU、内存、中断控制器等核心硬件挂载根文件系统将根文件系统rootfs挂载到指定目录为用户空间提供基础文件结构启动用户空间程序启动init或systemd进程由其启动系统服务和用户进程完成系统启动八、C/C 核心区别与特性8.1 C与C的基础区别8.1.1 文件名与编译区别文件名C源文件后缀为.cpp/.cc头文件后缀为.hpp或无后缀C源文件后缀为.c头文件后缀为.h编译X86平台下C用gcc编译器C用g编译器g可兼容编译C代码但gcc不能直接编译C代码头文件包含C标准头文件无.h如iostreamC标准头文件带.h如stdio.h8.1.2 核心特性区别输入输出C用scanf/printfC用std::cin/std::cout命名空间C独有namespace如std用于避免命名冲突新数据类型C新增bool、string类型支持字符串直接用比较C独有特性函数默认传参、函数重载、内联函数、引用、智能指针等8.1.3 struct区别C语言的struct只能包含数据成员不能定义函数无访问控制默认全部公有C的struct可包含数据成员和成员函数支持public/protected/private访问控制默认公有与类class本质无区别class默认私有8.2 new/delete 与 malloc/free 的区别对比维度new/deleteCmalloc/freeC返回类型返回对应类型指针无需强制类型转换返回void*指针需显式强制类型转换构造/析构new分配内存时调用对象构造函数delete释放时调用析构函数仅分配/释放内存不调用构造、析构函数错误处理内存分配失败抛出std::bad_alloc异常内存分配失败返回NULL指针8.3 C智能指针核心作用基于RAII思想自动管理堆内存替代手动new/delete避免内存泄漏、野指针、重复释放等问题。8.3.1 unique_ptr独占智能指针特点独占内存所有权一块内存只能被一个unique_ptr持有不能拷贝只能移动move优势无引用计数性能最高离开作用域自动释放内存适用场景硬件句柄、帧缓冲、临时对象等轻量高效的场景8.3.2 shared_ptr共享智能指针特点引入引用计数机制多个shared_ptr可共享同一块内存每新增一个引用计数1析构时计数-1计数为0时释放内存缺点可能出现循环引用导致内存泄漏适用场景共享音视频帧、设备状态等需要多指针访问的场景8.3.3 weak_ptr弱智能指针特点不增加引用计数专门解决shared_ptr的循环引用问题不能直接访问内存需通过.lock()转换为shared_ptr后使用适用场景多线程模块用于线程间弱引用防止内存泄漏8.3.4 智能指针与普通指针的区别普通指针需手动new分配、delete释放易出现忘记释放、重复释放、野指针等问题智能指针自动管理生命周期无需手动释放底层封装普通指针实现自动析构嵌入式场景底层驱动、硬件操作优先用普通指针追求极致性能上层C封装、模块管理优先用智能指针减少内存问题8.4 C类与面向对象特性8.4.1 类的基础本质用户自定义复合数据类型用于描述对象的属性成员变量和行为成员函数类似C的结构体但功能更强大访问控制public公有外部可访问、protected保护子类可访问、private私有仅类内部可访问成员函数实现方式类内声明类内实现便于阅读但函数体过大会导致类过长类内声明类外实现避免类过于臃肿但查找函数实现需切换文件8.4.2 构造函数与析构函数构造函数与类名同名无返回值对象创建时自动调用用于初始化对象析构函数类名前加~无返回值对象销毁时自动调用用于释放资源如堆内存、文件句柄调用时机构造函数在对象创建局部对象、动态分配、对象数组时调用析构函数在对象销毁作用域结束、动态释放时调用8.4.3 类的继承核心概念派生类子类继承基类父类的成员实现代码复用基类的私有成员不会被继承三种继承方式及访问权限public继承基类public→派生类public基类protected→派生类protectedprotected继承基类public→派生类protected基类protected→派生类protectedprivate继承基类public→派生类private基类protected→派生类private8.4.4 虚函数与函数重写函数重写子类继承父类后若父类函数无法满足需求可重写该函数要求函数名、返回值、参数完全一致虚函数基类成员函数前加virtual关键字用于实现多态通过基类指针/引用调用函数时会根据实际对象类型调用对应子类的重写函数虚函数原理基于虚函数表编译时生成存储虚函数地址和虚表指针对象内置指向虚函数表实现动态绑定注意构造函数不能是虚函数虚函数表在构造函数执行时才构建基类析构函数建议声明为虚函数避免子类资源泄漏通过基类指针删除子类对象时确保调用子类析构8.5 C关键字详解8.5.1 static关键字修饰全局变量失去全局性仅在定义文件内可访问文件作用域避免同名冲突修饰局部变量延长生命周期至整个程序运行期间作用域仍限制在函数/代码块内函数执行完毕后变量值不销毁修饰类成员属于类本身而非类的实例所有实例共享该成员静态成员变量需在类外部初始化静态成员函数不能访问非静态成员8.5.2 const关键字修饰普通变量变量值定义后不可修改修饰指针指向常量的指针const int* p指针指向的内容不可修改指针本身可修改常量指针int* const p指针本身不可修改指向的内容可修改指向常量的常量指针const int* const p指针和指向的内容均不可修改修饰函数参数确保参数在函数内不被修改常用于引用/指针参数修饰函数返回值返回值不可被修改修饰类成员函数函数不会修改类的成员变量也不能调用非const成员函数8.5.3 volatile关键字作用指示编译器该变量的值可能在程序未显式修改的情况下发生变化如硬件修改、多线程修改原理禁止编译器优化该变量避免将变量缓存到寄存器每次访问都从内存中读取适用场景硬件编程、多线程编程8.5.4 auto与decltypeauto编译器根据变量的初始化值自动推导变量类型decltype获取表达式的类型用于精确查询类型无需初始化变量8.5.5 extern C作用用于C代码中调用C语言编写的函数如rkmedia、ffmpeg避免C名称修饰导致的链接错误原理告诉C编译器以C语言的方式编译指定的代码块不进行名称修饰8.6 指针与引用8.6.1 核心区别对比维度指针引用定义方式变量存储另一个变量的地址用*定义变量的别名定义时必须初始化且不能更改指向用定义占用空间需要分配内存存储地址不需要分配内存仅为别名多级性支持多级指针如int** p不支持多级引用如int a 是右值引用非多级自增运算指针自增指向下一内存空间引用自增是变量值加1访问方式间接访问通过*解引用直接访问与变量本身一致8.6.2 指针的常见类型多级指针一级指针指向变量地址二级指针指向一级指针地址以此类推函数指针指向函数的指针存储函数地址可通过指针间接调用函数指针数组数组的每个元素都是指针如int* arr[5]数组指针指向整个数组的指针如int (*p)[5]空指针与野指针空指针不指向任何有效内存通常为NULL或nullptr野指针指向已释放或无效的内存地址会导致程序崩溃或数据损坏避免野指针内存释放后指针置空、使用智能指针、避免指向局部变量、用nullptr初始化8.6.3 函数传参方式值传递将实参复制到形参函数内部操作不影响实参指针传递传递实参的地址函数可通过指针间接修改实参的值引用传递传递实参的别名函数内部操作直接修改实参可用const引用避免修改实参8.7 STL标准模板库核心C提供的通用、可复用的数据结构和算法库基于模板实现无需手动编写底层数据结构如链表、排序直接调用即可。四大核心部分容器、算法、迭代器、函数对象附加内存分配器。8.7.1 容器存储数据结构1顺序容器元素按顺序存放vector动态数组连续内存随机访问快尾部插入/删除效率高扩容时会申请2倍大小的新内存queue队列先进先出FIFO适用于帧队列、线程消息队列deque双端队列头尾均可快速插入/删除兼顾vector和queue的优势list双向链表插入/删除快任意位置但不能随机访问2关联容器有序底层红黑树map键值对存储键唯一自动按键排序查找效率O(logn)set存储唯一元素自动排序适用于需要元素唯一性、快速查找的场景3无序容器底层哈希表unordered_map/unordered_set哈希实现查找效率接近O(1)无序8.7.2 迭代器本质通用指针用于遍历所有容器语法统一无论vector、map均可用相同方式遍历作用隔离容器底层实现让算法可通用如sort可用于vector、list8.7.3 算法STL内置通用算法无需手动编写如冒泡、快排直接调用即可常见算法sort排序、find查找、for_each遍历、copy拷贝8.7.4 vector扩容机制触发条件向vector添加元素导致元素个数超过当前容量扩容步骤申请新内存新内存大小通常是当前容量的2倍复制/移动元素将旧内存中的元素复制/移动到新内存释放旧内存复制完成后释放旧内存空间8.7.5 set与map的区别set仅存储单一类型元素元素唯一、有序无键值对概念map存储键值对键唯一、有序可通过键快速查找值共同点均基于平衡二叉树实现查找、插入、删除效率均为O(logn)九、并发编程线程相关9.1 线程与进程的区别对比维度进程线程核心定位资源分配的基本单位CPU调度和执行的基本单位资源占用有独立的地址空间、内存、环境变量等资源占用多共享所属进程的资源仅拥有独立的执行栈资源占用少创建/销毁开销开销大涉及资源分配与回收开销小仅需创建执行栈和上下文通信方式需通过IPC机制管道、消息队列等复杂可直接读写共享变量简单如全局变量独立性独立性高一个进程崩溃不影响其他进程依赖性强一个线程崩溃可能导致整个进程崩溃9.2 线程与协程的区别线程由操作系统内核调度每个线程有独立的栈和上下文切换涉及内核态切换开销大、耗时久协程由用户程序主动调度共享线程资源切换仅需保存少量寄存器开销小、耗时短9.3 线程操作POSIX线程pthread头文件pthread.h编译时需加-lpthread参数核心接口pthread_create创建线程pthread_self获取当前线程号pthread_join阻塞等待线程结束回收线程资源pthread_exit线程退出不影响其他线程pthread_cancel取消指定线程线程清理pthread_cleanup_push注册清理函数、pthread_cleanup_pop执行清理函数需成对出现9.4 线程同步与互斥9.4.1 互斥锁pthread_mutex_t核心作用保证同一时刻只有一个线程能访问临界资源避免数据竞争操作流程初始化动态初始化pthread_mutex_init、静态初始化pthread_mutex_t mutex PTHREAD_MUTEX_INITIALIZER加锁阻塞加锁pthread_mutex_lock、非阻塞加锁pthread_mutex_trylock解锁pthread_mutex_unlock只有持有锁的线程能解锁销毁pthread_mutex_destroy释放锁资源9.4.2 条件变量pthread_cond_t核心作用同步多个线程让线程按照指定顺序执行如等待某个条件成立后再执行操作流程初始化动态初始化pthread_cond_init、静态初始化pthread_cond_t cond PTHREAD_COND_INITIALIZER等待条件pthread_cond_wait阻塞线程释放互斥锁条件成立后唤醒并重新加锁唤醒线程pthread_cond_signal唤醒一个等待的线程、pthread_cond_broadcast唤醒所有等待的线程9.4.3 读写锁核心特点读时共享、写时独占提升并发效率多个线程可同时读同一时刻只能有一个线程写分类读锁共享锁、写锁独占锁9.5 线程状态新建状态调用pthread_create后线程未开始执行就绪状态线程已初始化等待CPU调度运行状态CPU正在执行线程代码阻塞状态线程因等待资源如锁、条件变量暂停执行死亡状态线程执行完毕或被取消资源被回收9.6 死锁死锁发生的四个必要条件缺一不可互斥资源只能被一个线程占用占有并等待线程持有一个资源同时等待另一个资源不可抢占优先级高的线程占有低优先级的无法打断循环等待循环等待cpu调度9.7 线程间同步方式锁机制条件变量信号量