自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(77)
  • 收藏
  • 关注

原创 C++17(新特性)

C++为了区分同名变量通过域作用限定符来访问不同的对象,也就是对象被封到命名空间李了,如果命名空间嵌套的太深了,太冗余了,C++ 17 给了一套新的定义方式。// C++ 17 之前{}// C++ 17int a = 10;

2025-10-31 18:45:35 841

原创 TCP(滑动窗口/拥塞窗口补充)

方案,如果对端已经收到所有的报文或者刚连接什么也没发,也就是发送的报文全部都 ACK 了,则无论多大的包都直接发送,否则如果还有的报文没有 ACK,后续写的数据会积攒起来,如果积攒超过 MSS 则会打包发过去,或者前面发的所有包都 ACK 了也会直接发出去。对端通告窗口大小为 1,2,3.... 这种很小的窗口,发送端就只能发送很小的数据,但基于网络协议栈进行封包,TCP/IP最少报头都是 20 + 20,不携带选项,在携带这么少的数据,也就是 MSS,开销比较大。1. ACK丢包:发送 1,2,3。

2025-10-23 23:40:12 945

原创 C++11新特性补充

1. 先来谈谈 volatile:防止编译器对代码进行优化(代码编译后生成指令,编译器可能因为效率的原因对指令进行重新排序,也就是调换位置),并保证他修饰的对象在内存中是可见的,因为 CPU 高速缓存(L1 L2 L3)会通过预加载机制读取一定范围的物理地址,如缓存数据和指令,如果某个对象用 const 修饰,编译器则会认为这个对象不会被改,后续访问就去缓存直接读取,volatile 则就保证了禁止去缓存,转而去内存读取数据。

2025-10-09 22:08:41 731

原创 Redis(基础数据类型/String)

比如:0 ~ 30 秒内只能获取一次,通过 setnx ex,存在则设置,不存在则出错,并设置过期时间。比如:用户身份校验,浏览器传入 cookie/sessionid,Redis 缓存并查询。通过上述的 incr/incrby 等来实现。使用类型必须匹配,且保证不会溢出最大范围。

2025-09-17 21:26:27 423

原创 Redis(哨兵)

前章讲到主从结构下,主节点挂了是需要手动让某个从节点变成主节点,或者修复原来的主节点,人为干涉肯定是不现实的,所以 Redis 引入了哨兵机制。顾名思义:建立在主从结构之上,用来管理主从节点由于自身的的异常情况而避免人为干涉,变成了自动解决。当这些哨兵发现主节点挂了会统计个数,并判断 达没达到 认为主节点真正挂了的阈值,防止误判。然后调整从节点和挂了的主节点和客户端连接的 Redis 服务之间的关系即可。

2025-09-11 18:44:38 323

原创 Redis(集群)

都知道 Redis 是跑在内存中的,既然在内存,能存储的数据是有限的,如果存储的数据太大,就必须引入更多的 Redis 服务来进行分摊数据,所以 Redis 中集群模式就是来解决这类问题的。

2025-09-11 18:44:05 555

原创 Redis(缓存)

1. 生活上的例子比如有一个行李箱和一个手机,每次把手机放到行李箱在拿出来肯定很麻烦,如果放到裤兜里就会方便很多,所以裤兜算作行李箱的一个缓存,不仅仅是裤兜,甚至可以一直拿在手上等其他有存储介质的东西。说白了缓存就是用来提高效率的,比如 内存 作为 CPU 和 外设 的缓存,和接下来要讲的 Redis 作为 MySQL 的缓存,MySQL 和磁盘打交道,磁盘是外设 I/O 效率慢,并且是随机寻址就更慢了,而 Redis 工作在内存,用来缓存 MySQL 的部分数据来分摊压力再合适不过了。

2025-09-09 22:40:05 839

原创 Redis(主从复制)

