自定义博客皮肤VIP专享

*博客头图:

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

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

博客底图:

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

栏目图:

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

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+

方亮的专栏

方亮的专栏

  • 博客(473)
  • 资源 (2)
  • 收藏
  • 关注

原创 谈代码注释

只要写代码,就会遇到代码注释的问题。在不同的公司,不同的项目组,不同的项目中,可能会有不同的注释标准。有些标准让我们感觉很受益,有些则让我们感觉很反感。而对于没有明确标准的项目,我们往往会遇到“百花齐放,百家争鸣”般的注释。我无法给出一个明确的标准,只是在此探讨下:什么样的注释不应该写,什么地方需要写注释。(转载请指明出于breaksoftware的csdn博客)“不”的原则...

2018-04-01 01:24:25 10434 11

原创 Robot Operating System——ParameterEventHandler监控Parameters的增删改行为

AsyncParametersClient和SyncParametersClient的on_parameter_event的功能和ParameterEventHandler::add_parameter_event_callback比较类似,会通知所有Parameter的变动;

2024-07-27 00:30:00 1061

原创 Robot Operating System——AsyncParametersClient监控Parameters的增删改行为

在一文中,我们使用Node::add_post_set_parameters_callback设置一个回调函数,用于在Parameters设置成功后,执行相关后续动作,但是这种行为发生在Node内部。如果我们希望在Node外部监控Parameters变动,则可以使用SyncParametersClient或者AsyncParametersClient类的on_parameter_event方法设置一个回调函数来监控。我们分别以同步和异步的方式讲解这个功能。

2024-07-27 00:15:00 511

原创 Robot Operating System——Parameter设置的预处理、校验和成功回调

在一文中,我们通过Node的add_on_set_parameters_callback方法,设置了一个回调函数,用于校验传递过来的Parameter参数。但是这个方法并不能对传递过来的内容做预处理,只能做校验。当我们需要干涉传入的Parameters时,比如填入一些默认值或者做某些计算,则需要使用预处理程序。如果Parameters设置成功,我们还可以通过成功回调函数来做对应值变更后的逻辑计算。

2024-07-26 00:30:00 859

原创 Robot Operating System——对Parameter设置进行校验

通过Node的add_on_set_parameters_callback设置回调函数,可以对传入的Parameters信息做预处理。如果回调函数返回的rcl_interfaces::msg::SetParametersResult::successful为true,框架就会对所有传入的Parameters做出修改;否则就放弃本次修改请求。

2024-07-26 00:15:00 487

原创 Robot Operating System——深度解析Parameter同步操作的底层实现

Parameter同步操作是通过对异步操作的封装来实现的。而在ROS2系统中,诸如spin_until_future_complete等待一个Node完整相关任务的操作,其在系统底层并不是一味地等待。而是尽量利用等待的空隙,完成一些诸如timer等可能已经被触发的行为。这样的设计虽然不能在系统上严格保证Wait时间的准确性,但是很大程度上利用了系统CPU资源,而不是让其一直IDLE。

2024-07-25 00:30:00 1141

原创 Robot Operating System——空Node的Service和Parameters

在中,我们提到Node自身作为Parameters相关Service的服务端,与我们创建的rclcpp::SyncParametersClient、rclcpp::AsyncParametersClient客户端通信。本文我们将看看一个空的Node提供了哪些默认的Service和Parameters。参考的例子是demo_nodes_cpp/src/parameters/parameter_blackboard.cpp。其内容非常简单:继承于Node类,并自动声明了Node中的Parameters。

2024-07-25 00:15:00 708

原创 Robot Operating System——取带前缀的Parameters

在一文中,我们看到如何使用get_parameters通过精确的Key来查询Parameters的值。本文将介绍一种通过前缀遍历所有符合条件的Parameters的方法。我们还是分为同步和异步两种模式来讲解。

2024-07-24 00:30:00 1240

原创 Robot Operating System——初探动态配置Parameters

本文的两个例子,分别使用SyncParametersClient和AsyncParametersClient从Node外部设置和查询Node的Parameters。实际我们在Node内部可以通过Node类中的set_parameter方法操作本Node的Parameters。

2024-07-24 00:15:00 1237

原创 Robot Operating System——Service的同步/异步通信

在ROS 2中,除了介绍的Topic,还有其他通信机制。Service就是其中一种。Service是一种同步的请求/响应通信机制。一个节点可以提供一个Service,其他节点可以请求这个Service,并等待响应。Service由Service类型定义,包括请求和响应消息。

