- 博客(51)
- 收藏
- 关注
原创 TCP连接,如果server端所在机器突然掉电,client是如何以及多久感知tcp连接断开
那么总的重传次数为 tcp_retries2,即 15 次,而不是 3 次初始重传加上 15 次长期重传。换句话说,重传的总次数是 15 次,其中前 3 次由 tcp_retries1 控制。此场景下,client会一直重传报文,直到某个上限后,内核就会认为tcp连接断开,client就能感知到此tcp连接断开。所以,此场景下,在linux系统中,最少经过7875s,client才可以感知到tcp连接断开。没有发数据的场景下,会触发tcp的保活机制,也就是TCP keepalive。
2024-07-04 21:22:15
334
原创 CyberRT 一个多线程并发的bug
多线程去调用cyber GlobalData中Register接口,比如RegisterNode、RegisterChannel、RegisterService、RegisterTaskName,入参必须填相同的。都会出现coredump。
2024-01-19 17:10:25
456
原创 MQTT协议详解
mqtt属于应用层协议,在tcp上层,mqtt协议中的用户角色分为两类mqtt_broker(中心转发)、mqtt_client(pub/sub)。这两者之间的消息交互分为如下几类:连接/断开服务器、订阅/取消订阅、发布消息、心跳。
2023-12-26 21:27:54
1093
原创 聊聊dynamic_cast的原理和缺陷
运行时类型检查意味着 dynamic_cast 在运行时会检查类型的合法性,如果转换合法,则返回转换后的类型;其次,由于 dynamic_cast 需要 RTTI(运行时类型信息)的支持,如果禁用了 RTTI,dynamic_cast 也就不能使用了。要使用 dynamic_cast,父类必须要有虚函数,有了虚函数就会生成虚表,才能分辨我们的父类指针指向的是父类还是子类。这也是 dynamic_cast 的一个限制,只有当类中至少有一个虚函数时,这个类的类型才可以被 dynamic_cast 进行转换。
2023-11-22 20:55:42
636
原创 Leaky singletons的一种使用场景
这种说法没问题,但是这里Test的线程是在Test析构的时候join的,而Test是以shared_ptr的形式返回,并且又被使用方2持有着。使用方1在dlopen你的test.so的时候,会申请出这个static map的内存空间,你的test.so中会另外启动多个线程在对这个map进行读写操作。并且会将Test的shared_ptr返回给使用方2持有。重点来了,这个test.so是以共享库的形式被别人使用,而且是通过dlopen、dlclose的形式加载和卸载你的test.so。
2023-10-30 22:21:03
358
原创 编译器返回值优化(Return Value Optimization,RVO)
返回值优化 (Return Value Optimization, RVO) 是编译器一种抑制拷贝 (Copy Elision) 的优化机制,避免代码发生不必要的拷贝。虽然这是编译器的行为,但是并非所有情况下,编译器都会对返回值进行优化。这两种优化技术都可以在不改变程序语义的前提下提高程序的性能,通过减少数据拷贝和临时变量的创建,可以有效地优化函数的返回值处理。看这个运行结果,傻眼了吧,和上面预测的完全不一致,这里就是返回值优化起作用了。编译器并非万能,在某些场景下,返回值优化也会失效。
2023-10-17 21:32:10
483
原创 非阻塞模式下,send和recv返回值的各种处理
send/recv write/read 函数返回值大于 0,表示成功发送或成功接收了多少字节,但是发送或者接收的字节数可能是部分字节数,比如你需要发送buf_length长度的数据,但是send/write返回的n有可能 < buf_length,这是因为发送缓冲区可能已经满了。EINTR:当进程在一个慢系统调用中阻塞时,如果捕获到某个信号且相应信号处理函数返回时,这个系统调用不再阻塞而是被中断,就会调用返回错误(一般为-1)并设置 errno 为 EINTR。返回值小于0,需要区分errno。
2023-10-08 09:43:45
742
原创 TCP粘包拆包的原因及解决办法
通过自定义协议进行粘包和拆包的处理。这些方法都需要在应用层进行设计和实现,以便在TCP字节流中正确地识别出消息边界。一般场景下,定界符和长度字段是比较通用的解决方法。
2023-09-19 17:28:34
261
原创 C++ PIMPL 编程技巧
Pimpl (Pointer to Implementation) 是一种常见的 C++ 设计模式,用于隐藏类的实现细节,从而减少编译依赖和提高编译速度。它的基本思想是将一个外部可见类 (visible class) 的实现细节(一般是所有私有的非虚成员)放在一个单独的实现类 (implementation class) 中,而在可见类中通过一个私有指针来间接访问该实现类。这种技术用于构建具有稳定 ABI 的 C++ 库接口并减少编译时间依赖。
2023-09-04 20:38:46
223
原创 emplace_back和std::move结合使用的一些注意事项
这句一定要加,不然后面测试向vector中添加东西的时候vector会扩容并且拷贝元素,影响测试结果。再看如果给Test类加上移动构造函数。这里又说明了一个简单道理,这里说明个很简单的道理,
2023-08-18 10:03:09
419
原创 linux inotify的一些坑
linux提供了一种机制,可以动态感知文件的变化:inotify。使用inotify可以感知到某个目录或者某个文件所有的动态操作。
2023-08-09 22:32:56
509
原创 __builtin_expect作用
有了这个理论基础,我们在编写程序时,遇到 if/switch 这种选择分支的程序结构,可以将大概率发生的分支写在前面,这样程序运行时,因为大概率发生,所以大部分时间就不需要跳转,程序就相当于一个顺序结构,从而提高 cache 的命中率。简单来说,就是依据空间相近原则。也就是说,使用likely(),执行 if 后面的语句的机会更大,使用 unlikely(),执行 else 后面的语句的机会更大。通过这种方式,编译器在编译过程中,会将可能性更大的代码紧跟着起面的代码,从而减少指令跳转带来的性能上的下降。
2022-10-29 11:20:33
424
原创 Linux无文件渗透执行elf方式
比如说你使用了一个开源组件,开源组件以bin的形式提供,但是你并不想直接./bin去运行它,而是想把开源bin直接集成到自己的代码中,这样对外相当于隐藏了开源bin,直接提供你自身代码的bin。这种场景可以简单应用到Linux elf in-memory execution这种方式。这个头文件中有两个变量bin, bin_len。bin中保存的就是bin的十六进制数据,bin_len是bin的data长度。将你依赖的开源bin通过xxd -i生成头文件。将头文件写到刚才创建的mem_fd中。
2022-10-29 10:09:25
735
原创 Linux eventfd简介
Linux2.6.22引入了eventfd,eventfd是专门用于事件通知的文件描述符(fd)。它创建一个eventfd对象,eventfd对象不仅可以用于进程间的通信,还能用于用户态和内核态的通信。eventfd对象在内核中包含了一个计数器,该计数器是64位的无符号整数(uint64_t),计数不为零是有可读事件发生,read之后计数会清零,write则会递增计数器。...
2022-07-31 11:39:34
1203
原创 c++ 基类和派生类的虚函数表是否为同一个
派生类实现基类的虚函数时,基类中虚函数表和派生类的虚函数表地址不同,基类虚函数表中的虚函数地址和派生类虚函数表中的虚函数地址不同;派生类不实现基类的虚函数时,基类中虚函数表和派生类中虚函数表地址不同,基类虚函数表中的虚函数地址和派生类虚函数表中的虚函数地址相同。...
2022-07-29 23:51:23
1876
原创 Fast-DDS中GUID的概念简述
最近也是一直在看fast-dds的源码,基本都是看的一些框架和业务逻辑相关的东西。也碰到了个关于guid的问题,正好总结下guid的组成。可以看下这个图:也可以看下RTPS协议中对prefix和entityid的描述:在fast-dds中有两个角色有guid的概念:分别是rtps participant和rtps endpoint。RTPS Participant GUID:每个participant都有GUID,其中常量entityid_...
2022-07-08 21:38:38
669
原创 c++ 之future和promise
future和promise可以配合使用,主要作用是在不同线程间传递数据。举个简单例子,直接看代码:从这个代码可以看到主线程中声明了一个p,然后通过p.get_future()将promise和future绑定。再将promise变量传到set_promise线程中,在set_promise线程中对promise赋值。然后就可以在主线程中通过future的get获取promise设置的值。运行结果:这里需要注意的一点是。如果set_promise线程迟迟没有对promise设置值,那主线程的futur
2022-06-23 16:07:49
2396
原创 【apollo】cyber底层通信--订阅方如何获取数据
cyber中所有reader的创建都有node来管理,node是拓扑网络中最基本的节点,所有的writer/reader、service/client都统一由node管理,cyber RT framework 在RTOS上层,所有node和writer、reader的概念也都是为了和ROS的接口兼容。reader的创建代码,这里只列举其中一个:可以看到,这里其实是调用了NodeChannelImpl::CreateReader去创建的。再看这个函数这里主要还是对config做个到attr的转换,然后再
2022-06-18 12:10:06
1178
原创 c++模板元编程std::enable_if详解
c++模板元编程std::enable_if详解文章目录c++模板元编程std::enable_if详解std::enable_if 概述使用场景类型偏特化控制函数返回值函数参数场景std::enable_if 概述 // Primary template. /// Define a member typedef @c type only if a boolean constant is true. template<bool, typename _Tp = void>
2022-05-05 14:52:34
2898
原创 百度apollo cyber中shm共享内存的处理
百度apollo cyber中shm共享内存的处理文章目录百度apollo cyber中shm共享内存的处理文件位置主要逻辑condition的构造共享内存的创建和映射indicator1结构共享内存写入共享内存读取文件位置cyber transport中关于shm共享内存封装在cyber/transport/shm/中condition_notifier.cc/.h主要逻辑condition的构造这里主要是hash出一个key,并调init来创建共享内存。ConditionNotifier:
2022-04-01 16:42:42
1568
1
原创 百度Apollo cyber中的transport和shm处理整理
近期一直在阅读apollo中cyber部分的源码,所以把最近看的代码稍微整理了下。transport部分:transport构造,transport一开始就创建好了intra、shm、rtps这三种dispatcher。Transport::Transport | |->CreateParticipant // 给rtps用 | |->NotifierFactory::CreateNotifier // 这个notifier感觉没啥用啊 | |->intra_dispa
2022-03-21 18:49:26
934
原创 linux CPU 负载高问题分析方法
linux CPU 负载高问题分析方法文章目录linux CPU 负载高问题分析方法CPU平均负载平均负载含义平均负载多少合理平均负载与CPU使用率如何分析平均负载过高问题CPU平均负载平均负载含义平均负载是指执行uptime后显示的Load Average(平均负载),单位时间内,系统处于可运行状态和不可中断状态的平均进程数,也就是平均活跃进程数。平均负载多少合理当平均负载比cpu个数还大的时候,系统已经出现了过载。要综合三个不同时间间隔的平均值去比较。平均负载与CPU使用率平均负载和C
2022-03-11 17:07:30
1560
原创 操作系统内存管理总结
操作系统内存管理文章目录操作系统内存管理什么是物理内存使用物理内存的缺点虚拟内存技术虚拟内存虚拟内存技术特点虚拟内存如何映射到物理内存内存分页简单分页缺陷多级页表TLB什么是物理内存我们常说的物理内存大小就是指内存条的大小,但是也要看CPU地址总线的位数。使用物理内存的缺点单个进程直接操作物理地址,可能破坏系统多进程运行,多个进程同时操作同一地址空间,产生并发读写问题虚拟内存技术虚拟内存虚拟出来的内存,确保每个进程都有自己的地址空间,一般是4G。操作系统自动将虚拟地址空间映射到物理地址
2022-02-17 19:55:45
555
原创 c++模板的一些总结
模板文章目录模板模板概念函数模板类模板可变参数模板可变参数类模板使用规则可变参数函数模板使用规则可变参数模板注意事项模板特例化函数模板特例化类模板特例化模板概念模板就是实现代码重用机制的一种工具,它可以实现类型参数化,即把类型定义为参数, 从而实现了真正的代码可重用性。模版可以分为两类,一个是函数模版,另外一个是类模版。函数模板函数模板一般形式如下:template <typename T>返回类型 函数名(形参表){ //函数体}eg:template <t
2022-02-17 19:51:50
382
原创 阅读zlmediakit源码的一些整理
注:如下展示结构非单纯调用顺序,只是方便看代码1.zlmediaservermain | |->loadIniConfig //加载配置文件,如果配置文件不存在就创建一个 | |->initEventListener | |->addListener Broadcast::kBroadcastOnGetRtspRealm //监听kBroadcastOnGetRtspRealm事件决定rtsp链接是否需要鉴权(传统的rtsp鉴权方案)才能访问 | |->
2022-01-02 19:48:18
2396
原创 高性能编程的一些总结
高性能编程文章目录高性能编程高性能技术问题c++的编译器优化核绑定内存池无锁队列内存对齐高性能技术问题如何充分利用单个CPU资源如何高效调节多处理器任务分配如何提高输入输出速度如何在多任务间高效传递数据如何更高效利用内存如何确保计算与存储一致性如何利用专用硬件提升部门任务的计算性能c++的编译器优化普通静态优化O1 一级优化O2 二级优化O3 三级优化指令集支持编译期特性支持这里主要介绍普通静态优化O1一级优化,在不影响编译速度的前提下,尽量采用一些优
2021-12-24 23:03:34
575
原创 c++移动语义、万能引用、引用折叠、完美转发
想了解标题的内容,我们可以先简单了解下c++中的左值和右值。左值和右值左值:能对表达式取地址,就是左值右值:不能对表达式取地址,就是右值将亡值:和右值引用相关的表达式,这样的表达式通常是将要移动的对象、T&&函数返回值、std::move()函数的返回值等纯右值:就是c++98标准右值的概念这里可以把将亡值和纯右值都看作右值即可。左值引用和右值引用左值引用如下:int a = 1;int& ref = a; //ref 就是a的别名,a是左值,ref就是
2021-12-21 20:12:27
289
原创 常用git命令
git 常用命令把某个项目的远端仓库复制一份出来到本地git clone [url]检查文件当前状态git status暂存某次更新,每次更新后,都要执行git addgit add <file> <file> <file>...查看具体修改了什么,此命令比较的是工作目录中当前文件和暂存区域快照之间的差异,也就是修改之后还没有暂存起来的变化内容。若要看已经暂存起来的文件和上次提交时的快照之间的差异,可以用 git diff --cache
2021-12-21 16:15:34
139
原创 c++14特性
C++ 14函数返回值类型推导c++14 对函数返回类型推导规则做了优化:auto func(int i) { return i;}返回值类型推导也可以用在模板中:template<typename T>auto func(T t){ return t;}注意:函数内如果有多个return语句,必须返回相同的类型,否则编译失败如果return语句返回初始化列表,返回值类型推导也会失败如果函数是虚函数,不能使用返回值类型推导lambda参数auto
2021-11-29 22:37:42
680
原创 实现一个简单的shared_ptr
实现一个简单的shared_ptr需要考虑以下几点:构造函数中计数初始化为1;拷贝构造函数中计数值加1;赋值运算符中,左边的对象引用计数减1,右边的对象引用计数加1;析构函数中引用计数减1;在赋值运算符和析构函数中,如果减1后为0,则调用delete释放对象。代码如下:template <class T>class shared_ptr {private: T* ptr_; // 计数指针,如果用对象,每次初始化之后都是新的值;如果用static,则不同
2021-11-16 15:17:40
322
原创 c++ std::call_once
std::call_oncec++11提供了std::call_once来保证某一函数在多线程环境中只调用一次,它需要配合std::once_flag使用,示例如下:std::once_flag onceflag;void CallOnce() { std::call_once(onceflag, []() { cout << "call once" << endl; });}int main() { std::thread
2021-11-16 15:10:24
680
原创 git如何同步fork的项目
同步fork项目确定下是否建立了住repo的远程源git remote -v添加项目A的远程仓库地址到upstreamgit remote add upstream <你朋友项目A的仓库地址>再次确认下git remote -v把项目A的更新来到本地的upstream里git fetch upstream切换到你自己想要merge的分支,这里我用举例:mastergit checkout mastermerge项目A的更新到你的branchgit
2021-11-16 15:08:19
347
转载 c++匿名函数
匿名函数lambda表达式定义了一个匿名函数,可以捕获一定范围的变量在函数内部使用,一般是如下形式语法:auto func = [capture] (params) opt -> ret { func_body; };其中func是lambda表达式的名字,作为一个函数使用,capture是捕获列表,params是参数表,opt是函数选项(mutable之类),ret是返回值类型,func_body是函数体。一个完整的lambda表达式:auto func1 = [](int a) -.
2021-11-04 20:50:58
468
原创 c++ 移动语义
c++ 移动语义概念移动语义:转移所有权,和深拷贝的区别在于,深拷贝是对于别人的资源,自己重新分配一块内存存储复制过来的资源,而移动语义,类似于转让。对于那块资源,转为自己所拥有,别人不再拥有也不会再使用。示例class TestA {public: TestA(int size) : size_(size) { data_ = new int[size]; } TestA() {} TestA(const TestA& a)
2021-11-03 20:01:20
590
原创 c++左值 右值概念
左值 右值左值:可以放等号左边的,可以取地址右值:不可以放等号左边,不能取地址纯右值 将亡值右值又分为纯右值和将亡值纯右值:运算表达式产生的临时变量、不和对象关联的原始字面量、非引用返回的临时变量、lambda表达式等都是纯右值。将亡值:将亡值是指C++11新增的和右值引用相关的表达式,通常指将要被移动的对象、T&&函数的返回值、std::move函数的返回值、转换为T&&类型转换函数的返回值,将亡值可以理解为即将要销毁的值,通过“盗取”其它变量内存空..
2021-11-03 16:56:05
389
原创 C++ 委派构造函数
C++ 委派构造函数首先我们看下如下代码例子:class TestA {public: TestA() : a(1), b(2) { Init(); } TestA(int index) : a(index), b(2) { Init(); } TestA(int index1, int index2) : a(index1), b(index2) { Init(); } private: void Init(); int a; int b;};TestA有三个
2021-10-14 18:12:01
188
原创 c++ 继承构造函数
c++ 继承构造函数class TestA {public: TestA(string i): a(i) {} ~TestA() {} string geta() { return a; } virtual string getb() = 0;private: string a;};class TestB: public TestA{public: TestB(string i):TestA(i),b(i) {}
2021-10-11 18:12:53
5124
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人