- 博客(291)
- 收藏
- 关注
原创 Linux-进程间通信
管道其实就是一个共享文件,如果一个进程-1打开了这个文件,另一个进程-2也打开了这个文件,那么进程-1往里面写入的内容进程-2也能看到并读取,这就完成了进程之间的数据传输。
2025-03-02 15:11:20
918
原创 Linux-进程与信号
它保存进程收到的、还未递达的信号,无论是否阻塞。收到的信号的对应比特位会置1,没有收到的信号置0。当一个信号被递达了,相应比特位又置0。子进程不会继承父进程的pending。信号给了操作系统和用户一种向进程发送特定事件的方式,而且是不受进程正在执行的代码所影响的,这极大地提升了管理进程的灵活性。
2025-03-02 12:36:53
791
原创 C++-第二十章:智能指针
智能指针的作用是防止指针出作用域时忘记释放内存而造成内存泄漏,智能指针重载了[]、*、->来模拟原生指针的行为,智能指针包含在<memory>中。智能指针有几种,各有其特点。
2025-03-01 16:14:05
845
原创 C++-第十九章:异常
异常的本质是一个数据,它可以是内置类型、也可以是自定义类型,但是它的数据发生了出乎意料的错误,例如一个购票系统中的剩余票数肯定不是负数,如果发现是负数,说明程序出现了BUG,此时将剩余票数抛出。func1嵌套了fun3,且func3也有对应的处理异常的catch,此时func1的异常就会被func3中的catch捕获并处理。使用 catch(...){} 表示捕获任意异常,一般放在main函数最后,防止程序因为main函数抛出异常却没有相应的catch导致函数退出,进而导致程序崩溃。要保持多态性必须使用。
2025-03-01 15:03:20
665
原创 C++-第十八章:线程相关内容
因为CPU是以时间片轮转的形式运行线程,如果线程1进入 if 后,此时tickets为1,线程1还未执行 tickets-- 就被剥离CPU了,线程2判断 if 时,因为tickets还是1,线程2也会执行一次 tickets--。唤醒所有线程后,这些线程仍然需要先竞争条件变量中的锁,竞争到锁的一个线程才能执行后面的代码,其他线程没有继续休眠,而是阻塞等待锁被释放,然后竞争锁。mutex的意思就是锁,它就像锁一样,锁住其他线程,不让它们继续执行代码,直到拥有锁的线程解锁。
2025-03-01 11:28:08
927
原创 C++-第十七章:包装器
模版参数包就包含了可调用对象的所有参数类型。std::bind(可调用对象,占位符1,占位符2,...);占位符有多个,而且占位符与参数是一一对应的,占位符1表示第一个参数,占位符2表示第二个参数。
2025-02-28 23:43:47
659
原创 C++-第十六章:lambda表达式、新的类功能
捕捉列表](参数)->returntype{函数体};相较于普通的函数,它没有函数名,但是多了一个捕捉列表,捕捉列表的作用和参数类似,函数体可以使用捕捉列表中的变量。")};")};所以捕捉列表和函数体就是lambda表达式不可省略的部分。模版中...在前,函数中...在后,传参...在括号内,原地分解...在括号外。获取参数包的参数个数:sizeof ...(args);
2025-02-28 19:31:00
608
原创 C++-第十五章:C++11新增内容
简单来区分,右值就是不能被取地址的数据,左值就是可以被取地址的数据。右值包括:字面常量、匿名对象、临时对象、表达式返回值。字面常量:&10;匿名对象:&(class A(1,0));临时对象:&(std::to_string(123));表达式返回值:&(x+y);以上操作都是不被允许的。不能取地址的原因是右值的生命周期只在当前语句(将亡值),取地址是无意义的。而且它们都具有一定的常性,本身是无法修改的。可以把右值理解为只可以读取,不能修改的数据。int *p = a;&(*p);
2025-02-28 14:39:08
582
原创 C++-第十四章:哈希
哈希其实就是一种映射,它将元素的值与存储位置[下标]建立映射。映射的规则是使用数值%哈希表空间得出的结果就是该元素保存的位置,这种方法叫做除留余数法。例如一个哈希表的容量为10,现在有数据100需要保存,此时将100%10==0,那么100就保存在下标为0的位置,同理99保存在下标为9的位置,99反而在100前面,所以哈希表是无序的。
2025-02-28 10:29:28
673
原创 C++-第十三章:红黑树
综上,其实一共就两种情况:(1)par为红时:一定有一个黑色的gra,unc为变量a.unc为红:Ⅰ.par、unc变黑,gra变红 继续向上调整b.unc为黑/不存在:Ⅰ.cur在外侧:单旋+par、gra变色 然后直接结束Ⅱ .cur在内侧:双旋+cur、gra变色 然后直接结束(2)par为黑时:直接结束C++-第十章:搜索二叉树-CSDN博客。
2025-02-27 22:38:57
672
原创 第十七章:联调测试
第一节:生产者客户端这个客户端向e1交换机发送了10条持久化消息,内容是"Hello World-i",routing_key都是"news.music.pop"。
2025-02-26 12:37:02
764
原创 第十一章:服务器信道管理模块
服务器信道的作用是处理来自于客户端的各种请求,然后返回一个响应,那么客户端都有哪些请求呢?比如:交换机的声明与创建、队列的声明与创建、绑定与解绑等。请求的种类如此多,信道要怎么识别这些请求,执行对应的任务呢?这就需要用到muduo库的协议分发器了:只要将每种请求各自封装成proto的结构体,然后实现每个请求的业务函数,并将对应请求的结构体和业务函数进行注册绑定,那么服务器在收到请求之后就会自动识别请求的结构体类型,去调用绑定的业务函数了。
2025-02-26 08:49:50
707
原创 第三章:工作线程池
工作线程池的作用是缓存一些不着急完成的任务,这些任务由子线程来完成,以达到削峰填谷的作用。在消息队列中,客户端的信道发送请求时,会把请求抛入线程池,由子线程发送请求,主线程继续发送其他请求;服务器推送消息时,也会把推送任务抛入线程池,由子线程完成,主线程继续接受其它请求。
2025-02-24 21:46:26
486
原创 第二章-续:辅助功能
序列号由一个静态原子变量维护,number是一个4字节(32比特)的数据,每次将序列号的8个比特位转成两位的十六进制,处理8次,就可以正好处理了32比特。FileHelper的其他功能函数可以自己去测试,这里不再演示了,唯一需要注意的是重命名函数的参数需要带上路径,不然重命名后的文件就在mqtest路径下了。前缀随机数由8个int类型的随机数组合而成,共32字节,因为最大的随机数是255,转成十六进制后最多两位,一位又以"0"填充,这样让每个前缀都是16位。
2025-02-24 20:43:53
902
原创 第二章:辅助功能
/ 声明版本package zd;// 声明命名空间声明版本就是使用最新的proto3语法,它的语法是做过优化的;声明命名空间的意思就是下面的内容都在名字为"zd"的命名空间中定义。// 交换机的发布模式// 因为只能从0开始,使用它占据0DIRECT = 1;// 直接模式FANOUT = 2;// 广播模式TOPIC = 3;// 主题模式交换机的发布模式与交换机的消息审核有关:(1)直接模式:每个消息都有一个"钥匙"数据,每个绑定也有一个"钥匙"数据,钥匙内容完全相同才成功。
2025-02-24 17:26:55
789
原创 第一章:项目简介
该项目是一个简化版的仿RabbitMQ消息队列,其内部实现了消息队列服务器以及客户端的搭建,并支持不同主机间消息的发布与订阅、消息推送功能。项目所用到的技术:(1)基于muduo库实现的底层网络通信服务和客户端的搭建(2)基于protobuf协议的应用层协议接口(3)基于轻量数据库sqlite的数据持久化管理功能(4)基于AMQP模型(高级消息队列协议)实现整个消息队列模块的整合(5)使用gtest框架进行模块单元测试。
2025-02-24 12:41:57
678
原创 C++-第十一章-加餐:实现一个简单的map
但是Erase需要注意,map是传入key删除整个key-value,所以我们也传入key,然后将这个key初始化为一个MyPair再传入 _bst 的Erase,这样就能保持类型一致性。Node的默认构造中,val的缺省值使用的是0,但是这是不恰当的,因为如果T的类型是一个自定义类型,而这个类型不能用0来初始化就会报错,所以我们直接使用T()调用T默认构造来初始化它自己。之前已经了解到map中存储的是键值对 pair,所以我们的map也需要自己简单的实现一个pair。第十章的搜索二叉树需要进行一些修改。
2025-02-14 13:04:29
903
原创 C++-第十一章:map与set
所以初始化列表{ {"一",1}, {"二",2}, {"三",3} }中的{"一",1}也是一个初始化列表,它创建了一个pair类型的对象,其中"一"赋值给first,1赋值给second。map和set是基于搜索树的容器,换言之,它们会对存储的数据进行排序,而且不允许相同元素的存在。而map不允许相同key的键值对存在,它的排序也是按照key的规则进行排序。set是key模型的搜索树,map是key-value模型的搜索树。初始化列表中的{"一",1}就是一个key为"一",值为1的键值对。
2025-02-12 10:56:17
994
原创 C++-第十章:搜索二叉树
搜索二叉树是一种二叉树,其特征是左节点一定比根小,右节点一定比根大,即左节点<根<右节点。这样一来寻找每个值时,当前节点小就向右走,当前节点大了就往左走,一次比较可以排除一层的节点,效率是很高的,时间复杂度为O(LogN)。搜索二叉树可以很简单的增加节点,但是不允许保存相等的数据,也可以使用代替法删除节点。
2025-02-11 23:40:09
739
原创 C++-第九章:多态
当子类对父类虚函数进行重写时,子类虚表位置的父类虚函数不变,虚表会新增重写后的虚函数地址,之前已经说到多态的原理是子类继承的父类切片中,虚表指针被替换成了子类的虚表指针,所指向的虚表是新拷贝的虚表,所以只需要子类当中的父类切片就能实现访问子类的虚表了,这就意味着。ptr1虽然类型是父类,但是它指向的是子类,那么按照常理来说应该是半价才对,所以只使用函数重写是不能达到多态的要求的。虚函数不保存在类中,而是在类中形成一个虚表指针,这个指针指向一个虚函数表(简称虚表),虚函数表用于存放虚函数的地址。
2025-02-02 12:36:20
952
原创 第十章:大内存的申请和释放
这样一个简化的高并发内存池就完成了,这是tcmalloc的简化版本,学习项目的主要目的还是学习大佬的代码思路。这是我学习的第一个项目,这种内存相关的bug真的是不好找,有时候一个bug要找几个小时,但是我仍然还是坚持下来了。我学习到了找bug的技巧、大佬的代码思路,这个项目完成后,我要需要马不停蹄的学习下一个项目了。路漫漫其修远兮,吾将上下而求索。
2025-02-01 21:39:25
365
原创 第九章:内存池的调整与测试
我的电脑是32位系统,那么就有2^32B空间,然后一页设置为8K,即2^13B,那么电脑中最多存在2^(32-13)个span,故需要2^19个位置来保存所有span。可以看到内存池的花销还是比较大的,这是因为pc中每次通过地址找span时都需要上锁,锁的花销太大了,所以需要找一种方式代替哈希映射,而且这种方式不需要上锁。基数树就是一种多级映射,但是每个span都有自己专属的位置,这样访问一个span的时候其他span的位置就不会受到影响,也就不需要上锁了。可以看见,内存池的速度已经超过malloc了。
2025-02-01 19:11:40
1263
原创 C++-第八章续:继承
假如Person中保存了名字和身份证号码等信息,那么对于Assistant来说,它有两份Person,当访问名字时就不知道访问继承自Student的名字还是Teacher的名字,就必须使用显式调用,此为二义性问题。那么子类的析构函数名为~Student,父类的析构函数名为~Person,看起来是不一样的,但是类的析构函数的名字实际上都是destructor。这就意味着子类有两个析构函数,一个是它自己的,一个是从父类继承的,因为都叫destructor,所以子类析构函数会对父类析构函数造成屏蔽。
2025-02-01 11:26:00
812
原创 C++-第八章:继承
子类虽然从父类继承了一些成员,但是子类中也可以定义与继承来的成员同名的成员,这样做的话会把继承而来的成员进行屏蔽(也叫重定义),直接调用时也只会调用到新定义的同名成员。那么子类中的父类成员可以看作在子类中的一个自定义类型,那么根据类的默认构造所做的工作:内置类型不作处理,自定义类型调用它的构造函数。现实生活中的继承就是下一代获得上一代的经验、责任、财产等,类的继承类似,继承的类会获得被继承类的一些成员变量和成员函数。实际上子类的默认构造函数调用了父类的构造函数来初始化从父类继承而来的成员。
2025-01-31 21:37:59
685
原创 C++-第七章:模板进阶
之前说了类,其实也说完了类的封装,迭代器就是一个体现封装意义的很好的例子,这里再说一遍封装:就是屏蔽了底层的细节,给用户一个简单交互接口即可,就像电脑开机只需要按下电源键,不需要自己去焊接电线、启动驱动等。所谓"特化"就是将特殊情况的模板再写一遍,然后函数会根据参数找最符合的模板。模板特化就是针对一些相似的场景,要达到相同的功能,直接使用模板会导致功能无法正常实现,但是只需要略微修改就可以完成任务的情况。非类型模板参数就是允许传入一个确切的值,而不是类型来作为模板参数,这一点可以类比函数传参。
2025-01-31 15:50:49
812
原创 第八章:Central Cache释放内存和Page Cache合并内存
代码进行到这里可以发现span会被频繁的进行new和delete,又因为一个Span类的大小是固定的,此时就可以使用之前写的定长内存池对new和delete进行替换。上一章我们说到tc将内存块链表给到cc之后,cc将内存块一个一个的归还到相应的span了。这个函数的作用是将从cc归还到pc的span与前后页的其他span进行合并,这样就能得到一个更大的span。定长内存池定义在pc中,然后简单的替换代码即可,这里不作演示。(1)发现没有span了(中断了)(2)将合并的span正在被使用。
2025-01-31 11:42:44
464
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人