自定义博客皮肤VIP专享

*博客头图:

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

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

博客底图:

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

栏目图:

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

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(95)
  • 资源 (2)
  • 收藏
  • 关注

原创 预处理、编译、汇编、链接过程

引入头文件 #include展开宏定义 #define处理条件编译指令 #ifdef删除注释添加行号在Linux下可以使用gcc -E命令把hello.c文件成hello.i文件。windows这些操作都集成在编译器visual studio这些里面了。

2024-03-30 16:22:33 591

原创 5.STL源码解析-算法、仿函数、适配器

仿函数是一种类或对象,可以像函数一样被调用。在STL中,仿函数广泛用于算法和容器中,允许我们以一种类似函数的方式进行操作。仿函数的关键特点是它实现了函数调用运算符 operator()。

2024-03-03 14:00:09 778

原创 4.关联式容器

关联式容器是指数据是键值对的格式。容器内部结构(可能是RB-tree或者hash-table)便依照其键值大小,以某种特定规则将这个元素放置于合适的位置,关联式容器没有所谓头尾(只有最大元素和最小元素);所以不会有所谓等行为的操作。

2024-03-03 13:43:46 804

原创 3.3 序列式容器-deque、stack、queue、heap、priority_queue

std::deque(双端队列)是C++标准模板库(STL)中的一种容器,表示双端队列数据结构。它提供了在两端高效地进行插入和删除操作的能力。与vector的连续线性空间类似,但有所不同,deque动态地以分段连续空间组合而成的,随时可以增加一段新的空间并链接起来。因此deque的迭代器并不是普通的指针;之前提到vector的动态内存增长需要涉及到更大内存的分配;内存数据的复制;原内存空间的释放。deque避开了vector中的反复内存搬移,但是数据结构的设计和迭代器架构却异常复杂。

2024-03-02 18:21:35 924

原创 3.1 序列式容器-list

std::list是一个双向链表(doubly linked list)的容器。相对于vector的连续线性空间存储,list是非连续的线性空间存储。因此list和vector这两个最常被使用的容器经常被用来比较。vector当需要快速随机访问元素的时候,例如在循环中通过索引访问元素。当知道容器的大小,并且需要预先分配一定数量的元素的情况。list当需要频繁在容器中间或头尾进行插入和删除操作时。当不需要频繁随机访问元素,而是通过迭代器遍历元素。

2024-03-02 17:53:54 289

原创 3.1 序列式容器-vector

C++本身提供了一个序列容器array数组,STL中新增了一个vector,被称为动态数组。它与array的区别是它提供了动态空间大小。

2024-03-02 17:48:02 1054

原创 C++内存泄漏:原因、预防、定位

通过编写自定义的内存分析工具,可以在应用程序中插入代码来跟踪内存分配和释放的情况,从而帮助定位内存泄漏。

2024-03-02 16:51:08 4300

原创 2.STL源码解析-空间配置器

空间配置器就是给容器分配空间的。像我们平时使用new和delete动态分配释放对象内存一样。空间配置器也封装了这些功能。但是STL的空间配置器不仅仅只简单调用分配空间,它在一些地方都做了优化来提升性能。

2024-02-05 21:00:34 871

原创 1.STL源码解析-迭代器Iterator

设计迭代器的时候,需要设计适当的相应型别以及对应的符号重载。而设计适当的迭代器,则是容器的责任。只有容器才知道该设计出怎样的迭代器来遍历自己,并执行迭代器该有的各种行为(前进、后退、取值、取用成员等)。而算法,完全是独立于容器和迭代器之外的,可以自由设计,在设计时以迭代器为对外接口就行了。traits技法广泛用于STL中,它利用“内嵌型别”的编程技巧,与编译器的模板templete参数推导功能,来为C++提供型别识别的能力。

2024-02-05 20:57:05 1039

原创 C++11的半同步半异步线程池

半同步半异步线程池用的比较多,实现也比较简单。其中同步层包括同步服务层和排队层,指的是将接收的任务排队,将所有的任务排队到一个队列中,等待处理;异步层指多个线程处理任务,异步处理层从同步层取出任务,并发处理任务。

2023-09-19 16:03:04 930 2

原创 C++11实用技术(五)泛型编程加载dll接口函数

3步看起来不多,但是如果加载上百个这样的函数,那就非常繁琐,可能会遇到重复命名、参数定义不一致等各种问题。C++11提供了方法可以通过泛型编程的方式,提供一个加载执行dll接口函数的通用函数。

2023-08-19 13:34:29 447

原创 C++11实用技术(四)for循环该怎么写