顾名思义:部署多台 Redis 服务器,并选择一个为主 Redis 服务器,其他为从 Redis 服务器。从节点的数据必须从主节点同步过来从节点只能读,主节点可读可写某个从节点挂了,不影响从其他节点读取数据和写数据主节点挂了,不能写数据,从节点读的数据可能是旧的引入主从模式在读的场景下能提高硬件资源数量和可用性,比如某个服务挂了,依旧能从其他节点读数据,但主节点挂了就不会更新新的数据了。

2025-09-09 20:42:18 980

原创 仿TCmalloc内存分配器

什么是内存池前面几章讲过,这里就不在多说了。

2025-08-03 23:16:35 735

原创 图(遍历/最小生成树/单/多源最短路径)

Dijkstra 是很快的算法,但不能针对负权值,这个算法则可以针对,因为采用的是暴力遍历的方式求最短路径,从源点出发,每次选择任意连接的顶点即可,不需要选择从源点到某个点的最小路径,当所有的点选完之后则再次选择所有的边,因为可能带负权,执行 n - 1次,但如果出现了负权回路则会永远选不出最短路径。比如:A 出 B D C,在出 B,此时 B 不能再出 A ,A已经出过要标记一下,也不能再出 C,所以 C入的时候就要标记,所以不管是出过的顶点还是待出的顶点都要标记为不能再次入或者出。

2025-08-02 16:40:12 934

原创 ptmalloc(glibc-2.12.1)源码解析2

bins[NBINS * 2 - 2]:bins 数组,前面说的逻辑结构是 128 个,实际物理是 128 * 2 - 2,前面说过一个 bin 的哨兵节点需要 2 个指针,这里把 2 个指针拆开放到下标里,也就是两两下标为一组。stat_lock_direct/stat_lock_loop/stat_lock_wait:表示线程的直接获取锁的数量/自选等待锁的数量/阻塞等待锁的数量。max_n_mmaps:表示当前进程已经调用 mmap 且取最大值,不能超过 n_mmaps_max。

2025-07-25 17:50:15 793

原创 ptmalloc(glibc-2.12.1)源码解析1

chunk2mem(p):根据已分配的 chunk 的起始地址得到用户实际用的其实地址,本质是跳过前 2 个固定字段的大小,后4个字段在已分配的 chunk 中无效,直接给用户复用,也就是给用户返回的是 fd 字段的起始地址。MINSIZE:进行按最小的 chunk 对齐,比如传入 1 字节,至少对齐到 1+16(最小的 chunk 大小) -> 32(按最小的 chunk 对齐),大于最小的一样按照最小的 chunk 对齐。

2025-07-24 14:31:52 820

原创 Linux(内存分配算法)

最小分配出去的内存块是1页,即4k,所以如果申请小于1页的需求,也至少分配1页出去,可能导致大量的内存浪费用不上,如果分配的是完整的页,即计算后的大小命中某个下标,则直接分配出去,否则如果没能命中,则尝试找更大的连续的页,然后进行切割,剩余挂到对应的下标里,或者一个也没有则尝试合并小的页成一个大的页进行分配然后尝试切割,否则说明该数组不能满足需求则直接分配失败。首先伙伴算法管理的内存块是以页为单位的和物理内存一样,每个下标管理的是以 2^n 个页的内存块,比如:1页,2页,4页,8页.....。

2025-07-21 11:03:39 825

原创 ptmalloc(glibc-2.12.1)整体结构

先说说生活上的例子:比如在学校,每个月又或者每个星期或者每天家里人都会给生活费来维持在学校的生活开销。那么一次要多少,隔多少天要一次?这些情况都会带来不一样的效果和影响。比如一天要一次和一个星期要一次:每天都要一点,每天都会给家里人通信,想必时间久了家里人都会觉得太麻烦了。每隔星期要一点,一次要多点,这样就会家里人就不会觉得太麻烦了。家里人可能很忙,不能每天抽空按时给生活费。

