- 博客(110)
- 收藏
- 关注
原创 守护进程(linux)
cpp运行#pragma once // 防止头文件重复包含(类似#ifndef的简化写法)#include <cstdlib> // 包含exit()等函数#include <signal.h> // 信号处理(signal())#include <unistd.h> // 包含fork()、chdir()、setsid()等系统调用#include <fcntl.h> // 文件操作(open()、dup2()等)// 根目录路径(用于切换工作目录)// 空设备路径(用于重定向I/O)
2025-11-21 20:01:15
491
6
原创 进程间关系(linux)
之前我们提到了进程的概念, 其实每一个进程除了有一个进程 ID(PID)之外 还属于一个进程组。进程组是一个或者多个进程的集合, 一个进程组可以包含多个进程。每一 个进程组也有一个唯一的进程组 ID(PGID), 并且这个 PGID 类似于进程 ID, 同样是 一个正整数, 可以存放在 pid_t 数据类型中。C++#结果如下# -e 选项表示 every 的意思, 表示输出每一个进程信息# -o 选项以逗号操作符(,)作为定界符, 可以指定要输出的列刚刚我们谈到了进程组的概念, 那么会话又是什么呢。
2025-11-15 13:34:42
822
7
原创 手写序列化与反序列化
本章的主要目的是体会具体序列化和反序列化的过程。本质:就是对字符串的处理实际情况肯定会更复杂,但是序列化与反序列化已经有很多的现成解决方案了。我们只是为了方便理解有一次手写的经历就够了。。C++// 问题// 1. 结构化数据的序列和反序列化// 2. 还要解决用户区分报文边界 --- 数据包粘报问题// 讲法// 1. 自定义协议// 2. 成熟方案序列和反序列化// 总结:// 我们今天定义了几组协议呢??我们可以同时存在多个协议吗???
2025-11-08 14:43:22
682
3
原创 网络版本计算器
我们的网络版本计算器项目就是为了将我们前面谈到的序列化和反序列化带到服务里进行实现。这些虚拟函数通过TcpSocket的实现,完整封装了 TCP 协议的核心操作:从服务端的 “创建 - 绑定 - 监听 - 接连接”,到客户端的 “创建 - 连服务端”,再到双向的 “收发数据” 和 “资源释放”。抽象接口与具体实现分离的设计,既保证了 TCP 操作的规范性,又为扩展其他协议(如 UDP)预留了接口。
2025-11-02 13:55:31
892
10
原创 应用层自定义协议与序列化
toStyledString、StreamWriter 和 FastWriter 提供了不同的序列化选项, 你可以根据具体需求选择使用。Json::Reader 和 parseFromStream 函数是 Jsoncpp 中主要的反序列化工具, 它们提供了强大的错误处理机制。在进行序列化和反序列化时,请确保处理所有可能的错误情况,并验证输入和输出的有效性。
2025-10-24 20:13:15
1081
12
原创 connect 的断线重连
该函数完成了 TCP 客户端与服务器建立连接的核心流程,包括创建 socket、设置服务器地址结构、发起连接并根据结果更新连接状态。
2025-10-18 18:00:11
745
9
原创 Socket 编程 TCP(准备阶段)
accept的返回值,就是 TCP 服务器为 “刚接进来的单个客户端” 分配的专属通信 “服务员”—— 它是后续和这个客户端收发数据的唯一 “接口”,而原始的监听套接字会继续负责 “拉新客”。
2025-09-27 15:53:15
883
15
原创 UDP-Server(3)chat聊天室
在讲解完上一篇文章之后,看过的人我相信对本篇文章要讲的内容已经有基本轮廓了,因为我这篇要讲的内容就是把业务功能切换成聊天室,把聊天室一讲之后我相信大家对udp网络通信的基本逻辑就有了更深刻的认知,那么废话不多说,我们直接开始。
2025-09-14 09:43:06
813
7
原创 UDP-Server(2)词典功能
/ 本主机 localhostif (argc!return 0;这个源文件的作用就是调用我们的服务器类,我们首先接收命令行参数,这里我们只需要两个,一个运行源文件的命令,一个是端口号,至于为什么不需要ip地址我在讲服务器类的时候就已经讲的很清楚了。接收成功后我们将日志打印形式设置成输出到屏幕上,然后将我们的业务类也就是字典类初始化好,我们这里提前准备一个字典的文件,只需要将它的地址给到我们的字典类就可以了。
2025-09-06 15:53:09
920
9
原创 Socket 编程 UDP
该程序实现了基本的 UDP 客户端功能,适合作为简单网络通信的示例,展示了 UDP 协议无连接特性下的数据发送和接收过程。这个类跟我们的多线程代码的代码是一模一样的,我们是直接拿过来用的,所以大家可以直接去看我多线程的那篇文章。我们设计这个类的目的是让我们的实现功能类通过继承它来做到单例模式,这样可以方便我们的代码编写。这个类的作用是帮助我们管理网络信息的基本操作,帮助我们更加快速的获取其ip和端口的信息。,主要功能是创建 UDP 套接字、绑定端口并处理客户端发送的数据。启动方法(Start)
2025-08-31 14:56:47
830
7
原创 Socket 编程预备
我们已经知道,内存中的多字节数据相对于内存地址有大端和小端之分, 磁盘文件中的多字节数据相对于文件中的偏移地址也有大端小端之分, 网络数据流同样有大端小端之分. 那么如何定义网络数据流的地址呢?此处我们的端口号也是唯一表示一个进程. 那么这两者之间是怎样的关系?传输层协议(TCP 和 UDP)的数据段中有两个端口号, 分别叫做源端口号和目的端口号. 就是在描述 "数据是谁发的, 要发给谁";而启动的 qq,迅雷,浏览器都是进程。换句话说,进程是人在系统中的代表,只要把数据给进程,人就相当于就拿到了数据。
2025-08-23 13:21:49
908
7
原创 Linux网络基础(一)
TCP/IP 协议的本质是一种解决方案TCP/IP 协议能分层,前提是因为问题们本身能分层截止到目前,我们还没接触过任何协议,但是如何朴素的理解协议,我们已经可以试试了。OS 源代码一般都是用 C/C++语言写的。下面,仔细看看下面的图问题:主机 B 能识别 data,并且准确提取 a=10,b=20,c=30 吗?回答:答案是肯定的!因为双方都有同样的结构体类型 struct protocol。
2025-08-15 17:12:38
1835
11
原创 线程安全的单例模式,STL和智能指针
单例模式是一种 "经典的, 常用的, 常考的" 设计模式.通俗的来讲,IT行业这么火, 涌入的人很多. 俗话说林子大了啥鸟都有. 大佬和菜鸡们两极分化的越来越严重. 为了让菜鸡们不太拖大佬的后腿, 于是大佬们针对一些经典的常见的场景, 给定了一些对应的解决方案, 这个就是设计模式。
2025-08-09 13:24:33
681
6
原创 线程池的实现
一种线程使用模式。线程过多会带来调度开销,进而影响缓存局部性和整体性能。而线程池维护着多个线程,等待着监督管理者分配可并发执行的任务。这避免了在处理短时间任务时创建与销毁线程的代价。线程池不仅能够保证内核的充分利用,还能防止过分调度。可用线程数量应该取决于可用的并发处理器、处理器内核、内存、网络sockets等的数量。
2025-08-02 22:27:21
1204
3
原创 POSIX信号量及基于它的生产者消费者模型
data_sem是我们消费者关心的信号量,_space_sem是我们生产者关心的信号量。接下来就是设计我们生产者生产任务和消费者消费任务的核心接口:我们先来讲生产者(Push),来到Push这个接口我们就得让资源进行P操作,让资源数量-1,然后在锁的保护下,将任务放入到队列中,将下标进行加一取模,最后我们就可以将消费者的资进行V操作,+1操作。构造函数就是正常的将我们的信号量和锁初始化一下,这里有个要点就是我们的消费者关心的信号量初始值是0,生产者的信号量初始值为_max_cap。
2025-07-24 15:30:44
660
2
原创 生产者消费者模型
生产者和消费者彼此之间不直接通讯,而通过阻塞队列来进行通讯,所以生产者生产完数据之后不用等待消费者处理,直接扔给阻塞队列,消费者不找生产者要数据,而是直接从阻塞队列里取,阻塞队列就相当于一个缓冲区,平衡了生产者和消费者的处理能力。我们先来讲派发(Equeue):我们的思路很简单,首先,为了保证我们代码的安全性,我们需要加锁,我们需要判断队列是否已满,满了就等待消费者去消费,没满我们就可以生产,生产完后就可以通知消费者去消费(若消费者处于等待状态)。为了便于大家理解,我们以双生产者,双消费者,来进行讲解。
2025-07-19 14:37:35
991
2
原创 Linux锁的概念及线程同步
通过预先判断资源分配是否会导致系统进入 “不安全状态”(可能引发死锁的状态),来拒绝或允许资源请求,确保系统始终处于 “安全状态”。死锁是指在一组进程中的各个进程均占有不会释放的资源,但因互相申请被其他进程所站用不会释放的资源而处于的一种永久等待状态。:通过监控系统资源分配状态,判断是否存在死锁的必要条件(尤其是循环等待),并在检测到死锁时触发恢复机制。这段代码的主要功能就是让2个线程分别执行:一个一直等待,另一个每隔1秒唤醒它打印。
2025-07-13 18:41:26
1026
4
原创 Linux线程概念及常用接口(2)互斥
这段代码的代码本身还是很好理解的,无非就是4个线程在那里进行抢票,但是我们看运行结果的时候就会发现:为什么会有两个2呢?为什么会抢到负数呢?要做到这三点,本质上就是需要一把锁。Linux上提供的这把锁叫互斥量。
2025-07-01 14:35:26
627
8
原创 Linux线程概念及常用接口(1)
在一个程序里的一个执行路线就叫做线程(thread)。更准确的定义是:线程是“一个进程内部的控制序列”一切进程至少都有一个执行线程线程在进程内部运行,本质是在进程地址空间内运行在Linux系统中,在CPU眼中,看到的PCB都要比传统的进程更加轻量化透过进程虚拟地址空间,可以看到进程的大部分资源,将进程资源合理分配给每个执行流,就形成了线程执行流。
2025-06-24 14:08:49
903
7
原创 Linux进程信号
每个信号都有一个编号和一个宏定义名称,这些宏定义可以在signal.h中找到,例如其中有定义 #define SIGINT 2编号34以上的是实时信号,本章只讨论编号34以下的信号,不讨论实时信号。这些信号各自在什么条件下产生,默认的处理动作是什么,在signal(7)中都有详细说明: man 7 signal上面所说的所有信号产生,最终都要有OS来进行执行,为什么?OS是进程的管理者信号的处理是否是立即处理的?在合适的时候信号如果不是被立即处理,那么信号是否需要暂时被进程记录下来?
2025-06-22 15:10:32
691
6
原创 共享内存实现进程通信
命名管道(Named Pipe)也称为FIFO(First In First Out)管道。它允许无亲缘关系的进程间进行通信,通过一个在文件系统中存在的名字来标识,进程可以通过这个名字来访问和通信。数据流动是单向的,即数据只能从一个进程流向另一个进程。如果需要双向通信,通常需要创建两个管道。命名管道常用于跨进程通信,并且允许数据以流的方式从一个进程传输到另一个进程。共享内存(SharedMemory)它是映射一段能被其他进程所访问的内存,这段共享内存由一个进程创建,但多个进程都可以访问。
2025-06-15 20:29:25
888
4
原创 命名管道实现本地通信
另一个进程的身份是客户端(我们的使用者),它只会进行我们的写操作。由这个函数我们就知道我们得有命名管道的文件路径名,还有它的权限设置,权限设置我们可以直接传,但我们的路径就可以作为我们的成员变量。我们的构造函数首先将我们的3个成员变量赋值,分别是文件名,身份,自身持有的文件描述符(我们暂设-1,因为还没打开文件),函数内部我们只对创建者进行创建命名管道的动作。查询我们的3号手册我们会发现它是我们C语言库帮我们封装好的一个接口,它的两个参数一个是你的路径名,另一个是你这个命名管道文件的权限。
2025-06-05 20:07:04
1208
5
原创 进程间通信及管道(理论)
数据传输:一个进程需要将它的数据发送给另一个进程资源共享:多个进程之间共享同样的资源。通知事件:一个进程需要向另一个或一组进程发送消息,通知它(它们)发生了某种事件(如进程终止时要通知父进程)。进程控制:有些进程希望完全控制另一个进程的执行(如Debug进程),此时控制进程希望能够拦截另 一个进程的所有陷入和异常,并能够及时知道它的状态改变。管道是Unix中最古老的进程间通信的形式。我们把从一个进程连接到另一个进程的一个数据流称为一个“管道”
2025-05-30 23:21:52
1220
2
原创 Linux理解软硬链接及动静态库
这就是我们前面说的编译的时候会把静态库链接到可执行文件中,所以我们就不再需要静态库了。我们写了如下的几个简单的文件,两个头文件两个.c文件,一个主函数.c文件。我们知道,真正找到磁盘上文件的并不是文件名,而是inode。硬链接是通过inode引用另外一个文件,软链接是通过名字引用另外一个文件,在shell中的做法。动态库不像静态库,我们把动态库移到另一个目录下程序就运行不了了。我们先将方法库汇编成.o文件,然后将他们两个打个包生成静态库。测试目标文件生成后,静态库删掉,程序照样可以运行。
2025-05-22 11:30:23
1077
1
原创 Linux重定向与缓冲区
另外,我们这里所说的缓冲区, 都是用户级缓冲区。printf是C库函数当中的IO函数,一般往 stdout 中输出,但是stdout底层访问文件的时候,找的还是fd:1, 但此时,fd:1 下标所表示内容,已经变成了log.txt的地址,不再是显示器文件的地址,所以,输出的任何消息都会往文件中写入,进而完成输出重定向。发现是结果是: fd: 0 或者 fd 2 可见,文件描述符的分配规则:在files_struct数组当中,找到当前没有被使用的最小的一个下标,作为新的文件描述符。肯定和 fork有关!
2025-05-14 19:26:02
691
4
原创 Linux理解文件fd
打开文件的方式w Truncate(缩短) file to zero length or create text file for writing.如上,是我们之前博客学的文件相关操作。man 2 open我将它们整理一下pathname: 要打开或创建的目标文件flags: 打开文件时,可以传入多个参数选项,用下面的一个或者多个常量进行“或”运算,构成flags。参数:O_RDONLY: 只读打开O_WRONLY: 只写打开O_RDWR : 读,写打开。
2025-05-07 17:03:02
753
8
原创 Linux进程控制
当一个进程调用fork之后,就有两个二进制代码相同的进程。通常,父子代码共享,父子再不写入时,数据也是共享的,当任意一方试图写入,便以写时拷贝的方式各自拷贝一份副本。所以,fork之前父进程独立执行,fork之后,父子两个执行流分别执行。低8位也就是下标8~15,是我们的错误码信息,0~7中前7位是我们的进程信号区,后一位是我们的标志区。可以看到我们的父进程/子进程要修改数据时,为了保证进程间的独立性,操作系统就会采用写时拷贝。衡量一个程序的退出我们只需要看两个,一个退出码,一个退出信号。
2025-04-30 17:30:26
1112
4
原创 Linux程序地址空间
在系统当中查找一个最合适调度的进程的时间复杂度是一个常数,不随着进程增多而导致时间成本增加,我们称之为进程调度O(1)算法!Linux的进程优先级 NI 和 PR - 简书。
2025-04-23 20:56:49
889
4
原创 Linux环境变量
因为我们写的程序都是bash的子进程创建的,父进程的数据被子进程共享,而我们的bash在被加载的时候会创建两张表,一张是命令行参数表(argv【】)接收着我们用户输入的命令行,一张是环境变量表(env[])从os的配置文件中来的,所以我们的子进程能通过各种方式拿到父进程的这两张表。如:我们在编写C/C++代码的时候,在链接的时候,从来不知道我们的所链接的动态静态库在哪里,但是照样可以链接成功,生成可执行程序,原因就是有相关环境变量帮助编译器进行查找。可以看到我们的PATH,我们也可以在后面添加。
2025-04-16 20:01:50
904
4
原创 Linux进程概念及理解
计算机管理硬件1. 描述起来,用struct结构体虽然不同厂商生产出来的硬件不一样,但是这不重要,我们操作系统只关心需要的数据,比如型号,厂商,状态...这些信息大家都是有的我们只需要将这些信息描述好就可以了。2. 组织起来,用链表或其他高效的数据结构描述好后,我们再用数据结构将他们管理起来就可以了。至此,值得关注的进程状态全部讲解完成,下面来认识另一种进程。
2025-04-08 22:07:22
900
1
原创 Linux项目自动化构建工具-make/Makefile
makefile是一个文件,它能帮助我们用make指令进行自动化构建,文件里面的构造是这样的,mytest,clean这些是目标文件,冒号后面的是依赖文件列表,这一行(比如说第一行这种)我们称他们为依赖关系,下面这一行gcc指令我们称他们为依赖方法,我们的make扫描是从上往下扫描,拿上面这个案例来说,我们的操作系统先是扫描到我们需要构建一个目标文件mytest,它需要什么呢?make是一条命令,makefile是一个文件,两个搭配使用,完成项目自动化构建。这是我们可执行文件的修改时间。
2025-04-01 22:49:46
342
2
原创 Linux编译器-gcc/g++使用
最后的答案是:系统把这些函数实现都被做到名为 libc.so.6 的库文件中去了,在没有特别指定时,gcc 会到系统默认的搜索路径“/usr/lib”下进行查找,也就是链接到 libc.so.6 库函数中去,这样就能实现函数“printf”了,而这也就是链接的作用。我们的C程序中,并没有定义“printf”的函数实现,且在预编译中包含的“stdio.h”中也只有该函数的声明,而没有定义函数的实现,那么,是在哪里实“printf”函数的呢?选项“-o”是指目标文件,“.i”文件为已经过预处理的C原始程序。
2025-03-25 20:07:52
694
1
原创 Python基础语法(2)
条件语句能够表达 "如果 ... 否则 ..." 这样的语义. 这构成了计算机中基础的逻辑判定条件语句也叫做分支语句, 表示了接下来的逻辑可能有几种走向.一个典型的例子:如果丘处机没有路过牛家村,1. 那么金兵不会死在郭, 杨两家手上2. 郭, 杨两家就不会流亡北方3. 郭夫人就不会去到大漠, 完颜洪烈就不会遇到包惜弱4. 郭靖就不会和江南七怪救了铁木真5. 蒙古就不会统一6. 蒙古铁骑就不会西征7. 欧洲就不会出现火药, 也就不会出现文艺复兴, 大航海.
2025-03-18 22:05:47
1109
4
原创 Linux开发工具----vim
三种模式正常模式 插入模式 底行模式我们一共有12种总模式,大家下来可以研究一下vim操作打开,关闭,查看,查询,插入,删除,替换,撤销,复制等等操作。
2025-03-11 16:27:47
1127
3
原创 Python基础语法(1)
a = 10创建变量的语句非常简单, 其中a 为变量名. 当我们创建很多个变量的时候, 就可以用名字来进行区分.= 为赋值运算符, 表示把 = 右侧的数据放到 = 左侧的空间中.注意: 变量的名字要遵守一定规则.硬性规则(务必遵守)变量名由数字字母下划线构成.数字不能开头.变量名不能和 "关键字" 重复.变量名大小写敏感. num 和 Num 是两个不同的变量名.软性规则(建议遵守)变量名使用有描述性的单词来表示, 尽量表达出变量的作用.
2025-03-04 14:16:20
809
5
原创 Linux 软件包管理器 yum
在Linux下安装软件, 一个通常的办法是下载到程序的源代码, 并进行编译, 得到可执行程序.但是这样太麻烦了, 于是有些人把一些常用的软件提前编译好, 做成软件包(可以理解成windows上的安装程序)放在一个服务器上, 通过包管理器可以很方便的获取到这个编译好的软件包, 直接进行安装.软件包和软件包管理器, 就好比 "App" 和 "应用商店" 这样的关系.
2025-02-25 16:52:16
416
8
原创 Linux权限的概念
超级用户:可以再linux系统下做任何事情,不受限制普通用户:在linux下做有限的事情。超级用户的命令提示符是“#”,普通用户的命令提示符是“$”。su [用户名]切换用户。例如,要从root用户切换到普通用户user,则使用 su user。要从普通用户user切换到root用户则使用 su root(root可以省略),此时系统会提示输入root用户的口令。
2025-02-18 12:22:40
623
2
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人
RSS订阅