自定义博客皮肤VIP专享

*博客头图:

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

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

博客底图:

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

栏目图:

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

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

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

原创 trace-cmd记录线程被中断打断的时间

(3)执行任务过程中有内存操作,内存操作肯呢个引起缺页中断,用户同样的内存操作,有缺页中断和无缺页中断,所消耗的时间是不一样的。使用trace-cmd report可以查看监听结果,结果如下,通过结果进一步分析,我们就可以确定线程被中断打断的时间。(5)以上情况都没有,但是同样优先级的线程比较多,也就是系统负载比较高,这个线程的运行需要排队等待。(1)线程主动让出了cpu,比如线程中出现了sleep,使用了互斥体,等待io等。(2)线程被动让出cpu,线程被更高优先级的线程抢占。

2025-09-11 21:21:59 363

原创 xdp 入门

xdp 全称 eXpress Data Path,是 linux ebpf 中的一个功能。ebpf 在内核中预留了一些插入点,用户可以在这些插入点插入自己的处理逻辑,当数据路过插入点时可以做一些预期的处理,具体实现方式如下:① 用户编写数据处理代码,也就是对于路过这个插入点的数据想做什么处理② 将代码编译③ 将编译好的目标文件安装到插入点安装之后,数据路过插入点时便会被安装的代码处理。插入点的处理逻辑就像一些路口的收费站,不同身份的车辆通过收费站的时候,可能需要做不同的事情。

2024-02-28 18:08:19 5275

原创 linux下怎么定位内存泄漏

正常情况下,软件使用的内存是随着时间在一定范围内波动的。内存泄漏说的是随着时间的推移,进程使用的内存越来越多。一般情况下,内存泄漏是程序不断地申请内存,但是没有释放导致的。

2024-02-27 14:55:33 3864

原创 使用cgroup踩过的坑

cgroup 全称 control group,控制组。通过 cgroup 可以限制应用使用的资源,资源包括 cpu、内存、磁盘 io、网络等。工作中经常使用的 docker 容器就使用了 cgroup 进行资源限制和隔离,cgroup 是 docker 的基础。

2024-02-18 22:08:43 6964

原创 SCHED_FIFO 和 SCHED_RR 同时存在时,如何调度

(1)从上边的实验现象可以看出来,实验现象符合 SCHED_FIFO 先入先出,SCHED_RR 时间轮询的调度原理。(2)在实时调度策略中,高优先级具有绝对的优先调度的的特权,即使 SCHED_RR 这种时间片轮询的调度算法,也是说的多个 SCHED_RR 的优先级相等的前提下才会轮询,如果优先级不相等,那么只会调度优先级最高的那个线程。

2024-01-19 21:03:55 3276 1

原创 linux 中进程的 D 状态和 Z 状态

僵尸态是 linux 进程的一种状态,用 Z (zombie) 表示。处于 Z 状态的进程已经不在工作,进程的资源(内存,打开的文件) 都已经释放,只保留 struct task_struct 一个空壳子,用僵尸来表示这个状态非常形象。僵尸进程不能被信号杀死(因为僵尸进程已经死了,当然也不能响应信号),只能被父进程回收。进程处于僵尸态时保存的信息非常少,其中包括进程号,退出码,退出码是比较重要的,父进程回收僵尸进程的时候可以根据退出码确定子进程的退出原因。

2024-01-13 11:05:54 6392 1

原创 linux中fd的几点理解——一切皆文件

fd 全称是 file descriptor,文件描述符,又称句柄。当我们在打开一个文件,创建一个 socket, 创建一个 epoll 时,返回值往往都用一个变量 int fd 来表示。

2024-01-13 10:35:03 4884 1

原创 rust:泛型

泛型的概念在c++中也有,泛型就是将类型参数化。泛型到的优点是提高代码复用率,相同逻辑、不同参数类型的只需要实现一份就可以。函数模板,类模板,结构体模板:概念落脚点是模板,表示一个模板,用来生成具体的函数、类、结构体。模板函数,模板类,模板结构体:概念落脚点事函数、类、结构体,是模板生成的对象。

2025-11-22 19:19:29 764

原创 rust:所有权

②引用传递,和c++有不一样的地方,c++的函数形参如果接受引用那么就是std::string &str这样的方式,函数调用处的实参不需要使用&来指定,rust中的函数声明以及实参调用的地方都需要使用&来指定是一个引用。④在同一个作用域,只能有一个可变引用,或者1个或多个不可变引用,可变引用和不可变引用不能同时存在。③变量本本身是mut,即可变的,这个变量才可以被可变引用;mut变量可以被不可变引用,也可以被可变引用;赋值和值传递,就类似于c++中的unique_ptr,即独占指针,语义是类似的。