2025-07-20 14:12:52 973

原创 C++(STL源码刨析/stack/queue/priority_queue)

【代码】C++(STL源码刨析/stack/queue/priority_queue)

2025-07-15 23:29:22 272

原创 C++(STL源码刨析/deque)

和前面 vector,list的接口不同,他是由一个数组,每个下标储存的是类型指针,在该指针上开辟空间,该指针的空间是连续的,但下标之间不是连续的,可能是连续的,这里不考虑,看起来像是vector 和 list 的结合,因为这样的结构,只需要从中间开始开辟空间,并向2边扩散,这样头尾操作都是O(1),完美的解决了 vector 和 list 的缺点,头操作,增加只需要往左边的缓冲区放入资源,删除则删除即可,不需要挪数据,每个下标之间的缓冲区无关系,尾操作也是一样的。一 deque的结构。

2025-07-15 00:26:33 307

原创 C++(STL源码刨析/list)

由于 链表 不是连续的内存块,所以对每一个申请到的内存块要进行统一组织,也就是封装成一个类,添加前后指针来关联申请到的内存块,在由 List 统一管理起来。由于 List 不像vector那样有一段连续的空间,所以不能直接用裸指针作为 List 的迭代器,但可以为这个指针封装一层,让他模拟指针的行为即可。list的无参构造表示没有节点,但要有个哨兵节点,因为list是双向带头循环链表,为了处理边界情况,所以有一个领头羊。那么怎么访问/遍历/修改 List 中的节点,一个个的访问吗?2. List本身字段。

2025-07-11 23:01:26 500

原创 C++(STL源码刨析/vector)

对象类型:对象指针:对象迭代器:对象引用:对象的个数: 用来计算对象的个数可以看出来指针和迭代器是一样的,因为vector是线性的,直接用裸指针就能模拟迭代器的行为,这里不需要过多考虑。

2025-07-08 22:58:00 837

原创 C++(STL源码刨析/空间配置器)

空间配置器:字面意思就是管理空间,也就是内存,但这个空间不仅仅指的是内存,比如磁盘等可以进行存储介质的硬件都可以有空间。都知道C++申请内存的方式是new,但STL容器走的都是空间配置器,为什么不走new?1. new把申请对象和对象的构造强绑定在一起。2. new申请内存必须指定类型。3. new如果在构造的时候抛异常,对象还没初始化完成,需要手动进行释放操作。4. new只能申请的是堆/共享区的内存,比如 gilic ptmalloc 管理小块内存块调用brk,大块内存块调用mmap。

2025-07-07 20:18:22 718

原创 C++(STL源码刨析/std::sort)

_introsort_loop():首先判断区间元素个数是否小于16,是就结束执行__introsort_loop()下一个函数__final_insertion_sort()插入排序,否则,先判断深度是否为0,是就转堆排,否则,减减深度,然后__unguarded_partition_pivot(),进行三数取中选取key,并划分左右区间,然后__introsort_loop(),递归右区间,然后让右迭代器=key,让他作为左区间的右开区间,即左区间最后一个元素+1的位置,然后执行下一次循环。

2025-07-03 22:36:50 979

原创 Linux(生产消费者模型/线程池)

这里的效率指的是生产者生产数据和消费者消费数据都需要时间,仅放/拿数据是互斥的,放/拿数据和他们生产任务/处理任务不和交易场所直接关联,也就是通过交易场所进行解耦,互相不冲突达到并行效果,所以总体来说效率高,并且上面是把交易场所当整体使用了,也可以比如交易场所有10个数据,同时放10个消费者取数据,维护他们之间的互斥和同步,也能达到同时消费,进而提高效率,所以下面引入信号量。工厂和工厂的关系:如果超市还差一个货物满了,工厂与工厂之间同时出货物,超市只能处理一个,剩下处理不了,所以工厂和工厂是互斥关系。

2025-06-07 23:06:06 773

原创 Linux(线程控制)

