自定义博客皮肤VIP专享

*博客头图:

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

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

博客底图:

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

栏目图:

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

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(58)
  • 问答 (1)
  • 收藏
  • 关注

原创 《程序员的自我修养》阅读笔记

阅读笔记

2023-02-25 17:27:55 747 3

原创 [C/C++后端开发学习]23 Nginx学习

反向代理负载均衡HTTP Server正向代理Nginx安装可以直接通过ubuntu的命令安装Nginx,但如果有开发需求的话,就必须通过下载源码进行编译的方式进行安装。Nginx源码下载地址:nginx,我下载的是1.20.2版本;同时还需要依赖openssl,pcre(用于正则匹配) 和 zlib(用于压缩):openSSL 1.1.1npcre 8.45zlib 1.2.11将这些库的目录与nginx源码的目录放在同一层,然后进入到nginx源码

2022-10-09 15:29:10 975

原创 [C/C++后端开发学习]22 协议设计与Protobuf

文章目录通信协议设计基本要素消息帧完整性的判断方法主流序列化协议Protobuf使用protobufIDL语法编译.proto命名规范在C++中使用protobufprotobuf 编码通信协议设计基本要素要能完整地识别一帧数据(帧完整性)能够进行序列化和反序列化能够进行协议升级(包括客户端和服务端,需要指明协议版本)协议具备安全性(加解密)能够实现数据压缩,减小传输数据量消息帧完整性的判断方法1、强制固定每个消息的数据长度,比如规定每个消息都发128字节这显然是很拙劣的方法。以

2022-03-20 14:24:50 1542

原创 索引技术核心学习笔记

参考资料:检索技术核心 20 讲基础:数据结构整理

2022-02-15 00:35:42 216

原创 [C/C++后端开发学习]21 定时器实现方案

文章目录定时任务的处理方式实现方案1)红黑树2)最小堆3)时间轮方案选择时间轮的实现单层级时间轮多层级时间轮Skynet的时间轮定时任务的处理方式服务端的驱动逻辑主要涉及两类事件的处理:网络I/O事件和定时事件,不同的框架采用不同的方式来整合这两种事件的处理流程:在同一个线程中先处理I/O事件,再处理定时事件,如nginx、redis。利用 epoll_wait 监测I/O的同时依靠 timeout 参数来实现所谓定时,缺点是I/O的处理导致延时比较严重。网络事件和I/O事件在不同线程中处理,如s

2022-01-26 18:24:30 2103

原创 GDB调试方法

文章目录启动GDB调试coredump的设置与调试常用命令列表部分命令详解break/binfo break以及断点的enable、disable和deleteprint/p 和 ptypethread及info threadwatch常用调试技巧使 print 打印显示完整多线程下锁定当前调试线程调试多进程GDB最详细的文档请参考GDB Documentation。其中给出的关于GDB的简介非常精炼:The purpose of a debugger such as GDB is to allow

2022-01-19 17:21:52 3444

原创 [C/C++后端开发学习]16 使用libevent

文章目录libevent和libevlibevent的封装层次使用libevent1)由调用者自己管理I/O2)调用者只处理事件网络监听和读写事件普通I/O事件3)定时事件和信号处理定时事件信号处理事件原理浅析定时任务管理的实现evbuffer的实现1)evbuffer写数据2)evbuffer读数据libevent和libevlibevent和libev均是基于C语言实现的异步事件库,它们封装了事件管理过程中与操作系统的交互,使得调用者无需关注事件监测机制以及IO处理机制等在不同平台上的差异,而只需关

2022-01-10 16:46:33 1541

原创 自制内存泄漏排查组件

内存泄漏内存泄漏的核心原因是调用分配与释放时没有符合开闭原则。有分配却没有释放,这自然会使得进程的堆内存会越来越少,直到耗尽。一个内存泄漏检测工具需要能够精准地定位到泄漏是由代码中的哪一行所引起的。可以直接使用一些现成的工具进行内存泄漏的排查,比如valgrind、mtrace、ASAN等等。但这些工具往往不适用于在生成环境中实时地检测内存泄漏,而多是用于在发现内存泄漏后进行测试。特别是valgrind和ASAN对性能的影响也比较大,而且不适用于嵌入式系统。那么,是否可以自己写一些小工具,对mall