2025-11-16 16:07:39 478

原创 c语言:double a = 3 / 2,a等于多少

e和f的区别:f中将a转换为了double类型,这样表达式就一个数据时double一个是int,表达式的类型就转换为了double;c = a/b这样是一个表达式,但是在计算a/b的是时候a/b本身也是一个表达式,这个表达式中都是int数据类型,也就不会转换成浮点类型。c语言中不同类型的数据进行计算,会进行默认类型转换,转换的原则是向精度高的方向转换,这样能保证不丢失精度。表达式的数据类型要转换成精度最高的那个数据类型的精度,这点没问题,但是要区分表达式的边界。那么下边的代码,c、d、e、f分别是什么?

2025-11-16 12:09:59 122

原创 编译动态库时只需要知道函数的声明,与可执行文件不同

通过g++ -fPIC -shared -o libhello.so lib.c编译动态库,可以编译成功,编译过程并不会去找构造函数Hello和Say函数的实现。main.c:包含了hello.h头文件,并且创建了Hello,执行了Say函数。lib.c:包含了hello.h头文件,并且创建了Hello,执行了Say函数。在编译动态库的时候,不需要知道函数的实现,只需要知道函数的声明就可以。hello.c:类的实现,定义了Hello构造函数和Say函数的实现。编译可执行文件的时候,需要知道函数的实现。

2025-11-15 20:34:49 119

原创 fastdds qos:UserDataQosPolicy

需要继承DomainParticipantListener,并实现on_paricipant_discovery,on_data_reader_discovery,on_data_writer_discovery三个函数。②创建DomainParicipant时需要传this指针,并且status_mask,要设置data avaliable,否则DataReader无法订阅到数据。DmainParticipant,DataWriter,DataReader读可以设置user data。

2025-11-02 17:03:19 177

原创 fastdds qos:PartitionQosPolicy

PartitionQosPolicy也可以对topic进行分区,使得DataWriter和DataReader在满足默认条件的情况下,还要满足PartitionQosPolicy的匹配规则,才能相互发现。否则,不能相互发现。subscriber,没有指定Partition,可以与publisher的空Partition匹配,所以可以订阅到数据。publisher指定了三个Partition,一个hello,一个world,一个是空。④支持空的字符串,也就是空的字符串也是有效的。

2025-11-02 09:55:31 260

原创 架构设计常画哪些图

在架构设计时,经常需要画图。在大多数时候,我们工作的团队并没有对架构设计中的图做规定,只要能把架构表达清楚即可,对于比较简单的软件,甚至不需要画图,只使用文字就可以描述清楚。这种因人而异的画图方式,比较灵活,并且效率高,用较少的图就能表达较多的信息,一张图中既能表达静态信息,又能表达动态信息,但是不利于跨团队之间的合作(很多时候也不需要跨团队合作,当然也没有问题)。当需要跨团队合作,或者多个人协同开发的时候,统一画图标准,往往就比较重要。

2025-10-08 17:27:15 694

原创 malloc:arena

多线程应用中,并发调用malloc,malloc的实现中,多线程之间需要锁进行同步吗?大部分时候是不需要的。每个线程有自己的tcache,有自己的arena,有自己的堆。所以说,对于多线程的进程来说,多个线程有自己的堆,而不是共用一个堆。glibc中的malloc管理,为了减小多线程之间并发调用malloc时的同步,引入了arena和tcache。

2025-10-02 20:10:01 292

原创 mlockall踩坑记录

对mlock相关函数的第一印象就是:锁定内存,不让内存进行swap。在堆实时性有要求的系统里,往往需要使用mlock,如果内存被swap,即内存数据被保存到吸盘,那么访问数据的时候,就会引入很大的不确定性。

2025-10-02 08:10:44 990

原创 c++:std::string,std::function,std::vector隐式申请动态内存

①如下代码,声明一个局部std::string变量s,打印出来s的capaciy为15,也就是说,默认情况下,std::string能保存15个字符,不需要动态申请内存(对malloc设置断点,没有打断,说明没有动态申请内存)。②向s赋值一个长度为15的字符串,不会申请动态内存。③向s赋值一个长度为16的字符串,会申请动态内存,会调用malloc。

2025-10-01 09:54:32 305

原创 设计模式:观察者模式