第一:内存中的值没变,其他线程可以继续申请,如果申请到,内存中的值变了,切走的线程再回来,恢复自己的寄存器的里的值:0,交换内存中的值,此时假设内存中原来的值为1,因切走被其他线程交换,变为0,此时0和0交换,在进行if()判断,走else 阻塞等待。第二:执行第二行代码被切走,此时内存中的值由初始1被交换到寄存器,变为0,线程切换保存寄存器的值,后续线程的寄存器初始化为0,和内存中被交换后的值:0,0和0交换,if()不成立,else阻塞。那么用户级线程是如何封装的?用户级线程包含哪些属性?

2025-06-06 16:18:55 1372

原创 Linux(线程概念)

当创建一个进程,加载可执行文件代码和数据,创建内核数据结构:PCB,mm_struct,文件描述符表....等对象,都需要在内存中申请空间,被CPU调度,切换保护进程上下文数据,重新填充pc指针,MMU,TLB,CR3,等一系列的寄存器,每个进程新创建/被切换,带来的开销势必是很大的,这也就是为什么进程是资源分配的基本单位,要什么资源直接给进程分配物理内存。进程调度,当时间片到了切换到下一个进程时,保存上下文更新,CR2指向的页表,TLB缓存内容,全部都失效重新加载新的进程,重新进行TLB缓存预热。

2025-06-03 23:25:08 1096

原创 Linux(信号)

1. 生活中的信号:红绿灯,闹钟,上课铃声....都称为信号。2. 当得知了这些信号,是执行默认动作?还是不管直接忽略掉?还是做你想做的动作?还是等会在做?都取决于自己。3. 当你正在做某件事情的时候,信号可能随时产生,也就是说信号的产生是异步的,比如3个人吃饭,突然有一个人干别的事情去了,无需等待他,继续吃饭称为异步,如果等他把事情做完了再回来在继续吃饭称为同步。// 返回值为 void 参数为 int 的函数指针类型int signum, // 信号编号。

2025-06-03 00:00:19 1056

原创 进程间通信(信号量)

2. 还是和之前的共享内存/消息队列一样,通过形成的key_t并创建一个信号量集,一个信号量集里面可以有多个信号量,并初始化信号量集合,后续对集合中某个特定的元素进行操作。3. 信号量主要用来计数器,信号量++,--操作是原子的,自带同步机制,当某个信号量元素为0则阻塞/其他时间,阻塞有资源则就唤醒等。1. 和共享内存/消息队列一样都属于system v版本的进程间通信,接口大同小异。三 二元信号量的demo代码。

2025-05-31 23:35:43 311

原创 进程间通信(消息队列)

责任链属于行为类设计模式,也就是程序在运行的时候每个模块之间都有任务和优先级,哪些任务完成或者不完成的结果要交给下一个节点(处理点),也可以不启动这个任务,就好比食堂打饭打完这个菜,后面的菜可打可不打。

2025-05-31 18:39:51 1279

原创 进程间通信(共享内存)

key是用户形成的只是用来获取和创建共享内存的,并不能对已经存在的共享内存进行字段修改/结构修改等,只有shmid能操作,本质就是 shmid 属于内核提供的,key是有用户提供的,他们的功能侧重点不同,用户管用户,内核管内核,变相的解耦。1. 传入一个路径和id并通过算法形成一个key_t结构,本质是int类型,算法是固定的,所以不同的进程传入相同的字符串和id得到的key_t都是一样的,这是用户传入数据生成的。key: 用户形成的随机值,用来获取,创建访问共享内存。bytes: 共享内存多大。

2025-05-29 23:44:50 1007

原创 进程间通信(命名管道)