上述代码需要关注迭代器,也需要显示得给出容器的begin和end。不便于书写。C++11支持基于范围的for循环。如下。

2023-08-15 21:26:27 234

原创 C++多线程场景中的变量提前释放导致栈内存异常

因为传入参数num是一个局部参数,我们在fun中修改或读取param时,可能num已经被释放掉了,这时候修改或者读取param就会发生内存泄露,并且这里栈内存泄露。这是非常危险的,因为栈内存可能会造成无法估量的问题。{fun(num);,采用引用传递,并且void fun(int& param)中也采用引用入参的形式。此时可能就会产生内存泄露。上面std::thread funThread(上述是一个正常的多线程代码。

2023-08-14 20:23:35 851

原创 docker运行报错docker: Error response from daemon: AppArmor enabled on system but the docker-default prof

AppArmor(Application Armor)是Linux上的一个安全模块,用于限制进程的权限和行为。它通过定义访问控制规则来保护系统中的应用程序免受潜在的安全威胁。我们卸载掉了AppArmor之后,可能会有些安全问题,但不影响docker正常的调试使用。直接通过指令把apparmor卸载掉,简单粗暴。卸载之后,运行docker即正常运行。安装完docker之后,运行报错。

2023-08-12 21:42:19 2251

原创 线程池-手写线程池C++11版本(生产者-消费者模型)

本项目是基于C++11的线程池。使用了许多C++的新特性,包含不限于模板函数泛型编程、std::future、std::packaged_task、std::bind、std::forward完美转发、std::make_shared智能指针、decltype类型推断、std::unique_lock锁等C++11新特性功能。本项目有一定的上手难度。推荐参考系列文章。

2023-08-08 21:40:30 374

原创 C++11实用技术(三)std::future、std::promise、std::packaged_task、async

C++的多线程指令是thread。例如# include # include // 线程函数,打印一条消息 void printMessage(const std :: string & message) {// 创建线程对象,并指定线程函数及其参数 std :: thread t(printMessage , "Hello, world!");// 等待线程执行完毕 t . join();return 0;我们可以通过thread创建多线程。

2023-08-06 23:35:02 318

原创 C++11实用技术(二)std::function和bind绑定器

C++11新增了std::function和std::bind。用于函数的包装以及参数的绑定。可以替代一些函数指针回调函数的场景。

2023-08-05 23:58:44 956

原创 C++ operator关键字的使用(重载运算符、仿函数、类型转换操作符)

C++11 中,operator 是一个关键字,用于重载运算符。通过重载运算符,您可以定义自定义类型的对象在使用内置运算符时的行为。operator可以重载我们运算符“±*/=”等;还可以重载我们的函数调用运算符"operator()";还可以做类型转换运算符。

2023-08-05 17:41:58 3184

原创 C++11实用技术(一)auto与decltype的使用

刚刚提到auto在推导变量类型时,所修饰的变量必须初始化。那不需要初始化的场景就需要使用到decltype关键字来做类型推导。这段代码编译不过,因为t,u在参数列表中,C++的返回值是前置语法,这里先推导返回值类型是找不到u,t的定义。两个关键字的用法有所不同,可以在不同场景中应用,也可以结合使用在某些场景中。auto和decltype是在编译时推导确认变量类型,所以也不会影响性能。因为编译器需要通过初始化来确定auto所代表的类型、即需要定义变量。这也是auto、decltype最常用的组合用法。

2023-08-05 15:51:26 400

原创 线程池-手写线程池Linux C简单版本(生产者-消费者模型)

本线程池采用C语言实现当某些任务特别耗时(例如大量的IO读写操作),严重影响线程其他的任务的执行,可以使用线程池线程池通常是一个生产者-消费者模型生产者线程用于发布任务,任务通常保存在任务队列中线程池作为消费者,用于取出任务,执行任务有一个经验公式: 线程数量 =(io等待时间+cpu运算时间)*核心数/cpu运算时间cpu密集任务:线程数量=核心数(即上面的公式假设cpu运算时间>>io等待时间)io密集任务:线程数量=2*n+2。

2023-08-02 22:28:47 1017

原创 # windows安装gcc、g++、pthread

在windows使用pthread函数时报错:无法打开源文件,通常是因为缺少pthread库。本文记录windows安装gcc、g++、pthread的操作流程。windows安装gcc、g++、pthread可采用mingw的形式安装。打开一下网页https://sourceforge.net/projects/mingw/files/,下载mingw-get-setup.exe运行 mingw-get-setup.exe安装mingw,需要注意安装目录,记住安装目录,待会需要设置环

2023-08-02 16:56:43 3128 1

原创 visual studio 生成dll文件以及修改输出dll文件名称操作

Windows系统下Visual Studio可以通过.def文件创建dll。

2023-08-02 16:36:54 5869 1

转载 HTTP之HTTP1.0/HTTP1.1(pipline)/HTTP2.0(多路复用)/HTTP3.0(QUIC)

2015 年,HTTP/2 发布。HTTP/2 是现行 HTTP 协议(HTTP/1.x)的替代,但它不是重写,HTTP 方法/状态码/语义都与 HTTP/1.x 一样。HTTP/2 基于 SPDY3,专注于性能,最大的一个目标是在用户和网站间只用一个连接(connection)。HTTP/2 由两个规范(Specification)组成:虽然 HTTP/2 解决了很多之前旧版本的问题,但是它还是存在一个巨大的问题,主要是底层支撑的 TCP 协议造成的。

2023-07-31 20:13:53 279

原创 HTTP之Session、Cookie 与 Application

cookie、seesion、application三个都会缓存我们用户状态的数据,使得我们在浏览器访问网站时可以更快速的获取到信息。主要原因在于HTTP协议是无状态的,我们每次访问服务器,对于服务器来说都是一个单独的请求,没有上下文的联系。以淘宝登录的例子来说明:假如我们输入我们的淘宝账号和密码登录后,我们浏览商品、加入购物车、付款等步骤,都会向服务器发出一条条的请求,但是服务器怎么知道这些请求是你这同一个用户发的呢?主要就是靠的cookie、seesion、application来实现的。

2023-07-30 21:48:14 1398

原创 结构型设计模式:装饰器模式

这些组件可能只是完成一些核心功能。但在。

2023-07-25 19:06:25 413

原创 protobuf原理以及实例(Varint编码)

注意:每个字段的编号,需要按照顺序从1开始规则定义,最小编号是 1,最大的是 2^29 -1即536,870,911,其中 19000 到 19999不能使用(内定为Protocol Buffers使用)。其中Varint 编码最常用,可以看到int,bool,enum这类数据都使用的Varint 编码。从代码中可以看出来我们是从最低的7位开始处理的,通过移位指令一直处理到高位,直到剩余高位小于0x80,从代码逻辑可以看出这样的编码形式的优雅。为0表示这就是最后一个字节,不需要再读写一个字节了。

2023-07-18 20:52:06 397

原创 零拷贝技术(DMA、MMAP、sendfile)

上述操作多次的上下文切换与拷贝会影响性能。可以使用零拷贝技术mmap+writesendfile和splice来优化。

2023-07-17 20:15:29 765

原创 Redis(三)存储原理与数据模型(hash冲突、渐进式rehash)

在 redis 实例中假如形成了很大的对象,比如一个很大的 hash 或很大的 zset,这样的对象在扩容的时候,会一次性申请更大的一块内存,这会导致卡顿;但是rehash时,将hash表1的数据复制到hash表2是一个庞大的工程,可能会造成redis线程阻塞,影响redis性能。时间复杂度能达到O(logn)。Redis是key-value的结构,其中value包含:字典,双向链表,压缩列表,跳表,整数数组,动态字符串。其中redis中各value的数据结构根据不同的情况有不同的自动存储转换。

2023-07-16 19:38:50 1446

原创 Redis(二)网络协议和异步方式(乐观锁&悲观锁、事务)

监控机制触发:所有对数据库进行修改的命令,如SET、LPUSH、SADD、ZREM、DEL、FLUSHDB等,在执行之后都会调用multi.c/touchWatchKey函数对watched_keys字典进行检查,查看是否有客户端正在监视刚刚被命令修改过的key,有的话touchWatchKey函数会将监视的客户端的REDIS_DIRTY_CAS标识打开,表示该客户端事物安全性已经被破坏。lua脚本具备原子性;乐观锁在执行时,不会将数据锁住,其他客户端可以修改数据,当数据被修改了,本地就不更新,返回失败。

2023-07-16 19:38:32 741

原创 Redis(一)原理及基本命令(柔性数组)

Redis 是 Remote Dictionary Service 的简称,被称为远程字典服务;redis客户端和服务端是基于TCP建立网络通信的。Redis 是内存数据库(保存在内存而不是磁盘),是目前市面上高性能的key-value数据库;底层的数据结构就是hash,因此查找数据的复杂度为O(1);Redis属于非关系型数据库,用键值来存储。类似于哈希表数据结构。和MySQL这类关系型数据库是不一样的。参考MySQL(一)基本架构、SQL语句操作、试图redis中的字符串是一种动态字符串。

2023-07-16 19:34:49 855

原创 MySQL(六)主从复制

MySQL自带主从同步机制,安装了MySQL的设备可以通过设置相关参数来实现主从数据库的同步功能。

2023-07-15 18:10:46 602

原创 MySQL(五)缓存策略

由于 mysql 的缓冲层不由用户来控制,也就是不能由用户来控制缓存具体数据;访问磁盘的速度比较慢,尽量获取数据从内存中获取,所以需要缓存从内存中读取;主要解决读的性能;因为写没必要优化,必须让数据正确的落盘;如果写性能出现问题,那么可以使用横向扩展集群方式来解决;项目中需要存储的数据应该远大于内存的容量,同时需要进行数据统计分析,所以数据存储获取的依据应该是关系型数据库;缓存数据库可以存储用户自定义的热点数据;以下的讨论都是基于热点数据的同步问题;

2023-07-15 18:07:48 913

原创 MySQL(四)事务原理及分析

背景:之前提到MySQL可以并发操作,即多个MySQL客户端操作一个服务端中的数据库,因此涉及到并发访问的问题,所以就有事务的概念。定义:事务的本质是并发控制的单元,是用户定义一系列数据库操作的集合。这些操作要么都做,要么都不做,是一个不可分割的工作单位。组成:事务可由一条非常简单的 SQL 语句组成,也可以由一组复杂的 SQL 语句组成;MySQL innodb 下,单条语句都具备事务;可以通过 autocommit = 0;设置当前会话手动提交;事务具有ACID特性,即原子性、一致性、隔离性和持久性。

2023-07-15 17:35:08 589

原创 MySQL(三)SQL优化、Buffer pool、Change buffer

MySQL可以通过B+树来减少索引查处时的IO磁盘次数,但是每次查找、新增都去做磁盘IO的话,如果频繁操作还是会遇到瓶颈。因此就有Buffer pool和Change buffer的出现。

2023-07-15 16:52:22 716

原创 MySQL(二)索引原理以及优化

MySQL数据库是用来保存海量数据的,但是海量数据涉及到一个快速查找问题,怎么从海量数据查找到我想要的数据呢?常见的办法就是将表中每一列类比成索引来定位我是这一列哪一个单元。那我定位表中这一列的某一个数据,就通过索引去查找就好了。但肯定不能一个一个去遍历,这里就涉及到MySQL 数据库的数据结构组成。用一些数据结构可以加快查找效率。而MySQL常用的innodb存储引擎采用的是B+树作为索引的数据结构。为什么选B+树?有序数组+二分法:数组不便于增删节点,增删节点需变化节点之后的数据。

2023-07-15 16:24:24 637

原创 数据库三范式

范式是建数据表的一种标准。设计三范式的目的是为了。但是在查询某些信息时,可能涉及到多次查询,可以理解范式是一种时间换空间建表模式。

2023-07-15 14:15:13 818

原创 MySQL(一)基本架构、SQL语句操作、试图

MySQL是关系型数据库。数据库就是用来保存数据的。那关系型又是什么意思?关系型数据库就是类似于excel表格,每一行每一列中的每一个单元都能在表格中找到相关联的数据。整个库就像一张关系网。那非关系型数据库又是什么?非关系型数据库就类似于redis这种,用键值来存储。类似于哈希表数据结构。可以想象,键值对存储中的每个存储数据之间是没有关联的。

2023-07-15 13:07:02 28345

原创 为什么需要无锁队列

时,另外一个EnQueue操作做了一半,此时的 p->next 不为 NULL了,但是 tail 指针还差最后一步,没有更新到新加的结点,这个时候就会出现,在 EnQueue 并没有完成的时候, DeQueue 已经把新增加的结点给取走了,此时,队列为空,但是,p->next与 tail 并没有指向同一个结点。Cache中的数据会失效,因为它缓存的是将被换出任务的数据,这些数据对于新换进的任务是没⽤的。任务将⼤量的时间(睡眠,等待,唤醒)浪费在获得保护队列数据的互斥锁,⽽不是处理队列中的数据上。

2023-07-07 22:37:59 203

原创 原子操作CAS

悲观锁具有强烈的独占和排他特性。在有悲观锁的情况下,对数据进行处理,数据会处于锁定状态。前面讲到的synchronized同一时间,其他线程处于阻塞状态,就是一个独占锁,是悲观锁中的一种。乐观锁对数据有更加宽松的加锁机制,允,一般通过版本号机制+CAS来实现。适用于读操作比较多的场景。

2023-07-07 22:12:39 621

原创 gRPC远程调用协议

gRPC是一个现代的、高性能、开源的和语言无关的通用 RPC 框架,基于 HTTP2 协议设计,序列化使用PB(Protocol Buffer),PB 是一种语言无关的高性能序列化框架,基于 HTTP2+PB 保证了的高性能。

2023-07-07 22:05:13 351

STL源码解析,简体中文扫描版,带目录

STL源码解析,简体中文扫描版,带目录,STL源码解析,简体中文扫描版,带目录,STL源码解析,简体中文扫描版,带目录,S,STL源码解析,简体中文扫描版,带目录TL源码解析,简体中文扫描版,带目录,STL源码解析,简体中文扫描版,带目录,STL源码解析,简体中文扫描版,带目录,STL源码解析,简体中文扫描版,带目录,STL源码解析,简体中文扫描版,带目录,STL源码解析,简体中文扫描版,带目录,STL源码解析,简体中文扫描版,带目录,STL源码解析,简体中文扫描版,带目录,STL源码解析,简体中文扫描版,带目录,STL源码解析,简体中文扫描版,带目录,STL源码解析,简体中文扫描版,带目录,STL源码解析,简体中文扫描版,带目录,STL源码解析,简体中文扫描版,带目录

2024-01-02

基于C++11的线程池

本项目是基于C++11的线程池。使用了许多C++的新特性,包含不限于模板函数泛型编程、std::future、std::packaged_task、std::bind、std::forward完美转发、std::make_shared智能指针、decltype类型推断、std::unique_lock锁等C++11新特性功能。 本项目线程池功能分以下几个函数去实现: > threadpool.init(isize_t num);设置线程的数量 > threadpool::get(TaskFuncPtr& task);读取任务队列中的任务 > threadpool::run();通过get()读取任务并执行 > threadpool.start(); 启动线程池,并通过run()执行任务 > threadpool.exec();封装任务到任务队列中 > threadpool.waitForAllDone();等待所有任务执行完成 > threadpool.stop();分离线程,释放内存

2023-08-08

线程池Linux C语言简单版本

本线程池采用C语言实现。包括以下内容 > - thread_pool_create:创建线程池所需要的资源,包含不限于任务队列,子线程的创建。 > - thread_pool_post:用于任务的发布,将执行任务存在任务队列中。 > - thread_pool_destroy:用于线程池的退出,以及资源的销毁。 > - wait_all_done:join线程池所有子线程,等待回收子线程。 > - thread_worker:用于任务执行。 主要的核心点集中在thread_pool_post和thread_worker两个函数中,这两个函数也构成了生产者-消费者模型。本文采用队列+互斥锁+条件变量实现。

2023-08-02

本项目包括利用多线程、select、poll以及epoll实现的并发处理连接请求

服务器与客户端建立连接需要使用到一些接口,包括但不限于socket、bind、listen、accept.高并发编程会有一些服务器模型,例如reactor或proactor。这两类都要使用到IO多路复用,O多路复用是指单个进程/线程就可以同时处理多个IO请求。有三个方式select、poll、epoll。 select:将文件描述符放入一个集合中,调用select时,将这个集合从用户空间拷贝到内核空间(缺点:每次都要复制,开销大),由内核根据就绪状态修改该集合的内容。 poll:和select几乎没有区别,区别在于文件描述符的存储方式不同,poll采用链表的方式存储,没有最大存储数量的限制; epollepoll底层通过红黑树来描述,并维护一个ready list,将事件表中已经就绪的事件添加到这里,在使用epoll_wait调用时,仅观察这个list中有没有数据即可。

2022-04-21

epoll的reactor模型实现

Reactor 模型开发效率上比起直接使用 IO 复用要高,它通常是单线程的,设计目标是希望单线程使用一颗 CPU 的全部资源,但也有附带优点,即每个事件处理中很多时候可以不考虑共享资源的互斥访问。可是缺点也是明显的,现在的硬件发展,已经不再遵循摩尔定律,CPU 的频率受制于材料的限制不再有大的提升,而改为是从核数的增加上提升能力,当程序需要使用多核资源时,Reactor 模型就会悲剧。 文件中程序通过C语言,调用了相关的网络socket API完成的一个reactor并发服务器功能。能够实现消息的接收与回发。分析了程序的不同以及各自的特点。 文件解释了epoll与reactor的区别之处,分析了各自的特点。并最后通过程序演示了reactor模型的结果。

2022-04-20

空空如也

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

TA关注的人

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