- 博客(102)
- 收藏
- 关注
原创 C/C++常见面试题
局部变量是定义在函数内部或者大括号{}代码块内部的变量,它的作用域只局限于当前这个代码块,出了大括号就无法访问。局部变量存储在栈空间,当程序进入代码块时创建,代码块执行完毕之后就会自动销毁。局部变量不会自动初始化,如果没有手动赋值,里面存放的是随机垃圾值。函数的形参属于局部变量。如果调用函数时,传入的实参是写在 main 或者其他函数内部定义的变量,那这个实参就是局部变量;实参也可以直接写常量数字,比如func(10),这个10是字面量,不是变量。
2026-10-04 11:13:50
126
原创 9.24 面试复盘
您好,我本科专业是环境科学,但因为自己比较喜欢编程,所以从大学期间开始系统学习 C++。目前主要掌握 C++、数据结构、Linux、多线程以及 Qt 开发。C++方面学习过面向对象、STL、内存管理等基础知识,也通过技术博客和项目进行巩固。Linux方面主要学习了常用命令、进程线程以及多线程同步。项目方面,我做过一个基于 Qt 的音乐播放器,以及一个仿 muduo 的高并发服务器,对 Qt 开发和 Linux 网络编程都有一定实践。
2026-09-26 19:56:11
224
原创 9.20 知识点查漏补缺
Muduo 每个 EventLoop 都有独立私有的任务队列,不存在所有 EventLoop 共用同一个全局任务池。别的线程通过 runInLoop 向这个 loop 投递任务时,队列本身带互斥锁保护,push 操作线程安全。但是任务回调内部访问的业务数据,muduo 不会自动加锁,业务数据的并发访问需要我们自己保证线程安全。
2026-09-19 21:51:49
198
原创 9.18 面试题总结 --- 绿盟
我参与比较深的是频谱监测上位机的 IQ 数据接收模块。接手的时候项目已经有一部分代码。最开始开发我将 UDP 数据接收解析和 UI 绘图全部放在 Qt 主线程,大数据量下界面卡顿。之后我做线程拆分,子线程负责 UDP 接收、解析,UI 线程负责波形渲染。因为万兆 UDP 数据流很大,存在乱序丢包,我在 UDP 自定义包头增加包序号,应用层实现环形缓冲区,做数据包的排序重组,数据完整率达到 95% 以上。同时使用 setsockopt 调大 socket 内核接收缓冲区,防止高速数据下内核层面丢包。
2026-09-19 11:29:56
198
原创 9.16 面试总结
我改成多线程架构,子线程负责 UDP 接收和数据解析,利用 Qt 跨线程信号槽把处理完成的数据投递 UI 线程渲染,规避子线程直接操作 UI 的问题。我理解工业软件和普通业务软件不一样,既要做底层的数据采集、处理,又要做上层可视化界面,对稳定性、数据可靠性要求很高。我实习做的频谱上位机,就属于工业采集类软件,需要处理高速数据流,还要保证异常情况下数据不损坏。如果要删除一个中间的定时器,不能直接从堆里删掉,一般采用懒删除:标记定时器失效,堆不主动删,等到堆顶取出的时候,判断标记,如果失效就丢弃。
2026-09-18 22:02:13
160
原创 9.15 面试问题总结(一面挂)
在 Linux 系统里,会话是进程的一种分组管理单元,一个会话里可以包含多个进程组,最开始由第一个创建会话的进程做会话首进程;我们打开一个终端窗口,这个终端本身就是一个独立会话,你在终端里敲命令运行的程序、启动的服务进程,默认都归属于这个终端会话,一旦关闭终端,会话销毁,里面所有进程都会被系统杀掉。守护进程就是脱离终端、后台静默运行的服务进程,像服务器、日志进程都是它,它不需要依赖终端输入输出,就算关掉终端也不会退出,一直后台跑。序列化:内存中的结构体 / 对象,转为可以网络传输、落地保存的数据格式。
2026-09-15 19:12:01
162
原创 面试问题总结 --- Linux篇
条件变量用于多线程中等待某个条件达成,必须配合互斥锁使用。条件不满足时,cond_wait会释放锁并阻塞休眠;其他线程修改条件后通过 signal 唤醒它,唤醒后重新获取锁,再次检查条件。避免循环轮询浪费 CPU。signal:唤醒至少一个等待在条件变量上的线程broadcast唤醒全部等待的线程当条件变量广播唤醒所有等待线程,不管是生产者还是消费者全部被唤醒,然后大量线程去竞争同一把锁,大部分线程发现条件不满足又继续休眠,造成大量无效竞争、浪费 CPU。
2026-09-14 23:25:11
160
原创 面试题总结 ---Linux篇
操作系统在物理内存开辟一块内存,多个进程通过系统调用把这块物理内存映射到自己的虚拟地址空间。进程读写,直接操作物理内存,数据不需要在内核缓冲区和用户缓冲区之间拷贝,所以速度最快。本身不带同步互斥机制,需要我们自己加信号量 / 互斥锁保护,防止并发读写冲突。因为每个进程都有自己的虚拟地址空间,相互隔离,不能直接进行读写,ipc就是一套让不同进程之间可以进行交流,同步信息的机制。二元信号量就是os将共享内存划分成了一块,信号量对应的计数器的个数是一,二元信号量的本质就是琐。
2026-09-13 22:11:47
217
原创 面试题总结 ---Linux篇
行缓冲是 stdio 用户缓冲区的一种缓冲策略,标准输出 stdout 默认是行缓冲模式。当往缓冲区写入换行符\n的时候,就自动调用 fflush,把缓冲区里所有数据刷到内核。设计这个的目的,是为了终端交互场景。比如我们在控制台打印日志,一行结束加换行,用户就能立刻看到这一行的输出,不用等缓冲区填满。ELF 是 Linux 下的可执行与可链接格式,是目标文件、可执行程序、动态库的标准文件格式。
2026-09-12 20:09:20
177
原创 9.10日面试遇到问题总结
自己添加包序列号 seq。FPGA 打包时,给每个 UDP 包写入 seq 序号、帧编号、一帧总包数量。上位机收到包,解析出自定义包头里的 seq,根据序列号,在环形缓冲区对应位置存放数据包,完成重组。接收完成后检查序列号是否连续,检测丢包;一旦丢包,通知设备重扫。
2026-09-11 16:26:37
183
原创 仿muduo库实现高并发服务器项目
事件驱动多路复用,统一监听所有 IO 事件,事件到达后分发交给对应回调函数处理。Reactor 不是服务器,是一套「事件调度设计模式」,是高并发服务器的核心骨架。它是一种干活的规则 / 架构思想:用一个总管(事件循环 + epoll)统一盯着所有客户端连接,哪个连接有读写 / 连接事件,就派发任务给对应函数处理。
2026-09-09 20:26:18
210
原创 算法哪些事儿---1
所谓的高精度就是位数多到我们的double都没办法存储,对于它的加减乘除计算我们要使用模拟的方法;而它的背后是对我们小学学习的列竖式的模拟;
2026-08-26 14:46:05
204
原创 链表常用的技巧和操作与基础算法题实现
在我们做算法题的时候我们经常会遇到上面这种在链表的两个结点中间插入一个结点cur的情况,按理来说我们会使用上面这四步,但是这样很容易出错,这个时候我们可以考虑定义一个next的指针变量,即让prev的next指针被命名为next的指针,这样上面的四步就会变得简单起来上面的四步就变成了这四步的顺序是怎么样的也没有关系,因为我们就不再害怕会丢了prev的next指针;
2026-08-18 20:59:56
153
原创 set、map、unordered_map、unordered_set在应用上详细对比与底层实现逻辑分析
map 是一种容器,存的是"键值对(Key-Value),通过 Key 快速查找对应的 Value。就像"通讯录":输入名字(Key),查到手机号(Value)。set的名字叫做集合,map叫做映射。map和set一样,map的底层使用也是红黑树,也是有序的,map和set的区别是map从set的单个元素变成了键值对,map是按照key排序。
2026-08-16 16:54:16
294
原创 初始Redis---为什么出现redis
只有一台服务器,这代服务器负责所有工作;随着我们用户的数量增多,一台主机即负责业务逻辑、又负责数据处理的的方法行不通了,我们可以想到改变代码性能,如果这个还是行不通,并且因为一个主机的硬件资源是有限的,所以我们引入分布式系统,随着用户数量的增多,服务器数量也会随着增多;可能性永远是要保证的第一要务,不管一个技术有多牛,只要挂了就免谈了;处理的一个响应所用的时间;①单机架构应用程序服务器+ 数据库服务器②数据库和应用分离应用程序和数据库服务器分别放到不同主机上部署③引入负载均衡。
2026-07-08 23:00:05
254
原创 多路转接--select /poll
引言linux中创建的多路转接的方式有三种,select ,poll ,epoll;多路转接的核心思想是一次等待多个文件描述符,也就是socket;内核对多路转接的大量fd的管理使用的是红黑树,epoll 内核用红黑树管理所有监听文件描述符,依靠平衡特性实现;网卡数据触发硬件中断后,内核通过红黑树精准定位对应 fd,放入就绪队列,最后唤醒用户进程处理事件。内核用 epoll 监听哪些套接字就绪,拿到就绪事件后,扔给线程池去读写业务数据,。
2026-05-18 19:31:45
379
原创 五种IO模型
我们这里所说的五种IO模型指的是将数据从传输层的接收和发送缓冲区进行的IO,不再是我们之前所说的在本地进行的基础IO,之前我们的网络所进行的IO使用的是send,recv接口,可是我们并没有对IO的效率进行考虑,这篇文章就是来讨论这个问题的;
2026-05-18 11:02:51
405
原创 传输层协议Tcp详解----上
TCP全称为 "传输控制协议"). ⼈如其名, 要对数据的传输进行⼀个详细的控制;TCP 是互联网传输层核心可靠协议,面向连接、有序无差错传输,通信前需三次握手建立连接,传输中进行确认应答、超时重传、流量控制与拥塞控制保障数据完整送达,通信结束通过四次挥手断开连接,以字节流形式收发数据,具备丢包重传、去重排序能力,适用于文件传输、网页访问等对数据完整性要求极;由上图我们可以知道TCP协议位于传输层,由操作系统进行管理;下图是TCP协议的报文结构,接下来我们将详细的学习它其中每一个字段的作用;
2026-05-16 12:20:59
379
原创 自定义协议、序列化、反序列化实现
定义结构体来表⽰我们需要交互的信息;发送数据时将这个结构体按照⼀个规则转换成字符串, 接收到数据的时候再按照相同的规则把字符串转化回结构体;这个过程叫做 "序列化" 和 "反序列化;这样的约定就是应用层协议;而之所以要序列化其实是为了方便网络发送,因为之前我们发送的都是一个字符串;
2026-05-10 20:47:11
668
原创 每日“一”忘(守护进程居多)
(1)如何创建后台进程(2)如何杀掉后台进程如何将后台进程提到前台?fg+任务号,这个时候在按ctrl+c就可以杀掉进程了;(3)如何将放到前台的进程再放到后台,并让其运行起来?先按ctrl + z,让前台进程暂停,再输入bg 1 进程回到后台运行;(4)如何查看当前有多少个任务?
2026-05-10 20:42:24
261
原创 基于tcp协议实现远程命令操作功能服务器
TCP是面向连接的,也就是需要连接的,使用Tcp协议的客户端进行通信的时候必须要先和服务器建立连接,这就要求服务器随时都要处于等待连接的状态,这也就是所谓的监听,才能进行通信,而Udp一旦绑定就自动建立连接,可以直接通信;backlog是指服务器中全链接的个数,其实也就是排队个数;还有就是Tcp是面向字节流进行通信的,Udp是面向数据报通信,两者的区别是面向数据报是不可能会发生读不完这种情况的,但是面向字节流可能会发生,所以我们使用recv和sendto来解决这个问题;
2026-05-09 15:58:07
150
原创 Socket编程实现UDP通信
套接字=IP地址+端口号第一个参数详解第二个参数详解socket有指定的类型,该类型确定了通信的语义(规则)SOCK_STREAM 提供有序、可靠、双向(全双工)、基于连接的字节流。two-way:翻译为全双工,意思是连接一旦建立成功双方可以同时发数据和接收数据;返回值:成功返回一个文件描述符fd,失败返回-1;
2026-05-06 20:38:59
421
原创 QT-设计师模式基本知识
Key Sequence Edit 是 Qt 中专门用于捕获、编辑键盘快捷键序列的输入控件,是软件设置「自定义快捷键」功能的核心组件,能让用户直观地绑定、修改全局 / 局部快捷键。就是一个快捷键设置输入框,比如你在软件里设置「Ctrl+S 保存」「Ctrl+O 打开」时,点击这个输入框,按下你想要的快捷键,它就会自动识别并记录,是所有带自定义快捷键功能的软件的标配组件核心作用快捷键序列捕获:自动识别用户按下的键盘组合(如 Ctrl+S、Alt+F4、Ctrl+Shift+N),无需手动输入。
2026-04-03 20:22:35
484
原创 死锁+线程安全
重入就是同一个函数被不同的执行流调用,当前一个流程还没有执行完,就有其他的执行流再次进入,我们把这种情况成为重入;一个函数在重入的情况下,运行结果不会吃先任何不同或者问题,这个函数成为可重入函数,否则,是不可重入函数;重入可分为两种:①多线程重入函数 ②信号导致一个执行流重复进入函数(1)可重入与线程安全联系可重入函数一定是线程安全的线程安全函数不一定是可重入的可重入是线程安全的子集,要求更严格;(2)可重入与线程安全区别。
2026-04-02 21:29:43
389
原创 POSIX信号量+生产消费模型应用+环形缓冲区实现
信号量就是一个带计数的锁,用来控制最多同时有多少个线程能进入某段代码(共享资源)。互斥锁(mutex):只能 1 个线程进,同一时刻只允许一个线程进入临界区,这样的信号量就叫做互斥锁,也叫做也叫做二元信号量;信号量(semaphore):可以设置 N 个线程 同时进入临界区;申请信号量的本质:申请一份 “许可”,让线程可以继续往下执行;没有许可就阻塞等待。“资源是否准备成功 == 申请信号量是否成功” -> 非常重要!!!!
2026-04-01 11:16:05
448
原创 线程互斥+线程同步+生产消费模型
互斥量就是一把保护共享资源的锁,同一时间只允许一个线程持有它,就是访问当前的临界区代码,用来解决多线程同时读写同一块数据导致的混乱、错误问题。线程共享进程的内存空间,所以全局、静态、堆、成员变量都是共享数据;只有局部变量是线程私有。这就是为什么必须用互斥锁—— 防止多个线程同时改同一块内存导致结果错乱。我们去在超市中买东西,超市的东西是供应商,每次超市都会买很多的东西给我们卖,我们直接去超时买东西会比直接去工厂方便很多,而超市在我们看来其实就是缓存;
2026-03-30 21:46:21
429
原创 从源码深度探究“线程控制“
而且我们这个库是用户级线程库,所以库对对应的属性有对应的函数接口,而这么多线程都需要维护对应的属性,就需要操作系统对这些属性进行先描述、后组织,而描述的这个结构体的名字不是Pcb,而是tcb;pthread_create 函数第一个参数指向的内存单元中存储的,是 NPTL 线程库层面的线程 ID,线程库的后续操作都是根据该线程 ID 来操作线程的;进程的时间片是被线程瓜分的,也就是说线程的时间片不是系统分配的,因为如果是系统分配的,呢么进程就可以通过创建更多的线程来获得更多的时间片,这样是不好的;
2026-03-28 11:49:58
378
原创 深度剖析Linux 线程概念
首先线程是一个执行流,它的执行力度比进程更细,是进程内部的一个执行分支,而进程是承担分配系统资源的基本实体,线程是OS调度的基本单位,线程一定要用自己的独立上下文和栈结构!!!线程允许一个程序内部同时做多件事而不互相卡住,它让程序能在执行耗时操作(如网络请求、文件读写、计算)时依然保持界面响应,避免整个软件卡死;通过把任务拆分成多个轻量级线程,可以提升运行效率,同时线程间共享同一进程的内存空间,切换成本远低于进程,适合高并发、高响应速度的场景;
2026-03-25 20:28:19
611
原创 Linux“信号“从硬件到软件详解
信号本质上是一种用户、OS、其他进程向目标进程发送异步事件的一种方式;所谓的异步事件就是指突然发生的事件;进程是怎么识别信号的呢?其实信号是内置的,也就是程序员给每个进程都内置了信号的特性,因此进程是认识信号的;进程处理信号必须是立即的吗?不是的,如果进程有优先级更高的事情要做,可能不会立即处理而是在合适的时候。进程处理信号有三种方式,分别是下面的;SIG_IGN内核直接丢掉信号,进程完全不处理SIG_DFL按系统默认动作处理(终止 / 暂停 / 忽略等收到信号时,执行自己写的函数。
2026-03-24 17:51:56
404
原创 进程间通信——信号量篇
信号量本质上是一个计数器,不同的进程访问共享内存的子区域,这样保证了不同进程访问共享资源,具有一定的并发性,但是我们最害怕的是将资源分成了16个,但是有17个进程来访问资源,所以我们定义了一个int count,让每一个进程进来之后判断 count >0,进程进入共享资源,<0 ,先让进程进行等待,其实每一个小的资源和之前的管道访问的资源的互斥性是一样的;这个计数器不止是对资源数量的++,--,还会对资源进行预定;
2026-03-23 15:15:32
388
原创 进程间通信 --- 共享内存篇(通信速度最快)
此图说明两个进程通过共享内存通信是通过将物理内存的一块内存分别映射到两个毫不相干的进程的地址空间上,这样两个进程就看到了同一份资源;
2026-03-23 11:44:57
562
原创 Linux中进程间通信 ---管道篇
命名管道(FIFO,First In First Out)是一种半双工的进程间通信机制,它在文件系统中以特殊文件形式存在,所以有文件名和inode ,,允许无亲缘关系的进程间进行数据交换。与匿名管道(pipe)不同,命名管道可被多个进程通过路径名访问,生命周期独立于创建进程,只要文件未删除就可长期使用。它遵循先进先出的读写规则,数据按写入顺序被读取,且默认以阻塞模式工作:读端会等待数据写入,写端会等待读端打开。
2026-03-22 17:34:04
441
原创 Linux中库的制作和原理详解
库是预先编写完成、经过验证的成熟代码集合,核心价值是代码复用。现实中几乎所有程序都依赖大量基础底层库,无需从零开发,因此库的存在对软件开发至关重要。从本质上讲,库是可执行代码的二进制形式,能被操作系统加载到内存中执行。
2026-03-21 15:40:24
443
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人
RSS订阅