我们在开发中经常使用回调函数的思想,想要观察一个对象的状态变化,就向该对象注册一个回调函数,当对象状态变化的时候,调用注册的回调函数。如果有多个观察者呢,注册的回调函数就可以放到数组中,当对象状态变化的时候,依次调用数组中的回调函数。当然也可以实现一个观察者接口,每个观察者都实现接口,创建一个观察者对象,然后将对象注册给被观察者。当被观察者状态发生变化时,逐个调用观察者的函数。观察者模式,关键自是观察者,Observer。微信群、钉钉群,当有人在群里发送信息时,每个读者都是观察者,发消息的人是被观察者。

2025-09-13 19:46:37 161

原创 linux线程被中断打断,不会计入调度次数

通过线程的status文件,可以查看线程的调度次数。status的最后两行,voluntary_ctxt_switches表示线程的资源调度次数,比如线程调用了sleep睡眠,或者调用io接口发生了阻塞,均会统计为主动调度次数;nonvoluntary_ctxt_switches表示非自愿调度次数,比如线程在运行过程中被强张了。

2025-09-11 21:21:37 351

原创 fastdds qos:LifespanQosPolicy

在实际业务中,如果对数据的新/旧程度有要求,比如数据产生之后如果1ms都没有被使用,那么数据就相当于过期了,没有使用价值了,这种数据直接丢弃就可以了。如果有这种需求,那么可以考虑结合LifespanQosPolicy来实现。通过helloworld进行测试,将超时时间设置的非常短100ns,实际测试可以看到DataReader接收不到DataWriter发送的数据。(1)当DataWriter写数据History的数据,或者接收数据到DataReader的History的数据,均可以加时间戳。

2025-08-30 18:42:16 328

原创 fastdds qos:OwnershipQosPolicy、OwnershipStrengthQosPolicy

DataWriter1和DataWriter2的OwnershipQosPolicy都是独占类型,OwnershipStrengthQosPolicy的strength分别是100和90。TODO:待验证,通过tcpdump抓包,在DataReader所在的机器,能抓到DataWriter2发送的数据。当DataWriter1和DataWriter2同时存在时,DataWriter2的数据会真正被发送,也会被DataReader所在的进程接收,但是对于用户是读取不到DataWriter2的数据的。

2025-08-29 07:18:27 166

原创 fastdds:topic instance

如果让我们自己实现,我们在定义数据类型的时候,除了摄像头数据之外,我们还可以增加一个id属性,用id来区分数据来源于哪个摄像头,这种方式直观,好理解,完全可行。从fastdds example中的topic instances例子来看,DataWriter在创建的时候,可以针对每个key创建一个句柄,这样在发送数据的时候,不需要对数据类型中的key字段进行赋值,只需要使用key对应的句柄进行发送即可。试想,如果我们自己实现对每个instance的状态机的维护,还是有一定的复杂度的。

2025-08-24 22:01:35 381

原创 fastdds qos:DurabilityQosPolicy

假如DataWriter先起来,并且已经写了一些数据,之后有新的DataReader起来,那么新起来的DataReader能不能接收到它启动之前,DataWriter发布的数据呢。DurabilityQosPolicy用来做这种控制。VOLATILE_DURABILITY_QOS:易失的,新上线的DataReader只能读取上线之后,DataWriter发布的数据。

2025-08-23 17:40:30 748

原创 fastdds qos:DeadlineQosPolicy

DeadlineQosPolicy这种qos使用在DataWriter、DataReader、Topic。该qos用来监督数据是不是按照预期的频率进行收发。假如数据是周期性发送和接收,周期是固定的100ms,我们如果想要监督数据收发是不是按照预期的周期进行的,那么就可以配置DeadlineQosPolicy。以fastdds example中的hello_world为例,数据每100ms发送一次,我们配置DataWriter和DataReader的deadline为90ms,

2025-08-23 14:40:14 499

原创 tcp会无限次重传吗

超过这个次数,tcp会放弃重传,然后通过函数tcp_write_err将套接字的状态置错误。socket状态置为错误之后,针对这个socket的阻塞调用,比如read,epoll_wait等便会返回,但是返回值表示错误。tcp作为面向连接的,可靠的,字节流。最终要的特点就是可靠,其中重传又是保证可靠的重要前提。那么当tcp发送数据之后,收不到ack的情况下,会无限次重传吗。超过这个次数,tcp会将信息报告给网络层,网络层会进行一些操作,比如缓存的更新等。在建立连接的阶段,syn报文的重传次数。

2025-08-17 20:50:47 312

原创 fastdds:默认qos