2021-12-24 17:51:10 733

原创 自制死锁检测组件

文章目录死锁组件框架有向图构建以及环的检测测试死锁死锁,简单地说就是一组线程或进程互相之间通过互斥量去竞争资源而导致全部进入永久阻塞的状态。如下图所示,首先线程1获取了互斥锁mutex1,线程2获取了互斥锁mutex2,线程3获取了互斥锁mutex3;此时,线程1想要获取mutex2,则它将阻塞直至线程2释放mutex2;线程2又想要获取mutex3,则它将阻塞直至线程3释放mutex3;线程3又想要获取mutex1,则它将阻塞直至线程1释放mutex1。此时死锁就产生了,其中任何一方都获取不到想要的资

2021-12-24 00:14:22 568

原创 [C++]智能指针的实现

注:源码来源为 llvm/llvm-project使用智能指针时我们所包含的头文件为<memory>,而关于shared_ptr<T>的类定义实际上在shared_ptr.h中,为了便于理解,此处仅从源码中截取出其部分构造函数、成员变量以及重载的赋值运算符:template<class _Tp>class shared_ptr{private: element_type* __ptr_; // 所管理的对象内存的指针 __shared

2021-12-21 12:19:03 573

原创 锁与原子操作以及CAS的实现

文章目录线程同步锁互斥锁 mutex读写锁 rdlock自旋锁 spinlock原子操作_sync*CAS线程同步当我们对一个变量做增量操作时,其过程通常可分解为以下3步:从内存中将变量读入寄存器在寄存器中对变量做增量操作把新的值写回内存单元当多个线程同时对同一个变量做该增量操作时,如果不进行同步,结果很可能会与预想的不一致。如两个线程同时读出变量的原始值,先后做增量操作后再写回内存,此处涉及两次增量操作,这导致实际效果是只有一次增量操作。锁与原子操作都可以用来实现线程间的同步。锁互斥

2021-12-20 11:53:30 581

原创 [C/C++后端开发学习]12 基于netmap的用户态协议栈(二)

文章目录初步实现简单的TCP用户态协议栈TCP的状态迁移TCP首部处理TCP控制块(TCB)几个辅助函数TCP数据报的接收和发送1 实现三次握手2 接收数据并回复相同的数据3 实现“四次”挥手完整代码初步实现简单的TCP用户态协议栈TCP的状态迁移下图是TCP的状态迁移图。显然,由于TCP是一种有状态协议,所以实现起来要比之前实现的那些协议复杂很多,其中包括三次握手、四次挥手、连接重置等等。同时还有错误重传、滑动窗口等机制以及各种定时器。此外,还需要为TCP实现慢启动、拥塞控制、快速重传等等算法。平时

2021-12-11 22:27:45 2759

原创 [C++]Lambda表达式

基本语法Lambda表示式即匿名函数,用于临时创建一个函数进行处理。基本构成为:[捕获列表](参数列表)->返回类型{函数体}举例:int main(){ auto Add = [](int a, int b)->int { return a + b; }; std::cout << Add(1, 2) << std::endl; //输出3 return 0; }一般来说,编译器可以自动推断出lambda表达式的返回类型,所以可以不显式

2021-12-07 12:07:02 1231

原创 [C/C++后端开发学习]20 Redis基础数据结构

文章目录简单动态字符串SDS双向链表Quicklist字典Dict跳表Skiplist整数集合Intset压缩列表Ziplist已知Redis 对外提供了5种不同类型的对象。Redis 针对不同的使用场景,为对象设置多种不同的数据结构实现,从而优化对象在不同场景下的使用效率。简单动态字符串SDSSDS(Simple Dynamic String)对原始C字符串进行了封装,在Redis中除了将字符串作为常量而不需要修改的地方,几乎都使用SDS作为字符串。不论是使用哪一种对象,其key和value如果是用

2021-11-30 16:28:15 405

原创 [C/C++后端开发学习]19 Redis对象与命令

文章目录关于Rediskey-value基础数据结构应用场景value的内部存储结构及其选择基础数据结构及其操作命令1 string1.1 存储结构1.2 基础命令1.3 应用2 list2.1 存储结构2.2 基础命令2.3 应用3 hash3.1 存储结构3.2 基础命令3.3 应用4 set4.1 存储结构4.2 基础命令4.3 应用5 zset5.1 存储结构5.2 基础命令5.3 应用关于RedisRedis(Remote Dictionary Service,远程字典服务)是一种内存数据库,

2021-11-29 01:48:10 1399

原创 [C/C++后端开发学习]18 Mysql事务原理

Mysql事务原理

2021-11-27 00:20:19 1261

原创 [C/C++后端开发学习]17 Mysql索引原理

文章目录索引、主键及约束索引分类主键的选择约束索引的实现索引的存储聚集索引辅助索引验证实际采用的索引索引的工作原则最左匹配原则覆盖索引索引失效索引的设计原则索引、主键及约束索引分类Mysql利用B+树来组织和存储数据,索引用于在B+树中作为key值快速地查找数据。唯一索引不可以出现相同的索引值,但可以有NULL值。UNIQUE(key)主键索引非空的唯一索引,一个表只有一个主键索引;在 InnoDB 中,由主键索引构建的B+树包含了表的完整数据信息;PRIMARY KEY(key

2021-11-25 23:02:21 1072

原创 [C/C++后端开发学习]15 简单内存池实现

文章目录为什么需要内存池内存池的设计策略对比内存池分配方法设计内存池结构空洞的利用内存释放数据结构设计内存池操作接口实现初始化内存池申请内存释放内存销毁内存池内存池的自动清空补充: 内存泄漏的排查为什么需要内存池简而言之,反复地进行malloc和free不利于内存管理,同时容易产生内存碎片。复杂的代码中还容易出现内存泄漏问题。内存池则提前分配好大块内存,形成内存池,再从内存池中提供现成的内存块给程序使用。内存池的设计策略对比由一个大的整块分散成多个小块,回收时再整合成大块(如伙伴系统)。一般以页为

2021-11-22 16:19:34 475

原创 [C/C++后端开发学习]14 线程池实现

文章目录线程池的作用线程池的结构任务的形式线程池的实现数据结构的封装线程与任务的管理方法实现测试代码线程数量设定线程池的作用服务器接收到客户端请求后,往往需要执行一些处理任务,然后再将执行结果返回给客户端。这其中有一些任务是比较耗时的,如写日志、计算任务及数据库CRUD等操作,在单线程环境下可能会影响到服务器对其他客户端的响应速度。因此需要采用多线程处理。那么,如果每次接收到请求之后再去新建线程来执行任务,则会存在比较大的性能开销。一种比较巧妙的方法就是,提前建立好可以执行任务的线程,放在一个线程池中,

2021-11-20 23:08:53 915

原创 [C/C++后端开发学习]13 Mysql连接池

池化技术池化技术简单地说就是复用现成的资源,减少资源对象的创建次数,在高并发的场景下提高程序的响应速度。具体实现包括线程池、内存池、连接池、对象池等等。使⽤池化技术缓存的资源对象有如下共同特点:对象创建时间⻓;对象创建需要⼤量资源;对象创建后可被重复使⽤数据库连接池即是在程序启动时就预先建⽴⾜够的数据库连接,并将这些连接通过一个容器组织起来,由程序动态地对池中的连接进⾏申请,使⽤,释放。创建数据库连接是⼀个很耗时的操作,也容易对数据库造成安全隐患。所以,在程序初始化的时候,集中创建多

2021-11-20 02:13:26 764

原创 [Linux内核源码阅读笔记] 4 物理内存的管理

文章目录1 物理内存的管理1.1 页表虚拟地址分解页表分析页表项的附加信息1.2 TLB的管理1.3 伙伴系统(页分配器)伙伴系统的基础伙伴系统的分区域管理区域水线1.4 slab块分配器基本原理编程接口通用内存缓存的编程接口针对特定对象类型的内存缓存的编程接口内存缓存的数据结构slab实现分配特定对象缓存slab分配通用缓存slab着色slab内存回收改进的块分配器1.5 不连续页分配器编程接口数据结构1 物理内存的管理1.1 页表页表用于记录虚拟地址到物理地址的一一映射关系。每一个页表项除了存放物

2021-11-18 22:03:27 665

原创 [Linux内核源码阅读笔记] 3 内存管理基础

文章目录虚拟地址空间1 内存管理子系统1.1 物理层面1.2 内核层面1.3 用户层面2 物理内存以及内核空间虚拟内存的管理2.1 页表的工作原理2.2 TLB的管理2.3 伙伴系统2.4 Slab/Slub/Slob块分配器2.5 不连续页分配器3 用户空间虚拟内存的管理3.1 用户虚拟地址空间的布局3.2 内存映射的实现3.3 堆的管理4 关于缺页异常5 用户空间与内核空间的数据拷贝补充:物理内存的组织结构虚拟地址空间虚拟地址的引入使得一个进程所能使用的最大地址空间与实际可用的物理内存数量无关。也就

2021-11-18 22:02:35 1061

原创 [C/C++后端开发学习] 11 实现一个简单的HTTP服务器

Reactor 模型中增加HTTP协议在实现GET方法实现POST方法实现CGI

2021-11-17 19:25:00 3283

原创 [C/C++后端开发学习]10 基于netmap的用户态协议栈(一)

用户态协议栈的意义在内核实现协议栈往往存在两次拷贝过程,一是网卡中的数据通过sk_buff拷贝到内核,之后再从内核拷贝到进程用户空间。于是我们考虑如何加快这个过程,减少拷贝次数。一种思路:通过DMA直接将数据从网卡拷贝到内存中,于是应用程序可以直接通过mmap从内存中取得数据。由于DMA的工作是不需要CPU干预的,所以对于CPU来说相当于没有做任何的拷贝操作,即所谓零拷贝。那么应用进程如何通过这种方式从网卡直接取得数据?常用几种方法:使用raw socketnetmap框架dpdk框架ne

2021-11-08 22:40:48 944

原创 Linux 网络性能监测

网络性能指标常用于衡量网络性能的指标包括:**带宽、吞吐量、延时、PPS(Packet Per Second)**等。带宽:链路的最大传输速率,单位b/s(bit/s)吞吐量:单位时间内成功传输的数据量,单位b/s(bit/s)或B/s(字节/s)。吞吐量 / 带宽 就是网络的使用率。延时:一般指从一端发出请求到收到另一端的响应,所需要的时间PPS: Packet Per Second(包 / 秒)此外还有网络的连通性(网络能否正常通信)、并发连接数(TCP 连接数量)、丢包率(丢包百分比)

2021-11-06 14:19:31 1370

原创 [C++] C++11 原子变量

在多线程程序中使用原子变量std::atomic可以非常方便地避免并发访问时的线程安全问题(data races),此外还可以通过指定不同的std::memory_order指定线程间数据同步的粒度。原子变量template <class T> struct atomic;常用方法: void store (T val, memory_order sync = memory_order_seq_cst); // 修改值 T load (memory_order sync = memo

2021-11-06 11:45:02 1754

原创 [Linux内核源码阅读笔记] 2 调度机制详解

注:使用内核源码版本4.12文章目录1 调度器的实现1.1 核心调度器周期性调度器(scheduler_tick)主调度器(schedule)1.2 调度类运行队列调度实体1) stop_sched_class 停机调度类2) dl_sched_class 限期调度类3) rt_sched_class 实时调度类实时调度类实现简析a) 队列操作b) 实时调度类在周期性调度器中的 task_tick4) fair_sched_class 公平调度类CFS调度实现简析a) 虚拟运行时间b) 队列操作c) 公

