- 博客(38)
- 收藏
- 关注
原创 基于 C++ 手写 HTTP 服务器:从请求解析到响应构建全流程解析
本文介绍了常见应用层协议及其用途,重点解析了HTTP协议的工作原理。通过实现一个简易HTTP服务器,展示了HTTP请求/响应的报文结构(首行、报头、空行、正文)及处理流程。文章对比了GET和POST方法的区别:GET将参数拼接在URL中,POST则将参数放在请求正文。最后强调HTTP协议本质是遵循特定格式的字符串通信,通过实现服务器揭示了浏览器与服务器交互的底层机制。
2026-03-24 22:59:25
614
20
原创 手写一个C++ TCP服务器实现自定义协议(顺便解决粘包问题)
本文探讨了TCP网络编程中应用层协议设计的重要性。由于TCP是字节流协议,存在粘包问题,需要自定义协议来确保数据完整性。作者通过实现一个网络计算器案例,展示了如何设计协议格式(长度+内容)并使用序列化/反序列化技术处理结构化数据。核心解决方案包括Encode()封装报文和Decode()解析报文函数,确保每次处理完整请求。服务器通过循环读取和协议解析,正确处理边界问题,实现了可靠的计算服务。文章强调TCP编程的关键在于设计合理的应用层协议来界定数据边界,而非简单的数据收发。
2026-03-17 18:11:46
2452
37
原创 TCP 服务器如何支持高并发?单进程、多进程、多线程模型详解
本文介绍了TCP服务器编程的实现过程,从单进程到多进程再到多线程版本。主要内容包括:1)TCP服务器基本流程(socket-bind-listen-accept);2)单进程版实现及存在的问题(无法并发处理客户端);3)通过双fork技术实现多进程版,解决僵尸进程问题;4)使用信号处理优化多进程版本;5)多线程版本实现及类成员函数适配问题处理。文章通过餐厅接待客户的比喻形象解释了listenfd和sockfd的作用,对比了三种模型的并发能力、资源消耗和适用场景,帮助读者理解TCP服务器的核心设计思想。
2026-02-12 15:28:19
8090
39
原创 Linux 网络编程:UDP Socket 群聊模型的实现与细节分析
本文介绍了一个基于UDP协议的简易群聊程序实现。系统采用C++开发,服务端负责接收消息并转发给所有客户端,客户端通过双线程实现消息发送与接收。关键点包括:1) 服务端使用socket/bind/recvfrom/sendto等系统调用;2) 客户端不绑定固定端口避免冲突;3) 通过IP+端口唯一标识客户端。文章还深入分析了UDP特性,如无连接、报文传输、端口分配机制等,并对比了TCP与UDP的差异。该实现展示了UDP在网络编程中的应用场景和核心思想,适合实时性要求高的通信需求。
2026-02-09 21:58:59
11392
32
原创 计算机网络到底在干什么?从协议、封装到 TCP/IP 协议栈
网络协议是计算机通信的基础规则,包括TCP/IP五层模型(物理层、数据链路层、网络层、传输层、应用层)。每层都有特定功能,如物理层处理信号传输,网络层负责IP寻址。通信过程涉及数据封装(添加协议头)和解包。IP地址标识主机,端口号标识进程,共同构成套接字。TCP提供可靠连接,UDP则更高效。编程时需处理字节序转换(htonl等函数)和使用sockaddr_in结构存储地址信息。协议确保不同设备能按统一标准通信,类似快递单确保包裹准确送达。
2026-02-08 23:21:53
11836
28
原创 POSIX 信号量:基于环形队列的生产者消费者模型
本文介绍了POSIX信号量及其在环形队列生产者消费者模型中的应用。POSIX信号量相比SystemV信号量更轻量级,适合多线程编程。通过两个信号量(空位信号量和数据信号量)控制资源数量,配合两把互斥锁保护临界区,实现了高效的线程同步。环形队列利用数组模拟循环结构,生产者关注空位数量,消费者关注数据数量。代码实现中采用先申请信号量再加锁的方案,提高了并发性能。相比传统"互斥锁+条件变量"方案,信号量方案逻辑更直接,在高并发场景下表现更优。
2026-02-04 18:08:36
11373
32
原创 Linux 多线程:生产者消费者模型、阻塞队列与条件变量详解
生产者消费者模型是一种通过缓冲区(如阻塞队列)解耦生产者和消费者的并发设计模式。生产者将数据放入队列后无需等待消费者处理,消费者直接从队列获取数据,从而平衡两者处理速度差异。该模型涉及三种线程关系:生产者间、消费者间互斥竞争,生产者和消费者间存在互斥与同步关系。代码实现需使用互斥锁保护共享队列,并通过条件变量实现线程等待/唤醒机制。特别要注意使用while循环而非if判断条件,避免"伪唤醒"问题。这种模式广泛应用于多线程编程中,有效解决了线程间安全高效通信的问题。
2026-02-02 22:51:53
11705
34
原创 Linux 多线程编程入门:线程栈、TLS、互斥锁与条件变量详解
本文深入探讨了Linux系统中线程的实现原理与同步机制。主要内容包括:1)Linux通过clone系统调用实现轻量级进程来模拟线程,线程栈由pthread库管理;2)验证了线程私有栈与共享全局数据区的特性,介绍了__thread线程局部存储;3)分析了多线程共享资源的并发问题,详细讲解了互斥锁的原理与实现;4)引入条件变量解决线程同步问题,避免线程饥饿现象。文章通过代码示例展示了线程创建、资源竞争、互斥锁和条件变量的实际应用,揭示了多线程编程中数据安全与同步的关键技术。
2026-01-27 22:53:17
12047
29
原创 《Linux线程原理详解:进程、轻量级进程(LWP)与pthread实战》
本文摘要:本文深入探讨了Linux系统中的线程概念及其实现机制。线程作为进程内的执行分支,共享进程资源但拥有独立执行流,相比进程具有更轻量的创建和切换开销。文章详细分析了线程与进程的区别,指出线程是操作系统调度的基本单位,而进程则是资源分配的基本实体。通过代码示例展示了线程创建、参数传递、等待和退出的具体实现,并解释了pthread_t与内核LWP的区别。文章还讨论了线程共享地址空间的特性及其带来的优缺点,包括通信便利性与健壮性问题。最后,通过对比进程与线程的切换过程,阐明了线程在Cache友好性方面的优势
2026-01-24 23:52:06
12633
39
原创 深入理解 Linux 信号机制:从 task_struct 到信号递达全过程
本文深入探讨了Linux信号机制的工作原理与实现细节。主要内容包括:1) 信号存储采用位图方式而非数组,节省空间;2) 进程通过handler表、pending表和block表三张内核表管理信号处理;3) 信号递达发生在进程从内核态返回用户态时;4) 演示了信号屏蔽、解除及自定义处理的完整流程;5) 利用SIGCHLD信号实现子进程异步回收,避免父进程阻塞等待;6) 分析了可重入函数概念及信号处理期间的自动屏蔽机制。讲解了SIGCHLD信号的应用,演示了如何通过信号处理实现子进程的异步回收,避免僵尸进程产生
2026-01-21 18:49:02
12879
30
原创 从除 0 到 SIGPIPE:Linux 信号的真正来源
本文介绍了Linux系统中的信号机制,包括信号的概念、产生、保存和处理过程。信号是进程间通信的一种方式,用于通知进程发生了特定事件。文章通过生活实例类比解释了信号处理的三个阶段:产生、保存和执行。详细阐述了信号的默认处理、忽略和自定义三种处理方式,并通过代码示例验证了ctrl+c对应2号信号。同时探讨了键盘输入转化为信号的机制、异常产生信号(如除零错误和野指针)的原理,以及alarm定时器和核心转储功能。最后指出只有9号和19号信号不能被自定义,其他普通信号均可被进程捕获并自定义处理。
2026-01-18 21:45:18
13154
17
原创 System V 消息队列与信号量
本文探讨了SystemV标准下的消息队列和信号量机制。消息队列通过内核中转数据块实现进程通信,相比共享内存更安全但效率较低。文章详细介绍了消息队列的接口函数及内核数据结构设计。针对SystemV IPC缺乏同步机制的问题,重点阐述了信号量的原理:作为计数器实现资源预定,通过原子性P/V操作(申请/释放)保证临界资源访问安全。特别指出二元信号量(0/1)实现互斥访问的机制。文章揭示了操作系统管理IPC资源的数组方式,并强调信号量在解决并发控制问题中的关键作用。
2026-01-15 15:16:45
13074
14
原创 命名管道和共享内存
本文介绍了命名管道(FIFO)和共享内存两种进程间通信方式。命名管道通过特殊文件让无血缘关系的进程通信,对比普通文件详述了FIFO的特性:不落盘、必须成对使用、内存级缓冲区等,并提供了mkfifo/unlink接口实现代码。共享内存则通过系统调用创建内核空间,映射到不同进程地址空间实现高效通信,详细讲解了shmget/shmat/shmdt/shmctl等接口和实现原理,强调其速度快但需自行维护同步的特点。最后通过代码示例展示了两种通信方式的具体应用,分析了共享内存的结构体属性。
2025-10-22 08:30:07
8433
64
原创 从零实现一个简易进程池:基于匿名管道的任务分发模型
本文深入解析了进程间通信(IPC)的概念与实现方式。文章首先指出进程独立性导致通信困难,需要通过操作系统提供的共享资源实现数据交互。重点介绍了匿名管道通信机制,其本质是让父子进程共享内存级文件资源,通过pipe()系统调用创建单向通道。文章详细分析了管道的4种工作状态、字节流特性及生命周期随进程的特点,并通过一个进程池的完整案例演示了多进程+管道通信的实际应用。案例展示了父进程分发任务、子进程执行任务的模型,特别强调了正确管理文件描述符的重要性,最后提供了完整的代码实现。
2025-09-18 16:07:06
7698
22
原创 如何实现静态库与动态库的制作
这篇博客介绍了 Linux 下静态库(.a)与动态库(.so)的原理与应用。静态库在编译时直接打包进可执行文件,运行不依赖库文件;动态库需在运行时由系统加载,支持共享,节省内存。文中展示了静态库的生成流程(目标文件 → ar 打包)及动态库的制作方法(-fPIC 生成位置无关代码,-shared 输出 .so),并说明了通过环境变量或 ldconfig 让系统找到动态库。最后结合 ELF 文件结构与地址空间,解释了动态库需位置无关代码的原因,并实验对比了两类库在运行时的差异。
2025-09-13 21:05:03
7938
22
原创 深入理解 Linux 磁盘文件存储:inode、扇区与数据块
本文深入探讨了Linux文件系统在磁盘中的存储与管理机制。文章首先介绍了磁盘的基本物理结构和工作原理,包括扇区、磁道、柱面等概念,以及CHS寻址方式。随后详细讲解了磁盘的逻辑抽象方法,将物理磁盘转换为线性扇区数组。重点分析了文件系统的核心组成部分。文章还解释了文件创建、删除、查看和修改时系统的内部操作流程,以及inode与文件名的映射关系。最后对比了软链接和硬链接的区别,指出软硬链接中需要注意的核心事项。通过这篇文章,读者可以全面了解Linux文件系统在磁盘层面的工作原理。
2025-08-19 08:55:35
8082
25
原创 C 语言 FILE * 与操作系统中文件机制详解
本文从文件操作的基本概念出发,深入探讨了文件描述符、缓冲区等底层原理。首先分析了文件由内容和属性组成。通过C语言文件接口与系统调用(open/write/read等)的对比,揭示了高级语言对系统调用的封装本质。重点剖析了文件描述符的分配规则和重定向原理,解释了标准输入/输出/错误流的本质。最后通过缓冲区刷新策略(行缓冲/全缓冲)的差异,说明了fork()后输出行为不同的原因,并阐述了缓冲区存在的必要性。全文通过大量代码示例,从应用层到系统层逐步深入,帮助读者理解文件操作的底层机制。
2025-08-19 08:55:05
8600
23
原创 Linux文件系统详解——内存中打开的文件(缓冲区部分)
摘要:本文探讨了C语言缓冲区对程序输出的影响。当使用C标准库函数(如printf)时,数据会先存入用户缓冲区,而系统调用(如write)则直接写入内核。向显示器输出时采用行缓冲(遇'\n'刷新),向文件输出时采用全缓冲(需手动刷新或缓冲区满)。在fork()后,父子进程共享缓冲区内容,导致全缓冲模式下数据被重复写入。此外,exit()会刷新用户缓冲区,而_exit()则直接退出不刷新。这些机制解释了为何不同输出方式会呈现不同结果,缓冲区的存在是为了提高I/O效率。
2025-08-19 08:46:18
5028
9
原创 Linux文件系统详解——内存中打开的文件(原理部分)
Linux文件系统原理:进程通过文件描述符(fd)管理打开的文件,内核使用struct file结构体描述文件信息。文件描述符本质是数组下标,0/1/2分别对应标准输入、输出和错误。通过实验验证了文件描述符分配规则(从最小可用位置开始)和重定向原理(使用dup2系统调用)。文章还解释了stdout与stderr的区别,以及"Linux下一切皆文件"的设计理念:通过VFS统一管理外设,将设备操作抽象为文件操作。最后通过代码示例展示了重定向的具体实现方式。
2025-08-19 08:43:22
4043
8
原创 Linux文件系统详解——内存中打开的文件(使用部分)
本文探讨了文件操作的本质与实现原理。文章首先指出学生对C语言文件接口的困惑源于缺乏操作系统层面的理解,强调文件=内容+属性的基本概念,并区分内存级和磁盘级文件。通过类比快递管理,说明操作系统对未打开文件的管理机制。详细分析了C语言文件操作函数与系统调用接口的关系,指出所有语言的文件操作最终都封装了系统调用。文章以open、write等系统调用为例,演示如何实现文件创建、写入等功能,并比较了C语言FILE*与系统调用返回的文件描述符fd的区别。最后揭示了文件操作的底层原理。
2025-08-19 08:40:18
4185
10
原创 进程控制->进程替换(Linux)
本文深入探讨了Linux系统中的进程替换机制。通过exec系列函数,子进程可以完全替换当前进程的用户空间代码和数据,转而执行新的程序。文章详细介绍了execl、execlp、execv、execvp等函数的用法和区别,并通过代码示例展示了如何替换系统命令、自定义程序以及跨语言脚本。解释了进程替换的原理,包括写时拷贝技术如何保证进程独立性。特别说明了execle和execve函数如何传递环境变量,以及如何自定义环境变量。文章指出,虽然exec系列函数有多个变体,但最终都调用execve这个系统调用实现进程替换
2025-07-25 21:35:22
7606
2
原创 进程控制->进程等待(Linux)
本文详细介绍了进程等待机制。通过具体的代码示例,解释了父进程如何使用wait和waitpid系统调用回收子进程资源,防止产生僵尸进程,从而避免内存泄漏。文章还分析了如何通过status参数获取子进程的退出信息,包括退出码和终止信号,并结合位运算与宏函数WIFEXITED、WEXITSTATUS进行解析。此外,还介绍了非阻塞轮询的实现方法,使父进程可以在等待子进程的同时继续执行自己的任务,提升程序灵活性。通过丰富的示例和类比,帮助读者深入理解进程控制的原理与实践应用。
2025-07-12 08:30:00
4286
1
原创 进程控制->进程的终止(Linux)
这篇博客讲解了 Linux 系统中进程控制的核心机制,包括虚拟内存的作用、fork 函数实现的进程创建、进程调度的不确定性、写时拷贝(COW)的原理、进程终止的多种情形(正常结束、异常中止),以及退出码的意义和用法。文中通过多个代码示例演示了父子进程的执行流程、如何使用 exit 和 _exit 终止进程,以及缓冲区刷新策略对输出行为的影响。此外,还介绍了 Linux 信号与错误码机制,为后续深入理解进程替换和信号处理打下基础。
2025-07-08 08:00:00
4230
1
原创 程序地址空间详解(Linux)
在上一篇博客的结尾我们简单介绍了一下程序地址空间,对程序的地址空间分布有了视觉上的感受我们可以看到在栈区是向下增长的,而堆区是向上增长的,因为,我们先定义的变量n1 - n4的地址是逐渐变小的,而在n1 - n4里申请存放的堆区地址是逐渐增大的,所以栈区是向下增长,而堆区是向上增长的。了解了程序地址空间,我们再来看下面这段代码,看看会有什么新奇的事情发生?这段代码的意思就是定义一个全局变量,父子进程同时打印这个全局变量的值和它的地址,子进程在过一段时间后对全局变量的值进行改变,结果会发生什么呢。
2025-06-24 21:24:07
4089
原创 进程的详解,命令行参数,程序的地址空间(Linux)
在上一篇博客结束的时候,我们了解了僵尸进程,现在我们接着僵尸进程继续往下探索,所谓的僵尸进程就是当子进程退出时,父进程如果一直不对子进程进行回收,子进程的状态就会一直变成僵尸状态(Z状态),这就好比你的女朋友给你分享了一个很有意思的视频,希望可以和你得到情绪共鸣。但是你呢,经常打游戏打的什么都顾不上,而在那边你女朋友一直等待你回复一下这个视频好不好看,但是迟迟等不到你的回复。此时,你女朋友的状态就属于僵尸状态,一直等待你的回复。
2025-06-06 19:03:02
4437
原创 STL库容器之一:vector
本文介绍了C++ STL中vector容器的实现原理与关键特性。vector是一种动态数组,使用连续存储空间,支持快速随机访问。与静态数组相比,vector能动态调整大小,其核心实现包含三个指针:_start指向首元素,_finish指向末元素后位置,_end_of_storage指向分配空间末尾。文章详细分析了vector的构造、迭代器、容量管理(resize/reserve)和增删改查操作,重点探讨了迭代器失效问题(由扩容或删除引起)及解决方案。特别指出使用memcpy拷贝资源管理对象会导致浅拷贝问题,
2025-05-29 17:51:19
8028
原创 写时拷贝(Copy-On-Write)
先简单列举一个生活中关于“写时拷贝”的例子,在大家上学的时候,相信大家一定都写过实验报告,每次写实验报告的时候,班级里的学习委员比如就会说,咱们的这个实验报告在这周五下午五点,交到我的手中,我再将实验报告交给老师,爱玩游戏的兄弟们一看,赶紧问一问学习委员这是交什么实验报告呀?学习委员说明情况后,你恍然大悟想到,那天是有一把很重要的游戏晋级赛,所以就没有去那节实验课。
2025-05-24 17:15:17
5226
原创 进程的详细讲解(Linux)
task_struct是Linux描述进程的结构体task_struc是linux内核的一种数据结构,它被装载到内存(RNA)里并包含着进程的信息。task_struct的内容分类标识符:描述进程的唯一标识符,用来区别其他进程。状态:任务状态,退出状态,退出信号等等。优先级:相对于其他进程的优先级。程序计数器(PC):程序中将要被执行的下一条指令的地址。内存指针:包括程序代码和进程相关数据的指针,还有和其他进程共享内存块的指针。上下文数据:进程执行时处理器中寄存器的数据。
2025-05-18 12:17:49
7619
原创 STL库容器之一:string(深浅拷贝以及VS和G++的扩容机制)
STL(标准模板库)中的string容器是C++中用于处理字符串的类,提供了丰富的功能来替代C风格的字符数组,具有更高的安全性和便捷性。以下是对string:需包含<string>。:是的别名,管理动态字符数组,自动处理内存(无需手动分配/释放)。:支持动态扩容、丰富的成员函数、操作符重载,避免缓冲区溢出。接下来是string的一些接口函数,我们挑几个函数进行实现,达到让我们自己写的string可以使用一些基本功能即可。string类对象的成员变量。
2025-05-04 14:50:38
4062
原创 模板和STL库的简单介绍
class 类模板名//类的实现// 动态顺序表public:, _size(0){}// 使用析构函数演示:在类中声明,在类外定义。~Vector();// 注意:类模板中函数放在类外进行定义时,需要加模板参数列表if (_data)注意:类模板的实例化需要在类模板名字后跟<>,将实例化的类型放在<>内即可,类的名字不是真正的类,实例化后的结果才是真正的类。其中vector是类名,vector<int>是类型。
2025-05-03 11:20:54
4239
原创 数据结构-AVL树(图解+全面分析平衡二叉树)
K _key;int _bf;,_key(key),_bf(0){}之所以使用三叉链结构,是因为AVL树的核心是通过平衡因子(BF)调整树的平衡性。当插入或删除节点时,需要沿着路径向上回溯到根节点,逐层更新祖先节点的平衡因子。通过_parent指针可以直接访问父节点,代码更简洁高效AVL树的旋转(左旋、右旋、双旋)需要调整父子节点的指向关系,涉及多个节点的指针修改。通过_parent指针,可以直接修改父节点对子节点的引用,无需从根节点重新定位父节点,减少指针操作的复杂度。
2025-04-09 16:35:40
8189
原创 让我们看看C++类中的默认成员函数到底是什么?(外加常量指针和指向常量指针的区别)
默认成员函数:就是即使类内什么都不写(就像之前我们在类对象的大小那里说的空类),编译器也会自动生成6个默认的成员函数,这6个成员函数称为默认成员函数。
2025-03-31 10:09:11
3940
原创 猜一猜C++类中的对象模型是什么样的?
class Date//由成员函数与成员变量组成class为定义类的关键字,Date为类的名字,{}中是类的主题,同时注意类的定义结束后面的分号不能省略。这样一看会不会觉得类的定义与C语言中的结构体的定义有异曲同工之妙呢?//类型的定义这是因为C++需要兼容C语言,所以C++中的struct既可以当成结构体使用,同时还可以用来定义类。和class定义的类是一样的,两者的区别在于struct定义的类默认访问权限是public,class定义的类默认访问权限是private。
2025-03-31 10:06:28
4083
原创 C++基本知识以及重载的原理和引用(详解)
不论采取何种定义,在使用空值的指针时,都不可避免的会遇到一些麻烦:程序本意是想通过f(NULL)调用指针版本的f(int*)函数,但是由于NULL被定义成0,因此与程序的初衷相悖。在C++98中,字面常量0既可以是一个整形数字,也可以是无类型的指针(void*)常量,但是编译器默认情况下将其看成是一个整形常量,如果要将其按照指针方式来使用,必须对其进行强转(void*)0。所以nullptr是C++11作为新关键字引入的。
2025-03-25 15:00:00
8291
原创 函数栈帧的创建与销毁
函数的栈帧(Stack Frame)是程序执行过程中,用于存储函数调用相关信息的一块内存区域。每当一个函数被调用时,系统会在调用栈(Call Stack)上为其分配一个栈帧,用于保存该函数的局部变量、参数、返回地址等信息。栈帧在函数调用结束后会被释放。
2025-03-21 15:25:54
7534
原创 数据在内存中的存储
大端存储方式:数据的低位在内存中的高地址处存储,数据的高位在内存中的低地址处存储。小端存储方式:数据的高位在内存中的高地址处存储,数据的低位在内存中的低地址处存储。下面解释一下为什么存在大小端字节序:多字节数据类型的存储方式:整数和浮点数通常由多个字节组成,例如4字节整数或8字节浮点数。这些字节需要以某种方式存储在计算机的内存中。问题在于,这些字节应该按照什么顺序存储,高位字节(most significant byte)在前还是低位字节(least significant byte)在前。
2023-10-22 17:58:04
221
2
原创 井字棋游戏
这个C语言实现的井字棋游戏是一个非常基础的示例。通过这个项目,我深入了解到了C语言的核心概念,如函数、条件语句和循环。不仅如此,我还可以通过这个项目了解如何管理用户输入和处理游戏规则。无论如何,这个项目为我学习和练习C语言编程提供了一个出色的起点。希望这篇博客对你了解如何使用C语言构建一个井字棋游戏有所帮助,以及为你的编程学习提供了一个有趣的项目方向。
2023-10-15 18:43:26
216
1
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人
RSS订阅