Publisher、Subscriber、DataWriter、DataReader、Topic均可以应用qos策略,不同的qos策略的使用范围是不一样的:DeadelineQosPolicy适用于Topic、DataWriter、DataReader;具体每种策略的适用范围,可以看官方文档的描述,也可以看fastdds源码,以TopicQos为例,源码中唵TopicQos类来管理,其中的汽油成员如下,说明这些qos策略适用于qos。(3)qos策略需要匹配,通信的双方才能通信。(2)qos策略适用对象。

2025-07-23 21:58:42 458

原创 c++无锁队列moodycamel::ConcurrentQueue测试结果

在c++开发中,无锁队列moodycamel::ConcurrentQueue使用较多,示意图如下:从宏观来看moodycamel::ConcurrentQueue是MPMC队列,即多生产者,多消费者队列;从微观来看,是SPMC队列,即单生产者,多消费者队列。在ConcurrentQueue中,没个生产者都有自己对应的队列。这也引入了ConcurrentQueue的一个特点:ConcurrentQueue只能保证单个生产者的FIFO特性,即对于一个生产者来说,元素出队的顺序和入队的顺序是一样的。

2025-07-13 13:40:23 937

原创 优先级继承和优先级天花板(pthread_mutexattr_setprotocol)

在B获取锁之后,释放锁之前,A想要获取锁,这个时候,如果B线程没有被其它线程抢占,正在运行,那么A等待B执行完毕即可,符合预期,既然用户实现了这样的业务,即两个不同优先级的线程会抢一个锁,那么就要有这样的预期。而如果这个时候出现了第三个线程C,C的优先级大于B,小于A,那么这个时候C会抢占B的执行,这种现象导致的结果才是不符合预期的。在B获取锁之后,释放锁之前,A想要获取锁,这个时候为了让B尽快执行完,会将A的优先级提升到B的优先级。那么不管哪个线程获取到锁,或者在等待锁,那么线程的优先级都是调整为30。

2025-06-21 16:11:26 442

原创 leetcode:最小覆盖字符串

对于算法题目,自己能想到的往往是最基础的笨方法。代码如下:如果t的长度是len1,s的长度是len2,那么最小窗口是len1,最大窗口是len2。所以可以从len1到len2,遍历窗口大小,对于每个窗口大小,将窗口从前向后进行移动。因为窗口是从小到大进行遍历,所以第一次遇到满足条件的子串时,就可以直接范围。这种算法的时间复杂度是O(n*n),在leetcode上运行会超时。

2025-05-04 18:44:30 492

原创 递归下降算法

在软件开发中有这样一个需求,开发语言是c++,用户可以通过配置指定任务依赖的事件,比如配置e1|e2|e3的意思是,e1、e2、e3 3个事件,只要有一个到来,那么条件就是满足的,任务可以执行;在比如,用户还可以配置(2*e1 | e2) & e3,这样复杂的逻辑,表示e3是必要的,另外e1到来两次或者e2到来一次也是必要的。事件的个数不仅仅是3个,还可以更多,逻辑关系包含|表示或,&表示与,*表示时间到来的次数,逻辑关系可以任意组合。之前只听说和使用过递归算法,递归算法就是在函数内部调用函数本身。

2025-05-04 18:15:41 373

原创 uml类关系(实现、继承,聚合、组合,依赖、关联)

drawio和EA是架构设计时经常使用的画图工具。drawio学习门槛低,使用灵活,但是功能仅仅限于画图。EA学习门槛高,但是功能更加的丰富:①在画图方面,EA严格满足UML标准,EA中的图和类是关联的,如果修改了一个类的名字或者函数等,在引用这个类的图中也会自动修改②EA还可以将架构设计时定义的类、接口等导出为代码③EA可以导入已有的代码,生成类图。

2025-04-26 17:40:21 1247

原创 fastdds:传输层SHM和DATA-SHARING的区别

下图是fastdds官方的图,清晰地展示了dds支持的传输层:根据通信双方的相对位置(跨机器、同机器跨进程、同进程)的不同选择合适的传输层,是通信中间件必须要考虑的事情。跨机器通信,只能通过网络, fastdds支持UDP和TCP。在同一个机器中,使用UDP和TCP进行通信,当然也是可以的。但是,从性能的角度来考虑,更推荐使用SHM,SHM和UDP/TCP相比有2点优势:1、减少系统调用次数共享内存创建完成之后,后边使用的时候直接是内存操作,而UCP/TCP每次发送或者接收的的时候,都要通过系统调用。

2025-04-18 21:37:23 1567

原创 fastdds:传输层端口号计算规则