2021-11-06 02:28:12 996

原创 [Linux内核源码阅读笔记] 1 进程管理的基本原理

注:本文所用源码版本4.12文章目录1 进程四要素task_struct 结构体2 进程的创建创建进程的系统调用写时复制3 进程的状态迁移4 调度策略及优先级调度策略优先级优先级计算的源码分析一点补充优先级反转与优先级继承1 进程四要素Linux内核把进程称为任务(task),线程是进程的特殊形式,包括内核线程和用户线程,共享同一个用户虚拟地址空间的所有用户线程组成一个线程组。同一个线程组的所有线程必须属于相同的用户命名空间和进程号命名空间。关于命名空间可以参考这篇。Linux进程四要素:进程执

2021-11-05 02:47:32 447

原创 常见TCP/IP协议栈相关问题

文章目录TCP相关UDP相关TCP相关TCP三次握手过程TCP四次挥手过程为什么建立连接需要三次握手,而断开连接需要四次挥手三次握手主要是提供一种确认机制,防止之前已经因分组丢失而失效的连接请求突然又重传到了服务端,导致服务端误以为客户端又发起了一次连接;那么断开连接时需要四次挥手,主要是由于TCP是双向通信的,读写是不同的两个通道,服务端的读通道被关闭后写通道的数据可能还未发送完毕,因此两个通道需要分开来发送FIN包及其ACK包,就出现了一般情况下的四次挥手。TIME_WA

