- 博客(111)
- 收藏
- 关注
原创 桶子排序算法理解
当数据越多时候越乱时刻,桶排序就可以以及其快速的并且具有稳定性的方式完成对数的排序,这是一个优秀的算法让我们看看这个牛皮算法是如何做到的。
2024-05-01 10:50:31
109
原创 项目总结-自主HTTP实现
终于是写完了,花费了2周时间,一点一点看,还没有扩展,但是基本功能是已经实现了。利用的是Tcp为网络链接,在其上面又写了http的壳。没有使用epoll,多路转接难度比较高,以后有机会再写,使用了多线程来对每一个链接请求做工作,每次处理一个工作后,响应结束后,服务器主动关闭对端链接,做到短链接,防止服务器链接过载宕机,主要是我的云服务器是学习用的,硬件就摆在哪里,过多的链接会导致我服务器崩溃,这是没有办法的呀。ThreadPool类:线程池一次性启动一堆线程,循环的方式等待任务队列有东西,有就拿,没就等。
2023-12-13 23:33:27
1263
原创 基于epoll实现Reactor服务器
创建epoll模型:调用epoll_create,在文件描述符表添加一个描述符,生成对应的文件结构体结构体保存对应生成eventpoll结构体的地址,该结构中有rbr(监视事件红黑树),rdllist(就绪事件队列)等等。添加一个fd到epoll中:调用epoll_ctl,通过epollfd在进程文件描述符表中找到对应的file,然后在对应的文件结构体中的标识符将特定指针强转为eventpoll,访问rbr,增加新结点在树中,并且添加对应的回调函数到对应fd的文件结构体中。
2023-12-07 00:36:31
1258
原创 多路转接<select>和<poll>使用手册
注意,这里的指针并不意味是只有一个pollfd,这里的指针是可以看成pollfd[NUM]的一个数组的,这个数组大小并不受约束,并且我们在堆创建,允许扩容realloc,每一个元素都是对应着一个文件描述符,管理着一个文件描述符。调用函数,他会管理设置在3个fds中的所有文件描述符,只要其中文件描述符中允许写入或者有数据可读取,返回并且设置这3个fds,以输出型参数方式返回给上层。最后一个参数timeout:是一个用毫秒表示的时间,是指定poll在返回前没有接收事件时应该等待的时间。fds是一个结构体数组。
2023-11-30 19:28:23
1018
原创 事务对隔离性的原理理解
我们之前所讲的所有 机制:索引,事务,隔离性,日志等,都是在内存中完成的,即在 MySQL 内部的相关缓冲区中,保存相关数据,完 成各种判断操作。因为`insert`是插入,也就是之前没有数据,那么`insert`也就没有历史版本。Read View就是事务进行 快照读 操作的时候生产的 读视图 (Read View),在该事务执行的快照读的那一刻,会生成数 据库系统当前的一个快照,记录并维护系统当前活跃事务的ID(当每个事务开启时,都会被分配一个ID, 这个ID是递增 的,所以最新的事务,ID值越大)
2023-11-23 14:33:39
810
原创 当你在浏览器地址栏输入一个URL后,将会发生的事情?个人笔记
校园网就是最好的正向代理服务器代表,链接校园网的设备,向外界访问资源的时候,所有的请求都会经过该服务器,我们可以将其看成一个巨大的路由器,但是服务器允许缓存资源预设在代理服务器中,打个比方,2个主机同时访问抖音服务器,A主机先B主机后,A、B主机访问的资源相同,服务器在访问数据后会预留一段时间,当B再来访问时候,直接从代理服务器中获取资源,不用再去抖音服务器访问,大大的提高了我们的网络读写效率,并且正向代理服务器会检查访问的合法性,访问的内存合法性。自从上次请求后,请求的网页未修改过。
2023-11-02 08:44:24
578
1
原创 ip划分与私公网ip、ip的传递
报文问路:1、不知道跳转默认路由器,2、知道路径,向对应路径发出报文,3、路口路由器,下一步就是目标主机在哪。想要通信必须同在一个局域网,其实将公网就可以看作一个大型的局域网。在同一个局域网内发送报文会被其他主机看到包括自己,如果发送报文的主机发现其他人,数据碰撞可能导致数据错乱无法避免,当然发送的主机也会知道,然后启动碰撞避免算法,发送主机进入随机休息时间,然后重新发送报文。同一个局域网内的主机越少越好,避免碰撞,一个网络中报文越短越好, 传输数据时间短避免碰撞。交换机:一个局域网我们分左右,
2023-10-30 14:21:01
620
原创 ip报头和ip报文切片组装问题
16位标识:每一个在网络层组装的报文都是不同的16位标识,类似于tcp层的32位序列号,这个序列号是区分不同报文的序列号,如果从网络得到相同的16位标识的报文,那么报文就是被切片了。3位标识:1位待用,1位禁止切片的标识,如果某个报文该位被设置,但是又过大,那么就直接将其报文丢弃。1位更多分片标志位,如果有报文该位被设置1,那么其报文之后一定还有报文在路上,如果被标识为0,原可能未被分片,或者是分片的最后一片。13位分片位置:就是该分片在原报文中的起始位置。分片好吗?如何识别ip报文的不同。
2023-10-22 20:12:50
977
原创 tcmalloc 框架介绍
tcmalloc解决锁频繁加锁解锁以及缓解锁竞争问题,尤其是在多线程并发申请内存的时候,相比malloc效率大大提升。20轮,每次8个线程,每次个线程申请10000次,释放10000次;malloc和我们的tcmalloc相比,malloc像个万金油,哪里都能有,但是哪里都不突出,所以在多线程高并发申请内存的过程中相比tcmalloc,malloc内存池申请是缓慢的。所以,我们创造tcmalloc内存池解决高并发效率问题。tcmalloc有3层结构,分别是ThreadCache层、Central
2023-10-19 18:15:01
177
原创 拥塞控制概念
何为拥塞控制?拥塞控制是指在计算机网络中,通过监测网络的拥塞程度并采取相应的措施来维持网络的稳定运行的方法。它的主要目标是确保网络资源的合理利用,避免网络拥塞导致的性能下降和服务质量下降。为什么需要拥塞控制?因为我们的网络也会拥塞网络拥塞是指在网络中传输的数据量超过了网络设备(如路由器、交换机)的处理能力,导致网络性能下降或者完全不可用的现象。
2023-09-17 18:01:30
709
2
原创 滑动窗口的理念
注意,虽然滑动窗口为0,无法再次发送携带数据的报文,但是会发送探测窗口报文(探测对方接收能力的报文),对应探测报文的确认应答返回,我们就知道了对端现在是否有剩余的空间允许我发送报文。当然接收方一旦倒腾出剩余也会发送窗口更新报文,通知我可以发送带数据报文了。我们知道当一个报文长时间未得到应答,就会发起超时重传。
2023-09-17 16:20:25
206
原创 UDP与TCP报头介绍,三次握手与四次挥手详谈
为了节约紧凑数据,降低内存对齐问题,我们的结构体使用位段结构。不做数据浪费,tcp报头数据结构也是使用位段结构原端口号:发送方的端口号,接收方再给发送方发送数据时候,可以依据端口发送到对应的主机中特定的进程。目的端口号:发送方机器上绑定该端口的进程。UDP长度:整个UDP报文(报头+数据)长度,确定数据长度用的,UDP报头是固定的8字节,所以16位UDP报文长度-8字节就是数据长度。16位UDP检验和:检测这次数据发送情况,如果有误直接将整个报文丢弃。检验和的检测我们后面讲完TCP报文后一起说。
2023-09-13 15:11:23
995
原创 弃用http改用https的缘故,与密钥的使用,证书意义
一篇文章经过一个hash算法形成一段固定的数字,这就是数据摘要.不论文章字数长度,100w字和1个标点符号生产的数据摘要是一样长的。一个文章只要有一点点哪怕一个符号的改变,经过同一个哈希函数生成的数据摘要都相差甚远。
2023-09-10 13:14:08
539
原创 以udp协议创建通信服务器
in结构体中保存的是ip\port数据,而_un中保存的则是本地的数据udp协议为了本地通信与网络通信同一套接口兼容,所以先将sockaddr_in/_un强转成sockaddr类型传入各个函数,在函数中判断前2个字节类型,来做本地通信或者网络通信。
2023-08-28 17:18:36
513
原创 线程池概念以及代码实现
线程池其实也是一种生产者消费者模型。何为线程池,其实就是在程序运行期间提前申请一批线程在自己的栈中等待任务的到来。将任务投入到线程池中,在线程池中让其中一个线程完成任务。为了让线程池中不让线程闲置着,一般可能会有多个执行流向同一个线程池发送任务,那么就必须需要一个缓冲区来存放任务,提高效率。提前申请一批线程当消费者,对这批线程进行封装,我们就叫做线程池。
2023-08-28 14:36:52
201
原创 生产消费者模型概念以及代码
何为生产消费者模型?在设计的角度上看,普通的进程间通信,可以认为发送信息与接收信息的人是同步的。生产者发信号消费者立刻就会收到。这样的做法虽然提高了效率,但是如果生产者和消费者一旦有一方出现问题就是影响另一方比如:消费者消费数据,生产者也无法运行。必须等等消费者对上次数据处理完毕才并取走数据。生产者生产数据消费者就必须等待生产者生产完毕。所以我们需要中间临时区域。如果生产者生产快了,就间数据放入中间缓冲区,再去运行生产者后续代码。如果消费者快了,直接去缓冲区取数据,不用等待生产者发送数据。
2023-08-28 12:50:46
163
原创 互斥锁的概念,与部分接口
一种对共享数据的保护,防止多线程同时访问共享资源的时,数据混乱的问题。在互斥期间,保证执行流由并行改为串行。任何时刻,互斥保证有且只有一个执行流进入临界区,访问临界资源,通常对临界资源起保护作用 原子性(后面讨论如何实现):不会被任何调度机制打断的操作(有歧义,会被打断,但是无法影响对数据的访问),该操作只有两态,要么完成,要么未完成加锁后,到解锁过程中,只允许一条执行流访问该区块代码,这就是我们所谓的原子性。
2023-08-21 22:56:38
198
原创 线程同步条件变量
在线程互斥中外面解决了多线程访问共享资源所会造成的问题。这篇文章主要是解决当多线程互斥后引发的新的问题:线程饥饿的问题。什么是线程饥饿?互斥导致了多线程对临界区访问只能改变为串行,这样访问临界资源的代码只能一个一个线程访问,如果不加以限制就会导致无序的争抢资源,并且当资源还未准备就绪的情况下也会不停的加锁解锁,浪费CPU资源。第一个问题无序存在,在循环中,有可能会导致部分优先级低的线程无法访问到锁从而无法访问到临界资源,我们称之为。
2023-08-17 17:47:29
112
原创 C++异常使用
catch(...){}放到捕捉异常的最后,在前面的catch都异常不匹配的情况下,最后三个点可以捕捉任意的异常。上级存在匹配,就执行步骤后的代码,func1捕捉异常,从func1开始执行。为了防止我们抛出的异常报错,一般都是在异常捕捉最后处使用捕捉任意异常的。如果没有异常信息没有被catch匹配,就会返回到上级继续匹配。如果一直找没有匹配到,直到main函数栈帧也没有被捕捉就会报错。允许抛出和捕捉各种类型的数据。try:在try部可检测异常。throw:抛出异常处。异常允许多次抛出的。
2023-08-09 21:32:24
176
原创 右值引用与移动语义与完美转发
什么是右值,没有地址临时数据的我们称之为右值我们无法对10、a+a、字符串取地址的值我们称之为右值。因为他们是临时数据,并不保存再内存中,所以我们右值没有地址,也无法被赋值(除const外,左值都可被赋值。注意:左值引用与右值引用可以交叉引用使用,但是需要加些东西。
2023-08-08 15:15:58
90
原创 线程概念linux
线程是程序中负责执行的单位,它可以被看作是进程的一部分,是进程的子任务。线程与进程的区别在于,进程是一个资源单位,而线程是进程的一部分,它只有栈这个独立的资源,其他资源如代码段、数据段、堆、环境变量表等都是共享的。一个进程至少有一个线程(主线程),可以有多个线程。线程可以通过同步方式(如pthread_join函数等待)或异步方式(不与主线程有关,无法被等待)来执行。
2023-08-04 12:39:25
721
1
原创 地址空间细致入微+深入了解页表
我们都知道,我们进程看到的空间其实是虚拟内存,真正的内存是需要页表的映射才能找到真正的物理内存,那么我我们有两个问题的引出。
2023-08-03 21:58:50
231
原创 信号执行流程
信号执行是一种用户态与内核态和来回切换,进程不会一接收到信号,就立刻执行,而是在合适的时候执行信号,(手头有重要的事情等等再说。一般来说都是在从内核态返回用户态的时候检测是否有可执行的信号(可执行信号,pending接收,block不为0)
2023-08-03 10:32:11
216
原创 原子操作的重要性
线程中printf函数实际上并不是直接输出,而是把数据放入缓冲区中,因此有可能A线程将打印的2放入缓冲区中,还没来得及输出,这时候B线程打印了3,时间片轮转回来就会后打印2。选项:a=a+1本身就不是原子操作因此有可能同时进行操作,都向寄存器中加载1进去,然后进行+1后,将2放回内存,因此有可能会打印2和2。:先执行I线程foo函数第一行代码,然后跳转执行II线程foo函数,返回后执行foo的后续代码。线程执行2条语句全部执行完毕,再执行。线程重新执行一遍foo函数。其实ABCD都是对的。
2023-08-02 13:39:34
205
原创 信号三表block,pending、handler
结论:在内核态中,从内核态返回用户态的时候,进行信号检测和处理每个进程都有分用户态与内核态,在CPU中有个内用寄存器,保存着当前进程状态的寄存器,他也是个位图,该位图在某个比特位保存当前进程的运行态。为什么会陷入内核态?执行系统调用,缺陷陷阱异常等等,我们的进程就会陷入内核态。如何陷入呢?在汇编指令中有个int 80(不是整型int)
2023-07-31 17:06:17
454
原创 C++继承体系中,基类析构函数请加上virtual,设置为虚函数
当我们将基类的析构设置为虚函数后,pa在delete就会调用B类析构函数,在通过B类的析构函数结束后调用A类析构函数,最后释放空间。当我们delete pa时候,编译器不会调用B类的析构函数在调用A类析构函数,而直接调用A类的析构函数。,在我们delete基类指针的时候,也可以调一下派生类析构,在调用基类的析构。而不是只调用基类的析构函数。我们继承中为将基类析构写虚函数,导致pa指向new的B对象,delete后不调用B类的析构函数。这时候会导致ptrb指向的空间丢失,导致内存泄露,这是我们不希望看见的。
2023-07-24 16:32:03
385
12
原创 reverse_iterator反向迭代器的实现
根据我们的认为下(我真的是只有认为)rend()、end()、begin()、rbegin(),是这样的指向设计。只要是允许双向迭代器(bidirectional iterator)都是这样使用反向迭代器的。我们的利用迭代器遍历我的list是都是从(1)遍历的(5)最后it指向head,结束遍历。如果重新写list反向迭代器,是没有必要的,我们会发现我们的反向迭代器行为是与正向相反的。将我们的反向迭代器指向改成了这样,那么我们的访问数据这是个问题。反向迭代器遍历反向是由数据(5)遍历到(1)的。
2023-07-20 16:07:54
126
2
原创 leetcode1171. 从链表中删去总和值为零的连续节点
我们的sum==X+1的数据已经存在,这时候sum-5后有一次sum==X+1的key值这个时候改变映射表中的x+1的second数据,这样前面的sum保存的指针数据(1),就被hash修改成(5);如果后面的sum依旧出现sum==X+1的情况再一次覆盖,将删除段扩大。判断我们的hash[sum]是否等于当前node,如果不等于说明当前结点开始后面有一段数据和为0,直到hash[sum]结点,假设我们对该链表进行操作,因为这是连续的结点和为0,需要删除,其实我们可以看成,删除链表中的一段结点。
2023-07-16 19:19:12
261
原创 哈希的应用->布隆过滤器
这个是基于位图的一个超级牛皮的一个数据结构。举个例子,假设我们创建Steam账号,我们的账户名字是不允许重复的,所以我们需要找到一个没有人使用过的名字,但是我们得知道现在这个名字是否有人用过,就得去访问服务器数据库查询名字是否被使用,由于服务器的交互远程的方式,所以我们“名字”这个数据需要去服务器中查询是否重复。但是如果一个名字就要直接访问服务器存储空间,效率是底下的,数据在服务器是以磁盘方式存储,在远端又是磁盘存储,访问速度大大降低,你也不想一个名字访问这么久吧?
2023-07-12 14:14:22
163
1
原创 leetcode:174. 地下城游戏:动态规划法
恶魔们抓住了公主并将她关在了地下城dungeon的。地下城是由m x n个房间组成的二维网格。我们英勇的骑士最初被安置在的房间里,他必须穿过地下城并通过对抗恶魔来拯救公主。骑士的初始健康点数为一个正整数。如果他的健康点数在某一时刻降至 0 或以下,他会立即死亡。有些房间由恶魔守卫,因此骑士在进入这些房间时会失去健康点数(若房间里的值为负整数,则表示骑士将损失健康点数);其他房间要么是空的(房间里的值为0),要么包含增加骑士健康点数的魔法球(若房间里的值为正整数,则表示骑士将增加健康点数)。
2023-07-09 22:55:11
496
原创 Linux-vim与gdb与make/makefile
三个模式:命令模式 文本模式 底行模式yum :instell 安装 remove 卸载gcc -o执行后生成文件命名-E预编译-S汇编-c生成机器码Linux 中 静态库:.a;动态库:.soLinux默认动态库,想要静态库编译的时候加上 - static一般来说,linux下编译后的文件是形成release发行版本,如果想要debug发行版本就要在在编译时加上-g指令gdb指令n F10s F11display -变量 常查看变量变化。
2023-07-04 23:46:57
857
原创 哈希桶的增删查改简单实现
个人简单笔记。什么是哈希桶呢?这是一个解决哈希数据结构的一种解决方法,在STL中的unorder_map与unorder_set的底层结构就是使用它来实现的。
2023-07-03 20:10:51
442
1
原创 剑指 Offer 33. 二叉搜索树的后序遍历序列
输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历结果。寻找分割左右的分割点-->从左到右第一个大于根的结点。继续向后,这个时候index比根数据大就向后走,直到大于或小于。假设输入的数组的任意两个数字都互不相同。观察数组我们可以得到一些初始数据。我们的数组就是前半部分值。小于根数据,后半部分值。
2023-07-03 15:36:15
94
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人