- 博客(31)
- 收藏
- 关注
原创 动态规划(Dynamic Programming)详解:从入门到 LeetCode Hot 100
将一个复杂问题拆分成多个规模更小的子问题,通过保存子问题的计算结果,避免重复计算,最终得到原问题的答案。先看一个经典问题。dp[i] = 以第 i 个元素结尾的最优结果例如最长递增子序列。最长递增子序列不一定以最后一个元素结尾,因此必须遍历整个数组取最大值。dp[i] = 前 i 个元素的最优结果这种情况下,最终答案通常就是dp[n]。关键在于理解 dp 数组的定义。动态规划的核心并不是背诵某个固定模板,而是建立正确的状态定义,并通过状态转移方程解决问题。dp[i] 或 dp[i][j] 表示什么?
2026-11-13 08:14:47
58
原创 排序算法详解:归并排序、堆排序与快速排序
归并排序:先拆分,再合并。合并时需要额外的辅助数组。快速排序:先划分,再递归处理左右区间。通常可以在原数组上完成排序。虽然单次堆调整最坏为 O(logn),但不同节点的调整高度不同:大部分节点位于树的底部,调整次数很少。只有少数节点位于树的顶部,可能需要较多调整。因此所有节点调整的总工作量为 O(n)。
2026-11-12 09:48:28
567
1
原创 数据结构复习——基础理论篇1
数据:描述客观事物的符号,是计算机能够识别和处理的对象。数据元素:数据的基本单位,通常作为一个整体进行处理。数据项:组成数据元素的最小单位。数据对象:具有相同性质的数据元素的集合。数据结构:相互之间存在一种或多种特定关系的数据元素的集合。数据结构主要包含三个方面:逻辑结构:数据元素之间的逻辑关系。存储结构:数据元素及其关系在计算机中的存储方式。数据的运算:对数据进行的操作,例如插入、删除、查找、排序等。集合结构:数据元素之间除了同属于一个集合外,没有其他关系。线性结构:数据元素之间存在一对一的关系。树形结构
2026-11-12 09:48:13
578
1
原创 spdlog 同步日志库使用详解
spdlog是一个轻量级 C++ 日志库,支持同步日志、异步日志、多线程日志、日志文件轮转和自定义日志格式。对于嵌入式 Linux 应用开发,我建议先使用。它可以帮我们完成:日志级别过滤。时间戳和线程 ID 输出。日志格式化。终端和文件输出。多线程安全写入。日志文件按大小或时间轮转。我们不需要自己实现互斥锁、文件写入、日志格式化和轮转等底层功能。
2026-11-11 11:14:17
995
1
原创 嵌入式 Linux 应用工程化开发:日志系统详解
在嵌入式 Linux 应用中,日志模块通常需要解决几个问题:统一日志输出格式。支持不同日志级别。支持多线程调用。支持输出到终端和文件。支持日志文件轮转,避免日志无限增长。在业务线程较多时,尽量避免日志 I/O 阻塞业务。实际项目中,可以自己实现一个基础日志模块,理解其内部原理;正式项目则可以使用 等成熟日志库。本文先实现一个同步日志模块,再在此基础上理解异步日志。首先设计一个统一的日志接口:业务代码只需要调用日志接口,不需要关心日志具体写到哪里。日志模块内部主要负责:判断当前日志级别是否允许输出。获
2026-11-11 11:13:53
1012
原创 算法:C++ STL 栈(stack)与队列(queue)详解
stack是 C++ STL 提供的栈容器适配器,遵循LIFO(Last In First Out,后进先出)原则。也就是说,最后放入栈中的元素最先被取出。这里定义了一个存储int类型元素的栈。接口功能是否修改栈push(x)入栈是pop()删除栈顶元素是top()获取栈顶元素否empty()判断是否为空否size()获取元素数量否直接在栈顶构造元素是其中emplace()和push()// push:先构造 pair,再放入栈中。
2026-11-10 13:19:12
1067
原创 C++ STL 高频知识点总结
迭代器可以理解为一种类似指针的对象,用于访问和遍历容器中的元素。it!= v.end();++it)类型特点常见容器输入迭代器只能向前读取输入流迭代器输出迭代器只能向前写入输出流迭代器前向迭代器可以多次向前访问双向迭代器可以前进和后退随机访问迭代器支持随机跳转vector 支持随机访问迭代器。list 不支持随机访问迭代器。map 和 set 支持双向迭代器。it + n这种随机跳转操作不能用于 list 的迭代器。迭代器用于访问容器中的元素。
2026-11-10 13:18:53
1071
原创 C++ 实习面试第一阶段:面向对象基础
C 和 C++ 都是通用编程语言,但设计思想和语言特性有所不同。C++ 相比 C 增加了以下重要特性:面试回答: C++ 并不是完全取代 C 的语言,它兼容了大量 C 语言的编程方式,同时提供了面向对象、泛型编程和资源管理等更丰富的特性。指针是存储对象地址的变量,引用是对象的别名。代码示例:需要注意:两者都用于表示空指针,但类型和使用方式不同。为什么引入 nullptr?因为 NULL 在一些实现中本质上是整数 0,可能导致函数重载时产生歧义。面试重点: C++11 以后优先使用 nullptr
2026-11-09 12:09:09
1131
原创 嵌入式LINUX应用开发需要掌握的C++知识概述
嵌入式 Linux 应用程序需要长期运行,经常涉及文件描述符、Socket、线程、设备句柄和动态内存,因此资源管理是重要考点。多线程是嵌入式 Linux C++ 应用开发的重要部分,常用于数据采集、网络通信、视频处理和后台任务调度。STL 不需要深入研究源码,重点是掌握常用容器、算法、迭代器及其适用场景。lock_guard 与 unique_lock 的区别。unique_ptr 与 shared_ptr 的区别。C++ 内存分区:栈、堆、全局/静态存储区、代码区等。
2026-11-09 12:08:12
835
原创 C++ 智能指针详解:unique_ptr、shared_ptr、weak_ptr 的原理与使用
智能指针是 C++ 提供的一种资源管理机制,利用 RAII 思想,通过对象的生命周期自动管理资源,减少内存泄漏、重复释放等问题。C++ 智能指针的核心不是简单地替代普通指针,而是通过明确资源所有权和生命周期,让资源管理更加安全。unique_ptr:独占所有权,不能复制,可以移动。shared_ptr:共享所有权,通过引用计数管理对象生命周期。weak_ptr:弱引用,不增加强引用计数,可以解决循环引用。
2026-11-08 14:36:56
904
原创 C++ 智能指针进阶:enable_shared_from_this、自定义删除器与多线程任务队列
普通智能指针默认使用delete释放对象。当p析构时,会自动释放它管理的整数对象。但是实际开发中,并不是所有资源都通过new申请。资源申请方式释放方式普通对象newdelete文件描述符openclose文件流指针fopenfclose这些资源都有各自的释放接口,不能直接使用delete。因此需要自定义删除器。自定义删除器就是告诉智能指针:当对象销毁时,应该使用什么方式释放资源。
2026-11-08 14:36:32
965
原创 Linux 网络编程面试高频考点:非阻塞 I/O、超时、心跳、断线重连、缓冲区与背压
面试问题:什么是非阻塞 I/O?它和阻塞 I/O 有什么区别?答:阻塞 I/O 是指当执行 I/O 操作时,如果当前无法完成操作,线程就会等待,直到操作完成或发生错误。非阻塞 I/O 是指当执行 I/O 操作时,如果当前无法立即完成操作,就直接返回,不会一直等待。例如,调用recv()接收数据:阻塞模式:接收缓冲区没有数据时,线程会等待。非阻塞模式:接收缓冲区没有数据时,立即返回,并设置errno为EAGAIN或。面试问题:TCP 连接已经建立,为什么还需要心跳机制?
2026-11-07 12:19:35
1152
原创 Linux I/O 多路复用详解:select、poll、epoll 机制与区别
在 Linux 网络编程中,经常需要处理多个客户端的连接。假设现在有一个 TCP 服务器,同时与 1000 个客户端建立连接。如果采用传统的阻塞 I/O 模型,通常需要为每个客户端创建一个线程,由对应线程阻塞等待客户端发送数据。客户端数量增加,线程数量也随之增加。线程创建和销毁存在额外开销。大量线程会带来频繁的上下文切换。每个线程都需要占用一定的栈内存。那么,有没有一种方式,可以让一个线程同时监视多个 Socket,哪个 Socket 有数据到达,就处理哪个 Socket?这就是。
2026-11-07 12:19:10
955
原创 Linux 进程管理:孤儿进程与僵尸进程详解
孤儿进程是指:父进程先于子进程退出,而子进程仍然在运行,此时子进程就成为孤儿进程。父进程+---- 子进程假设执行过程如下:父进程通过fork()创建子进程。父进程执行完毕,调用exit()退出。子进程还没有执行完毕,仍然继续运行。此时,子进程失去了原来的父进程,就成为孤儿进程。僵尸进程是指:子进程已经执行结束,但是父进程没有调用wait()或waitpid()回收子进程的退出状态,此时子进程就进入僵尸状态。孤儿进程和僵尸进程都是 Linux 进程生命周期管理中的重要概念。
2026-11-06 09:56:32
1067
1
原创 两种条件变量详解:std::condition_variable 与 pthread_cond_t
因为条件变量本身不负责保护共享数据。需要通过互斥锁保护共享状态,并保证条件检查和进入等待的过程正确同步,避免数据竞争和丢失唤醒。条件变量最核心的知识点可以归纳为:条件变量用于线程间的等待与通知,避免忙等待。条件变量本身不保存数据,也不保存等待条件。条件变量通常需要配合互斥锁使用。wait() 会原子地释放互斥锁并进入等待,唤醒后重新获取互斥锁。推荐使用 wait(lock, predicate),POSIX 中使用 while + pthread_cond_wait()。
2026-11-06 09:56:00
864
原创 Linux 网络编程面试题:TCP 字节流、部分读写与 UDP 数据报
答:环形缓冲区是一种循环利用固定内存空间的数据结构,通常使用数组实现,并维护读位置和写位置。写位置到达数组末尾后会回到数组开头,读位置也是如此。这样就可以重复利用已经释放的空间,不需要像普通线性缓冲区那样频繁删除头部数据和移动剩余数据。readPos:下一次读取数据的位置。writePos:下一次写入数据的位置。size:当前缓冲区中有效数据的数量。层次需要掌握的知识TCP 基础字节流、粘包拆包、应用层消息边界应用层协议固定长度、分隔符、长度字段、序列号TCP 读写。
2026-11-05 00:05:18
1505
原创 Linux 多线程编程详解:线程基础、同步机制、生产者消费者、线程池与面试重点
线程(Thread)是操作系统进行 CPU 调度和执行的基本单位。一个进程可以包含一个或多个线程,多个线程可以并发执行。例如,一个视频监控程序可以创建多个线程:采集线程:从摄像头获取视频帧。解码线程:负责视频数据解码。图像处理线程:负责图像分析和处理。显示线程:负责显示图像。网络线程:负责向服务器发送视频数据。这些线程属于同一个进程,可以共享进程中的资源。生产者消费者模型是多线程开发中非常经典的设计模式。核心思想:生产者负责生产任务,消费者负责处理任务,中间通过共享队列进行解耦。摄像头。
2026-11-05 00:03:48
788
原创 嵌入式 Linux 笔记:应用程序、设备驱动与内核之间的关系
调用进入内核后,由 VFS 或对应的设备子系统找到相关驱动操作,驱动再完成硬件配置、数据传输、中断处理等工作。对于应用层岗位,通常不要求一开始就能独立编写完整内核驱动,但要理解驱动向应用程序提供了什么接口,以及应用程序如何正确使用它。应用程序打开它后,内核根据设备节点关联的信息找到对应设备对象和操作接口。后续调用 read()、write()、ioctl() 时,内核根据 fd 找到对应的内核文件对象,再分发到相应操作。驱动可以把它管理的缓冲区映射给用户程序,但映射范围和权限由内核及驱动控制。
2026-11-04 11:39:56
1552
原创 C++ 二分查找完全指南:从 STL 接口到手写实现与 LeetCode Hot 100 实战
二分查找(Binary Search),也称折半查找,是一种在有序数据集合中查找目标元素的算法。其核心思想是:每次选择当前查找区间的中间位置,将中间元素与目标值进行比较,根据比较结果排除一半不可能包含目标值的区间,从而不断缩小查找范围,直到找到目标元素或者查找区间为空。例如,在一个升序数组中查找元素9第一次查找:取中间元素7,因为7 < 9,所以排除左半部分。第二次查找:在剩余区间中取中间元素11,因为11 > 9,所以排除右半部分。第三次查找:找到元素9。每次比较都会将查找范围缩小一半。
2026-11-04 11:39:01
891
原创 Linux 设备访问全解析:串口、设备节点、/proc 与 /sys 实战指南
dev 下的设备节点为用户空间访问驱动提供入口,应用通过 open、ioctl、read、write 等系统调用操作设备;/sys 基于 sysfs 展示内核设备模型,包括设备、驱动、总线及其属性。应先查阅对应驱动或内核文档,确认属性含义、允许的取值和写入副作用,不要随意向未知属性写数据。/sys 主要展示内核设备模型以及设备、驱动、总线和属性。应用程序打开设备节点后,内核会根据设备节点关联的信息,将操作分发给相应的设备驱动。它把设备、驱动、总线、类等内核对象及其属性,以目录和文件的形式呈现给用户空间。
2026-11-03 11:06:12
808
原创 Linux 信号处理、errno 与系统调用返回值:嵌入式 C/C++ 实战与面试速查
信号是 Linux 进程间的一种异步通知机制。操作系统或其他进程可以向目标进程发送信号,通知它发生了某种事件。
2026-11-03 11:03:14
1206
1
原创 ASan(AddressSanitizer)内存错误检测工具详讲
ASan 是一种通过编译器插桩和运行时检查来发现内存错误的工具。它能帮助开发者定位非法内存访问及相关的申请、释放位置,是 C/C++ 程序开发和测试阶段非常实用的内存排错工具。
2026-11-02 15:07:02
795
原创 Linux 进程间通信与线程同步详解:pipe、FIFO、共享内存、消息队列、信号量、互斥锁与条件变量
FIFO 是有名管道,在文件系统中有路径,因此不相关的进程也可以通过同一路径打开通信。多个进程把同一块内存映射到各自地址空间,可以直接访问共享数据,避免通过管道或消息队列传输大块数据时产生的额外数据复制开销。共享内存只解决数据共享,不保证一个进程写入时另一个进程不会同时读取,也不负责通知消费者数据已经准备好。进程 A 写入共享内存后,进程 B 可以读取同一块共享区域,避免像管道那样必须把数据从一个进程复制到内核缓冲区、再复制到另一个进程。消息队列按消息收发,保留消息边界,并支持消息优先级。
2026-11-02 15:05:23
933
原创 GDB 调试实战:启动调试、附加调试与 core 分析全解析
GDB 三种模式:启动调试(GDB 启动进程)、附加调试(attach 活进程)、事后 core 分析(只读崩溃快照,不碰活进程)。前两种 GDB 控制活进程,第三种只分析文件。一次看全,快速发现“谁等锁、谁持锁、谁空转、谁阻塞 read”。说明:进程已崩溃,GDB 只加载 core 内存快照文件进行分析。不 attach 任何活进程,不控制进程,只读文件。说明:GDB 自己 fork+exec 启动被调试进程,GDB 是父进程。附加调试时 GDB 暂停整个进程,bt 看的是暂停那一刻的快照。
2026-11-01 00:26:48
797
1
原创 Linux gdb 命令详解:从安装到基础命令讲解
GDB 支持多种编程语言,包括 C、C++、Objective-C、Fortran、Ada 等,是 Linux 开发者不可或缺的调试利器。
2026-11-01 00:26:37
157
原创 RAII:资源生命周期管理笔记
RAII = 资源获取即初始化,资源释放即析构。把资源绑在栈对象上:构造获取、析构释放,作用域结束自动清理,异常也清理。你从来没给 vector 写 delete[],没给 lock_guard 写 unlock()——这就是 RAII。一句话:别手动 open/close、new/delete、lock/unlock,交给栈对象,它死的时候自动释放。判断标准:这个资源是不是“无论怎么退出都必须释放”?判断标准一句话:这个资源是不是“无论怎么退出都要释放”?心智模型:栈对象的作用域 = 资源的生命周期。
2026-10-31 15:40:18
545
原创 GIT详细教程
暂存区,也称为索引(Index),是一个临时存储区域,用于保存即将提交到本地仓库的更改。你可以选择性地将工作目录中的更改添加到暂存区中,这样你可以一次提交多个文件的更改,而不必提交所有文件的更改。每次你提交更改时,Git 会将暂存区中的内容保存到本地仓库中。当你切换分支的时候,Git 会用该分支的最后提交的快照替换你的工作目录的内容, 所以多个分支不需要多个目录。Git 的工作就是创建和保存你的项目的快照及与之后的快照进行对比。Git 的工作就是创建和保存你项目的快照及与之后的快照进行对比。
2026-10-31 14:23:40
609
原创 CMake 基础
语法:project(<项目名> [<语言>...])# 语言参数可选,常用值:CXX(C++)、C(C 语言)# 调用 project() 后会自动设置 PROJECT_NAME 等变量# 语法:add_custom_command(# TARGET <目标># COMMAND <命令> [参数...]# [COMMENT <说明>]# PRE_BUILD:在编译前执行# PRE_LINK:在链接前执行# POST_BUILD:在构建完成后执行。
2026-10-30 10:14:44
537
原创 Linux应用开发必备技能
MetricsCollector:统计 FPS、延迟、CPU、内存与重连耗时。5. 优先把通用基础练扎实,再集成 FFmpeg、RTSP、MPP、RGA。- 软件解码与硬件解码使用相同输入、分辨率、帧率、运行时间和输出条件。- 日志:dmesg、journalctl(取决于系统)- branch、merge、rebase 的基本使用。- 文件与文本处理:find、grep、sed、awk。- TCP/UDP、epoll、日志配置、性能分析、交叉编译。- GDB:断点、单步、调用栈、变量检查、线程调试。
2026-10-29 18:38:15
331
原创 算法:前缀和的学习
前缀和(Prefix Sum)本身严格来说不算一种“高深”的算法,它更像是一种预处理技巧或数据结构的思想。它的核心目的只有一个:把区间求和(或求积)的时间复杂度从 O(n)O(n) 降到 O(1)O(1)。在面试中,面试官问前缀和,通常是在考察你对“空间换时间”和“边界处理”的理解。以下是前缀和的核心概念、常见形式及面试考点:假设你有一个数组 。如果我想让你求索引 到 的元素和(即 ),你肯定要用一个 循环去累加,这是 O(n)O(n) 的。但如果我让你查 100 次、1000 次呢?每次都循环太慢
2026-10-29 18:36:40
65
原创 哈希表的学习
哈希表是一种通过键(Key)来直接访问值(Value)的数据结构。它利用一个叫做哈希函数的转换规则,把任意大小的键(字符串、数字或对象)转换成一个固定范围内的数字,这个数字被称为哈希值。哈希值再作为底层数组的索引,值就存储在索引对应的数组位置上。这就像给每个键分配一个唯一的座位号:想找数据时,用同样的规则再算一次座位号,直接走过去就能拿到,而不用挨个座位去问。C语言实现int key;int value;int size;/* 哈希函数:处理负数 */
2026-10-17 20:24:58
224
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人
RSS订阅