2. 命名管道通过特殊的管道文件路径来标识唯一性,不同的进程的文件描述符表是独立的,但如果都对同一个文件进行操作,该文件的属性,缓冲区,方法级,都是一样的,所以不通过的进程只需要让自己的文件描述符指向同一个文件的相关属性即可,怎么知道不同的进程打开的文件是一样的?1. 前一章说了匿名管道是通过借鉴文件系统的属性方法缓冲区等,操作系统实现的一套具有血液关系的进程通信机制,本质是让不同的进程看到同一份资源(通过子进程继承父进程的文件描述符表),那么命名管道如何标记同一份资源呢?

2025-05-27 18:09:09 368

原创 进程间通信(匿名管道)

字面意思来看管道是单向流动的,只许一方读一方写,或者一方写一方读,也就是特殊的半双工,除非创建2个管道通信,也就是全双工。

2025-05-27 15:34:18 1041

原创 动静态库--

1. 每个函数内部的地址都是相对于该函数的起始位置的偏移量,比如 1168 -> 1 ,-> 2 , -> 3,1加上1168就能访问到具体的语句,被称为相对编址,而上图没有采用,而是采用的绝对地址,1168 -> 116c,直接访问116c不需加上偏移量,被称为绝对编址,这种采用绝对编制范围 全0 ~ 全F,也可以说是逻辑地址(虚拟地址),这个文件里面的地址都是采用ELF格式进行编制的,有自己的固定格式。3. 动态库加载到内存,他的地址是不变的,不管虚拟地址是否变化,最终映射到的库的起始地址是不变的。

2025-05-25 00:00:52 1142

原创 软硬链接--

他们的Inode号是一样的,Link也和上面的软连接不一样,Link就是硬链接数,标识有多少文件与Inode的映射关系,也就是说Inode只有一个,但文件可以有很多个并同时指向这个Inode,类似引用计数,删除任意一个不会影响Inode,只要硬链接数为0,Inode也就会释放掉了。如果被链接的文件被删除或者移动到别的目录下,软连接也就失效了,不会动态随着目标文件而改变,但如果目标文件不在了,但又创建一个和目标文件同名的文件,且路劲和软连接文件的路劲是一样的,就不会失效了。

2025-05-23 00:06:26 813

原创 K个一组链表翻转

很好解决让new一个指针ans,定义一个指针tmp=ans指向他,那怎么让反转后的最后一个节点1指向下一个节点?反转后的状态直接让tmp指向他,也就是 ans的next 指向 prev 所在的位置并让 tmp进行指向(ans后续返回答案要用)。总共5个节点,5/2,总共反转2次,结束让最后的指针指向剩余的节点。然后让tmp指向之前标记的cur也就是pos,也就是反转之前的头部。只要最开始记录1和2,2个节点,并让1指向空,在根据2得到3节点。结束,让tmp指向没反转的节点,节点就是cur指向的节点。

2025-05-21 23:16:21 384

原创 Socket echo server

因为他们的第一个字段是一样的,所以可以用 sockaddr_in和sockaddr_un强转成sockaddr结构,并提取第一个字段判断是AF_INET还是AF_UNIX选择强转成sockaddr_in还是sockaddr_un结构,也就是C语言版的继承和多态。知名端口号比如:HTTP(80),HTTPS(443),DNS(53)。2. 当server启动的时候,就需要accpet获取连接,也就是有连接来了,获取到的连接分配一个文件描述符来进行读写,所以要起多线程/多进程,不然会阻塞后续的accpet。

2025-05-16 19:19:23 660

原创 NAT/代理服务器/内网穿透

当某个内网想访问公网,就必须先找到处于同一个网段的出入口路由器,而内网又不能暴露在公网上,所以当IP地址到达路由器时,路由器会把源IP转换成路由器的WAN口IP,并和源IP进行映射,这里他们互为 key <=> val,当服务器回显时,填充目的服务器IP地址,也就是之前经过转换后的IP地址,源地址填服务器的IP地址,在路由到目的IP所在的路由器,并由该路由器进行查映射表,查到转换之前的私有IP,在进行转发。路由器进行查表:202.244.174.37,查到得到:10.0.0.10,并交付给最初的主机。