2024-07-23 00:30:00 615

原创 Robot Operating System——深度解析“借用内存型消息”

在前期,普通消息处理会有很多智能指针以及内存分配操作;而序列化消息和借用内存型消息没有太多复杂操作。在后期,普通消息和序列化消息比借用内存型消息多了一次序列化。所以整体看,借用内存型消息的效率是最高的。

2024-07-23 00:15:00 948

原创 Robot Operating System——借用内存型消息

在ROS 2中,"loaned message"是一种消息传递机制,用于在发布者(publisher)和订阅者(subscriber)之间传递数据。它是一种高效的消息传递方式,可以避免不必要的数据复制。在传统的ROS中,消息是通过复制的方式进行传递的,即发布者将消息复制一份发送给订阅者。这种方式在数据量较大或频繁传递消息时可能会导致性能问题。而在ROS 2中,引入了"loaned message"的概念。当发布者发送消息时,它不会直接复制消息,而是将消息的所有权(ownership)转移给订阅者。

2024-07-22 00:30:00 789

原创 bug诞生记——动态库加载错乱导致程序执行异常

这个案例发生在我研究ROS 2的测试Demo时发生的。整体现象是:修改了源码,编译也成功了,但是执行流程和没修改前一致,新代码的逻辑没有体现。最后定位到“动态库加载错乱”这个根本的问题,方案也就呼之欲出。但是整个排查过程经历了若干假设和推导,还是值得记录下。

2024-07-22 00:15:00 858

原创 Robot Operating System——深度解析序列化的实现

本案例中,std_msgs::msg::String的裸指针最终在Serialization的底层,通过std_msgs::msg::String的std::basic_string类型成员data获得其最终大小,进而保证数据复制的空间是正确的。

2024-07-21 00:30:00 1102

原创 Robot Operating System——消息的序列化和反序列化

在ROS 2中,提供了一种叫做SerializedMessage的消息。我们可以将C类型或者C++类型变量序列化后发送,然后在接收端再反序列化还原。这种方案在有别于我们常见的通过Json串进行序列化和反序列化。它在底层会使用类型的内存模型去做数据拼装,而不是转成某种可视化的字符串,所以它的效率更高些。本文我们将通过案例看看消息序列化和反序列化的使用。

2024-07-21 00:15:00 771

原创 Robot Operating System——订阅者订阅过滤消息

和很多订阅者-发布者模型的中间件类似,ROS 2也支持订阅者消息过滤功能。我们通过下面这个“温度”检测器来查看如何使用该项技术。

2024-07-20 00:30:00 675

原创 Robot Operating System——定时器

定时器是一种编程构造,用于在指定的延迟后执行一次或多次代码。定时器可以是一次性的,也就是说,它们在指定的延迟后只触发一次;或者是周期性的,意味着它们会以指定的时间间隔重复触发。在ROS 2中,定时器是重复性的,但是我们可以通过一些方法达到一次性的效果。我们通过两个例子来熟悉ROS 2中定时器的用法。

2024-07-20 00:15:00 307

原创 Robot Operating System——topic的发布和订阅

我们以demo_nodes_cpp中的listener和talker来分析如何在ROS2中定制发布和订阅机制。

2024-07-19 10:36:09 993

原创 Robot Operating System——Ubuntu上以二进制形式安装环境

在众多ROS版本中,我们选择Jazzy Jalisco。

2024-07-19 10:35:19 305

原创 从汇编层看64位程序运行——栈保护

在中,我们看到可以通过“微操”栈空间控制程序执行流程。现实中,黑客一般会利用栈溢出改写Next RIP地址,这就会修改连续的栈空间。而编译器针对这种场景,设计了“栈保护”机制。

2024-07-17 00:30:00 943

原创 从汇编层看64位程序运行——ROP攻击以控制程序执行流程

一般我们运行有调用关系的代码,就像套娃一样,一个套着一个。比如main函数调用foo7函数,foo7调用foo函数,则main函数要先进入foo7,然后进入foo。等foo执行完,会回到foo7;等foo7执行完,再回到main。那么我们有办法脱离这种套娃模式,然后foo函数执行返回到main函数吗?当然是有的。这就需要使用ROP攻击。ROP攻击全称是:Return Oriented Programming (ROP) attacks。

2024-07-17 00:15:00 1213

