自定义博客皮肤VIP专享

*博客头图:

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

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

博客底图:

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

栏目图:

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

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+

方亮的专栏

方亮的专栏

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

原创 谈代码注释

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

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

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

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

2024-07-22 00:30:00 640

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

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

2024-07-22 00:15:00 562

原创 Robot Operating System——深度分析对象序列化的实现

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

2024-07-21 00:30:00 870

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

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

2024-07-21 00:15:00 643

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

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

2024-07-20 00:30:00 613

原创 Robot Operating System——定时器

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

2024-07-20 00:15:00 303

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

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

2024-07-19 10:36:09 988

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

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

2024-07-19 10:35:19 303

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

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

2024-07-17 00:30:00 935

原创 从汇编层看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 1210

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

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

2024-07-16 00:30:00 983

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

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

2024-07-16 00:15:00 331

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

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

2024-07-15 00:30:00 1305

原创 从汇编层看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 992

原创 从汇编层看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 2047

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

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

2024-07-13 00:15:00 901

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

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

2024-07-12 01:15:00 423

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

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

2024-07-12 01:00:00 1191

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

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

2024-07-11 20:46:48 979

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

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

2024-07-11 20:46:18 706

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

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

2024-07-10 00:45:00 1230

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

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

2024-07-10 00:30:00 460

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

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

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

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

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

2024-07-09 00:15:00 1035

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

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

2024-07-08 00:30:00 876

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

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

2024-07-08 00:15:00 572

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

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

2024-07-03 00:30:00 1279

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

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

2024-07-03 00:15:00 799

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

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

2024-07-02 00:30:00 1124

原创 Websocket在Java中的实践——整合Rabbitmq和STOMP

在一文中,我们使用enableSimpleBroker启用一个内置的内存级消息代理。本文我们将使用Rabbitmq作为消息代理,这样我们的服务就可以变成分布式部署。

2024-07-02 00:15:00 2047

原创 Websocket在Java中的实践——STOMP通信的最小Demo

STOMP,即简单面向文本的消息协议,是一种为处理在消息中间件上传输的文本消息而设计的简单协议。它提供了一种类似于HTTP或SMTP的文本帧格式,允许客户端与消息中间件进行交互,如发布、订阅和处理消息。STOMP的设计初衷是提供一个简单、可互操作的协议,以便在多种不同的消息中间件产品之间实现通信。

2024-07-01 00:30:00 817

原创 Websocket在Java中的实践——SockJS连接服务端

SockJS 是一个为浏览器和服务器提供跨域通信的 JavaScript 库,它基于 WebSocket 协议进行实时双向通信。在 WebSocket 不支持的情况下,SockJS 会自动回退到其他通信技术,如长轮询等,以确保在任何浏览器中都能提供类似的体验。兼容性:SockJS 能够在各种浏览器和环境中工作,包括旧版本的 Internet Explorer。它会自动检测并选择最适合当前环境的通信方式。易用性:SockJS 提供了一个简洁的 API,使得在前端和后端进行实时通信变得非常容易。

2024-07-01 00:15:00 965

原创 Websocket在Java中的实践——自动注册端点

在中我们使用握手拦截器实现了路径解析的工作。这个过程略显复杂,因为路径解析这样比较底层的工作应该由框架来解决,而不应该交由开发者来做。本文介绍的自动注册端点的功能就可以很优雅的解决这个问题。

2024-06-27 00:30:00 455

原创 Websocket在Java中的实践——握手拦截器

在一文中,我们看到如何用最简单的方式实现Websocket通信。本文中,我们将介绍如何在握手前后进行干涉,以定制一些特殊需求。在的基础上,我们希望建立“用户”的概念,即不同用户有自己的用户名。用户只能收到别人发的消息,而不能收到自己的消息。这就要求我们服务可以处理ws://localhost:8080/websocket/{uid}这样的请求。而对于uid不存在或者不合法的场景,就要拒绝连接。

2024-06-27 00:15:00 750

原创 Websocket在Java中的实践——最小可行案例

WebSocket是一种先进的网络通信协议,它允许在单个TCP连接上进行全双工通信,即数据可以在同一时间双向流动。WebSocket由IETF标准化为RFC 6455,并且已被W3C定义为JavaScript API的标准,成为现代浏览器的重要特性之一。WebSocket的引入彻底改变了传统的Web应用交互模式。在WebSocket之前,Web应用通常使用HTTP协议进行通信,但由于HTTP是一个无状态的、请求-响应模式的协议,它无法满足实时、双向通信的需求。

2024-06-26 00:30:00 935

原创 RabbitMQ实践——Stream队列的使用方法

Stream队列保存了发布到其上所有未过期(时间或Size判断)的消息。消费者只可以读取该队列,但是不能让队列将已读消息删除。这样就可以保证相同配置的消费者可以读取到相同的消息。鉴于它保留了未过期消息,所以非常适合需要读取历史消息的场景。鉴于消费者不能让其删除已读消息,所以对于需要“扇出”大量相同消息的场景,可以使用一个Stream来替代Fanout交换器绑定多个相同消息队列的方案。这样即可以降低系统设计的复杂度,也会提升Rabbitmq服务效率。

2024-06-26 00:15:00 1609

原创 RabbitMQ实践——搭建多人聊天服务

在一文中,我们搭建了Tom和Jerry两人的聊天服务。在这个服务中,它们都向Fanout交换器发送消息。而Fanout会将消息路由到它们两各自监听的队列。这样它们就可以得到全部消息。如果是多人聊天,比如10个人聊天,按上述方案,需要Fanout交换器绑定10个队列。这就会使得结构变得非常复杂。这是因为Classic类型队列在消费者确认读取消息后,会将消息从队列中删除。这样就需要我们使用fanout向多个队列路由消息,以供不同消费者消费。

2024-06-25 00:30:00 1687

原创 RabbitMQ实践——搭建单人聊天服务

direct交换器以及其绑定规则fanout交换器自动删除的交换器自动删除的队列只有一个消费者的队列WebFlux响应式编程。

2024-06-25 00:15:00 861

原创 RabbitMQ实践——使用WebFlux响应式方式实时返回队列中消息

在之前的案例中,我们在管理后台收发消息都是通过短连接的形式。本文我们将探索对队列中消息的实时读取,并通过流式数据返回给客户端。webflux是反应式Web框架,客户端可以通过一个长连接和服务端相连,后续服务端可以通过该连接持续给客户端发送消息。可以达到:发送一次,多次接收的效果。

2024-06-24 00:30:00 686

LuaCmdTest

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

2012-11-27

同步双工管道

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

2011-11-24

空空如也

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

TA关注的人

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