2025-05-14 21:45:23 990

原创 -MAC桢-

当某台主机首次通信时,交换机会记录当前主机的mac地址,下次在进行通信,比如交换机首次记录A的mac地址,A再次通信,如果目的mac地址是B,则不需要往交换机右边的碰撞域发送数据包,同时C也能给E/F发送数据,进而减少了数据碰撞,如果A给右边的碰撞域发送数据,那就不会给B/D发送数据包,而是给右边的碰撞域所有的主机发送数据包。4. TCP三次握手的时候,双方会进行MSS的协商,在可变选项指定,因为双方的MTU可能不一样,最终双方使用的MSS取最小的那一个来进行后续数据包发送的大小避免数据包拆分。

2025-05-12 19:34:29 681

原创 ARP协议

5. 当路由器收到数据包,解包之后发现和自己mac地址一样,发现桢类型为0806,交给上层ARP,拿到ARP报头,先看op字段,因为不知道是别人构建的应答还是请求,这次是应答,首先看目的mac地址和目的IP地址和路由器的mac地址和IP地址一样,确定报文是发给路由器,然后得到源macE的地址,自此通过ARP请求根据目的IP地址得到目的主机的mac地址,后续重新封装mac桢填入目的主机mac地址发送数据包。前5个字段为固定字段,填充源ip,mac地址,目的ip地址,目的mac地址缺省广播。

2025-05-11 21:15:14 991

原创 Redis(持久化)

为什么要持久化Redis是跑在内存上的,但内存上的数据是临时的,Redis服务挂了,数据也就丢失了,所以为了解决上述问题,Redis的数据同时都要在内存和硬盘上,理论上内存上和磁盘上的数据要是一致的。

2025-04-19 19:01:51 1150

原创 IO多路复用

传统的read,write,都需要等对端写/缓冲区剩余空间足够才能写,相当于大部分时间都在等某个资源就绪,这样会不会太慢了?再比如appect获取连接,如果一直没人来连,就会一直阻塞等待。换句话说,一次性只能处理一个连接,有没有能同时等待多个事件?原理是一次性等待多个事件就绪,然后上层在进行统一处理,在同一时间段效率比传统的阻塞式等待效率要高,就好比如钓鱼,一次抛一个鱼竿和一次抛100个鱼竿,肯定是一次性抛100个鱼竿钓到鱼的概率要大些。

2025-03-25 12:40:05 1322

原创 HTTPS

当服务器把自己的公钥传输给客户端的时候,中间人拿到,并用自己伪造的M公钥交给客户但,客户端拿中间人的公钥加密自己的对称密钥,传给服务器,中间人再次拿到客户端加密的数据,拿自己的私钥解密得到客户端的对称密钥,在用客户端的公钥和服务器的公钥加密,传给服务器,服务器解密,得到客户端的对称密钥,但客户端的对称密钥和服务器的公钥已被窃取,后续通信采用对称密钥,中间人已经有了对称密钥,所以也有问题。如果对最开始的密钥进行加密,那么解密的密钥也要传给服务器进行解密,无限套娃,所以只采用对称加密不安全。

2025-03-20 19:28:34 4499

原创 MySQL(索引)

MySQL与磁盘IO交互的基本单位是16kb,这是在逻辑上的角度,因为MySQLd是在内存中的,属于应用层,访问磁盘硬件,必须通过操作系统进行交互,而操作系统IO交互的基本单位是4kb,也就是说操作系统内的文件缓冲区设置为16kb,在从磁盘读取4kb,读4次,在刷新到MySQL预先开辟的buffpoo缓冲区里,所以MySQL与操作系统page的比例为1:4,所以提交效率指的是IO的次数,就好比如读取100k,分一次读100k和分100次读1k,IO交互越少效率越高。

2025-03-18 22:45:50 952

空空如也

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除