原创 从汇编层看64位程序运行——所见非所写(编译器的优化),别做无用代码优化

我们发现函数的输入和输出对编译器的优化没有什么影响。但是最后一个例子我们发现,一个函数如果对外部产生影响,则其内部逻辑才不会被抛弃。编译器会按照它认为最优的方式优化代码,导致我们的C语言代码和最终编译结果在逻辑层面有非常大的差别,但是最终执行结果却是一致的。所以很多时候,我们在优化代码的时候,要深入汇编层确认后再去做,否则可能做的就是无用功,因为聪明的编译器已经帮我们优化了很多代码了。

2024-07-16 00:30:00 986

原创 从汇编层看64位程序运行——栈帧(Stack Frame)的组成

foo10函数的栈帧起始地址就是代码执行到+120处(+118行执行完,但是+120行没执行)时的rsp寄存器的值。这就意味着call指令压栈的Next RIP也属于子函数的栈帧,而通过栈向子函数传递参数的空间则属于上一个栈帧。比如在调用超过6个参数的函数时,子函数内部就会访问到上个栈帧中的数据,以获取第6个以外的其他参数。人们只是借用它来方便表述函数在运行过程中的栈的变化。之前+105,+109,+113和+117处的压栈空间,都是属于main函数的栈帧。这四篇的讲解,栈帧的组成基本清晰了。

2024-07-16 00:15:00 334

原创 从汇编层看64位程序运行——函数的调用和栈平衡

不知道有没有人想过一个问题:A函数调用B函数,B函数是如何知道在调用结束后回到A函数中的?比如下面的代码,main函数调用foo。当foo执行完毕,需要执行main函数的return 0语句。但是main和foo是割裂的,foo是怎么回到main函数中继续执行的呢?我们对上述代码进行反汇编。在main函数中,我们没有看到任何蛛丝马迹,只看到call指令。上图显示,当前代码执行到+8处(但是此行并没有执行,它的上一行执行了)。

2024-07-15 00:30:00 1311

原创 从汇编层看64位程序运行——栈上变量的rbp表达

如果发生了诸如0x00005555555553bb处的压栈行为,变量a的表达就要变成+0x10(%rsp),这对于汇编的阅读和编写会造成很大的麻烦。这样诸如-0x28(%rbp)表达变量a的方式,也可以通过+0x08(%rsp)的形式来表达。这是编译器让rsp的进行改变的,表达这个函数需要0x30的栈上空间存储局部变量(a,b,c,d,e,f,g,h,i,j)。我们让所有的变量初始化完成,然后再查看栈上变量的变化,可以看到栈上数值已经发生了改变。我们将所有的参数都压栈,然后观察rsp和rbp的变化。

2024-07-15 00:15:00 997

原创 从汇编层看64位程序运行——参数传递的底层实现

一个参数时直接使用edi寄存器传递参数。两个参数时,参数分别通过edi、esi寄存器传递。三个参数时,参数分别通过edi、esi和edx寄存器传递。四个参数时,参数分别通过edi、esi、edx和ecx寄存器传递。五个参数时,参数分别通过edi、esi、edx、ecx和r8d寄存器传递。六个参数时,参数分别通过edi、esi、edx、ecx、r8d和r9d寄存器传递。参数不超过6个时,参数按需使用edi、esi、edx、ecx、r8d和r9d寄存器传递到子函数。

2024-07-13 00:30:00 2065

原创 从汇编层看64位程序运行——栈帧(Stack Frame)边界

在中,我们简单介绍了栈帧的概念,以及它和函数调用之间的关系。如文中所述,栈帧是一种虚拟的概念,它表达了一个执行中的函数的栈空间区域。在这个区域中,该函数的局部非静态变量便被置于这个空间中,即我们常常说起的栈上变量。那么这个区间是通过什么划分的?这就需要引入寄存器这个概念。寄存器(Register)是中央处理器内用来暂存指令、数据和地址的存储器。寄存器的存贮容量有限,读写速度非常快。在计算机体系结构里,寄存器存储在已知时间点所作计算的中间结果,通过快速地访问数据来加速计算机程序的执行。需要注意的是,

2024-07-13 00:15:00 909

原创 从汇编层看64位程序运行——栈帧(Stack Frame)入门