2021-11-04 01:34:29 1303

原创 TCP的半关闭状态以及tcp-keepalive

文章目录半关闭状态实现方法tcp-keepalive开启 tcp-keepalive方法1 Linux系统全局开启方法2 setsockopt 设置 socket半关闭状态一次TCP四次挥手的过程如上图所示。设左侧为客户端,右侧为服务端,当客户端发起FIN而关闭其写通道时(对应服务端读通道),服务端进入close_wait状态,但希望推送完所有数据后再关闭整个连接。此时连接处于半关闭状态,客户端只能读,服务端只能写。待服务端发送完所有数据并发送一个FIN后,客户端响应ACK,服务端收到ACK后知道客

2021-11-03 17:33:36 3346

原创 Linux 文件I/O性能监测

缓存I/O缓存I/O又称作标准I/O,多数文件系统默认都采用缓存I/O。在 Linux 的缓存 I/O 机制中,数据先从磁盘复制到内核空间的缓冲区,然后从内核空间缓冲区复制到应用程序的地址空间(用户空间)。优点:减少硬盘读写次数;分离内核空间和用户空间,保护系统安全。缺点:数据可能在用户空间和内核空间之间来回地拷贝,这也会增大CPU及内存的开销。直接I/O应用程序跳过内核空间缓冲区直接访问磁盘,这可以克服缓存I/O的缺点,但应用程序一般需要自己实现缓存。比如数据库程序可能更倾