假如A发布的多播消息,那么B和C都会收到,如果B和A之间有相同topic的writer和reader,也就是说B和A是可以通信的,那么B就会向A发送单播消息,进行后续的协商,后边的协商过程均通过单播来实现。participantId的分配如下代码所示,同一个进程的同一个domain内,participantId都是从0开始的,也就是说participantId并不是domain内唯一的,而是domain和进程内唯一的。同样的,如果单播端口已经被占用,那么就会进行重试,重试的算法是在上一个端口的基础上加2。

2025-03-30 20:25:07 1255

原创 stack smashing detected

本文先介绍stack smashing detected问题现象,然后介绍问题产生的原因,最后介绍问题定位思路。

2025-03-22 12:05:24 1224

原创 leetcode:单词距离

遍历数组,当遍历到word1时更新index1,遍历到word2时更新index2。当index1和index2均不为-1时,则计算两者之差,如果两者之差比上一次计算的值小,则进行更新,否则不更新。对于这种情况,上边的两种方式,都可以解决,缺点是时间复杂度偏高。想要避免这种重复的工作,可以在第一次遍历的时候将每个单词的下标用map保存下来,map的key是word,value是单词下标的vector,单词下标从小到大进行存放。题干中说,如果文件多次输入,并且每次的两个单词都不相同,能不能优化?

2025-03-08 10:10:41 335

原创 设计模式:迭代器模式

但是对于一些复杂的数据结构,比如二叉树、map、set等,遍历操作就比较复杂,如果每次遍历这样的数据结构都要自己写遍历代码,这样的工作效率是比较低下的。这就给我们提供了一些写代码的思路,即使没有学习过设计模式,那么在写代码的时候,也可以想代码实现的是不是一个独立的、高内聚的功能,这样的代码是不是可以抽象出来,提高复用性。对于线性数据结构来说,迭代器模式,和直接使用下边的方式,复杂成都市差不多的,但是对于复杂的数据类型,比如map或者set,迭代器就有用了。比如编程语言标准库中的代码,修改的频率是比较低的。

2025-03-05 21:35:01 501

原创 std::thread:join/detach

用于线程间同步,特别是在主线程退出的时候,等待进程中的所有其它线程都退出之后,主线程再退出,这样能保证进程安全的退出。试想,如果主线程退出的时候,有其它线程还在运行,很容易导致进程的退出码不是0,或者被信号杀死。因为进程退出的时候就要释放所有的资源,而此时还在运行的线程可能会使用已经释放的资源,这样就会导致段错误。调用join之前,需要使用joinable进行判断现成是不是可join,如果线程不可join,那么调用join会抛异常。

2025-03-02 15:18:05 761

原创 设计模式:代理模式

代理模式是很常见的设计模式,即使没有专门学习过这种设计模式,在工作中也一定用过这种设计模式。在实际生活中,代理模式也是常见的,比如内阁首辅相对于皇帝,前者是后者的代理,内阁首辅收到奏折时,往往也要做一些预处理和后处理。当我们需要给原始类增加一些功能、日志、性能监控时,通过修改原始类当然是可以实现的,但是这样就侵入了原来的逻辑,违背了开闭原则。并且新增的功能与原有的功能本来就属于不同范畴的功能。在不修改原始类的基础上,增加新的功能,就需要用到代理模式。有些类也是无法修改的,这种情况下,只能使用代理模式。

2025-02-16 17:58:07 524

原创 设计模式:状态模式

状态机有3个要素:状态,事件,动作。假如一个对象有3个状态:S1、S2、S3。影响状态的事件有3个:E1、E2、E3。每个状态下收到对应事件的时候,对象的动作为AXY。那么该对象的状态机就可以用如下表格来表示。S1收到事件E1的时候动作为A11,收到事件E2的时候动作为A12,收到事件E3的时候动作为A13,以此类推。其中,动作可以是状态发生切换,也可以是其它与业务有关的动作。

2025-02-16 12:10:36 1252

原创 linux内核网络分层概述

在开发应用时,我们使用 socket 实现网络数据的收发。以tcp为例,server端通过 socket, bind, listen来创建服务端,然后通过 accept接收客户端连接;客户端通过 socket和 connect系统调用来创建客户端。用于数据收发的系统调用包括 send, recv, sendto, recvfrom等。除了上述系统调用之外,另外还有多路复用技术 select,poll, epoll,也常常在网络应用中使用。在做应用开发时,使用上述系统调用比较简单和简洁。对于 linux

2024-12-22 09:43:32 1033

空空如也

空空如也

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

TA关注的人

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