然后我们给main函数下断点,让其断在main的起始代码处。此时foo函数没有被调用,于是只有main函数的栈帧——即只有一个栈帧。一个函数所有的局部变量以及一些辅助信息,构成了这个函数的栈帧。一文中,我们讲解了X86体系架构下,程序的栈结构的特点。栈帧是栈上一个抽象的结构,即栈上一个起始地址和截止地址中间的一段内存块。然后给foo函数下断点,让程序运行到这个函数的入口处,然后查看栈帧的变化。可以看到此时有两个栈帧,因为main函数和foo函数都在运行态。此时我们看到,栈帧又变成1个。

2024-07-12 01:15:00 434

原创 从汇编层看64位程序运行——程序中的栈(Stack)结构及其产生的历史原因

如果要讲程序在系统层的运行,一个绕不开的名词就是“栈”。所以深入理解“栈”是这个系列重要的基础。本文也将深入浅出,只讲明白程序运行中使用的栈是什么。

2024-07-12 01:00:00 1202

原创 从汇编层看64位程序运行——静态分析和动态分析入门

本文我们只是做一个简单的介绍,后续我们将使用这些工具以及其他更多的工具,来深入分析软件在系统上运行的情况,以期展现出计算机微观世界的精彩设计。

2024-07-11 20:46:48 982

原创 Java版Flink使用指南——背压

通过这个无界数据流,我们可以持续给系统提供数据,进而方便我们测试。这块代码见《Java版Flink使用指南——自定义无界流生成器》。

2024-07-11 20:46:18 715

原创 Java版Flink使用指南——合流

在中,我们通过addSink进行了输出分流。本文我们将介绍几种通过多个无界流输入合并成一个流来进行处理的方案。

2024-07-10 00:45:00 1235

原创 Java版Flink使用指南——分流导出

新建src/main/java/org/example/generator/UnBoundedStreamGenerator.java这块的代码可以见《Java版Flink使用指南——自定义无界流生成器》它会每隔1秒钟生成一个递增的数字import org} }} }} }} }} }} }@Override@Override。

2024-07-10 00:30:00 465

原创 Java版Flink使用指南——定制RabbitMQ数据源的序列化器

在一文中,我们从RabbitMQ队列中读取了字符串型数据。如果我们希望读取的数据被自动化转换为一个对象,则需要定制序列化器。本文我们就将讲解数据源序列化器的定制方法。

2024-07-09 00:30:00 830 2

原创 Java版Flink使用指南——定制RabbitMQ的Sink序列化器

我们定义的序列化器SampleDataRabbitMQSerializer 需要实现SerializationSchema接口,主要是实现serialize方法,将SampleData对象转换成二进制数组。

2024-07-09 00:15:00 1045

原创 Java版Flink使用指南——自定义无界流生成器

新建src/main/java/org/example/generator/UnBoundedStreamGenerator.java然后UnBoundedStreamGenerator实现RichSourceFunction接口主要实现SourceFunction接口的run和cancel方法。run方法用来获取获取,cancel方法用于终止任务。

2024-07-08 00:30:00 893

原创 Java版Flink使用指南——将消息写入到RabbitMQ的队列中

在一文中,我们介绍了如何使用Java在Flink中读取RabbitMQ中的数据,并将其写入日志中。本文将通过代码产生一些数据,然后将它们写入到另外一个RabbitMQ队列中。

2024-07-08 00:15:00 574

原创 Java版Flink使用指南——从RabbitMQ中队列中接入消息流

在一文中,我们完成了第一个小型Demo的编写。例子中的数据是代码预先指定的。而现实中,数据往往来源于外部。本文我们将尝试Flink从RabbitMQ中读取数据,然后输出到日志中。关于RabbitMQ的知识可以参阅。

2024-07-03 00:30:00 1305

原创 Java版Flink使用指南——安装Flink和使用IntelliJ制作任务包

在专题中,我们熟悉了Flink的相关知识以及Python编码方案。这个系列我们将使用相对主流的Java语言,来实践Flink的相关设计。

2024-07-03 00:15:00 820

原创 Websocket在Java中的实践——使用STOMP和RabbitMQ搭建聊天室

在一文中,我们让Spring的Broker作为客户端的代理,订阅了RabbitMQ的队列。本文,我们将基于这篇文章的部分内容,搭建一个简单的多人聊天室功能。

2024-07-02 00:30:00 1127

LuaCmdTest

我用于测试的一个lua脚本,没啥用,不用下载。

2012-11-27

同步双工管道

http://blog.csdn.net/breaksoftware/article/details/7001672文中的工程

2011-11-24

空空如也

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

TA关注的人

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