2021-11-03 11:23:11 2328

原创 buffer和cache

buffer和cache $ free -h total used free shared buff/cache availableMem: 1.9G 1.3G 139M 9.5M 514M 481MSwap: 8.4G 233M 8.2Gfree 指令的输出结果中,buff/cache 一列

2021-11-03 03:33:43 153

原创 Linux CPU上下文切换性能监测

目录上下文切换1 系统调用上下文切换2 进程上下文切换3 线程上下文切换4 中断上下文切换vmstat测试工具sysbench上下文切换简而言之,就是将上一个任务的寄存器和程序计数器的资源保存起来,然后加载下一个任务的寄存器和程序计数器等,最后跳转到新任务的地址运行。CPU的上下文切换情况可分为:系统调用上下文切换进程上下文切换线程上下文切换中断上下文切换1 系统调用上下文切换进程可通过系统调用从用户态进入到内核态,这个过程存在用户空间和内核空间之间的上下文切换。并且在系统调用结束后需

2021-11-03 03:11:12 266

原创 Linux CPU负载性能监测

Linux CPU性能监测平均负载和 CPU 使用率压测命令 stress模拟负载场景监测工具topmpstatpidstat补充:自愿上下文切换和非自愿上下文切换平均负载和 CPU 使用率平均负载是指单位时间内的活跃进程数,也就是处于可运行状态®和不可中断状态(D)的进程数。不仅包括了正在使用 CPU 的进程,还包括等待 CPU 和等待 I/O 的进程。可以参考这篇笔记。CPU使用率是指单位时间内CPU繁忙情况的统计,与平均负载并不是一个东西。CPU使用率为100%时,是指换算成单个CPU

2021-11-03 01:57:40 8623

原创 [Linux内核源码阅读笔记] 页式内存管理

注:源码版本3.4.2,参考《Linux内核源码情景分析》页式内存管理页式内存管理的思路是:通过页目录和页表项分两个层次实现从线性地址(虚拟地址空间)到物理地址的映射,这样采用多级页表的映射方式在多数情况下能够减少存储页表项所需的内存空间。二级页表映射示意图:对于32位的系统采用两级映射是比较合理的,对于64位的系统则应采用3级映射三级页表映射示意图:内核空间和用户空间一个32位系统存在4G的虚拟地址空间,它被分为两部分,地址较低的3G空间用作用户空间,而地址较高的1G用作内核空间。

2021-11-02 17:02:09 180

原创 [C/C++后端开发学习] 9 服务端百万并发测试

服务端并发的概念并发量:同时承载的客户端的数量,实质上就是同时能够维护的 socket 的数量比如要实现10W客户端同时在线,200ms内正常返回结果,承载量的影响因素:数据库网络带宽内存操作日志常见单机服务模型单线程同步:NTP多线程同步:Natty纯异步:Redis、HAProxy半同步半异步:Natty多进程同步:fastcgi多线程异步:memcached多进程异步:Nginx一个请求一个进程/线程:Apache/CGI微进程框架:erlang/go/lua

2021-11-02 00:50:24 1187

原创 使用cmake编译项目

Cmake参考文档

2021-11-01 20:45:03 752 1

原创 Linux nc命令

netcatnc 命令即 netcat的简写,功能丰富,可以用于数据的传输,但我常用它来测试服务器端口是否开放。常用参数-l :(listen)将nc启用为服务器并监听指定的端口号,并且开启后必须由客户端主动关闭连接-v :输出用于调试的交互信息-w :(wait)指定一个超时的秒数-u :使用UDP协议,默认是TCP常用方法实例对本地8888端口进行监听,等待客户端发起连接nc -l 8888连接到IP为192.168.2.100的目标主机的8888端口,可测试目标主机是否

2021-10-29 12:23:01 662

原创 [C++] C++11的异步操作

异步操作—future与promiseC++11 提供了4个与函数异步执行相关的模板类和方法,分别为:std::futurestd::aysncstd::promisestd::packaged_task使用以上类和方法都只需要包含头文件<future>。future 与 async当你需要执行一项任务但目前不需要立刻得到结果时,你可以开启一个单独的线程去执行该任务,并在未来的某个时刻等待这个任务的返回结果。future 与 async 共同为我们提供了实现这种效果的机制。

2021-10-27 23:59:29 395

原创 [C++] C++11 条件变量

条件变量C++11 提供了条件变量condition variable用于实现线程间的同步操作,需要包含头文件#include <condition_variable>,并且一般都是与互斥量mutex配合使用。条件变量的工作方式为:使用条件变量的线程首先对互斥量加锁检查某个条件,如果条件不满足,则释放互斥锁量,进入休眠;如果条件满足,则继续执行资源操作,执行完操作后释放互斥量另外一个线程加锁执行资源操作,使条件满足后,释放互斥量,唤醒等待的线程具体参考:std::conditio

2021-10-27 15:41:47 752 1

空空如也

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

TA关注的人

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