Robot Operating System——深度解析通过符号和隐式加载动态库的运行模式

news2024/11/13 18:08:49

大纲

  • 运行时分析
  • 依赖文件分析
  • 汇编和符号分析

除了《Robot Operating System——深度解析自动隐式加载动态库的运行模式》中介绍的这种最终在底层依赖了RCLCPP_COMPONENTS_REGISTER_NODE来注册Node工厂类对象之外,还存在一种特殊的方式,即本文介绍的:通过隐式加载Node的实现逻辑,但是在调用上直接通过符号来对接,而不是通过class_loader::ClassLoader这套流程。

我们先看下样例(composition/src/manual_composition.cpp)代码

// Copyright 2016 Open Source Robotics Foundation, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <memory>

#include "composition/client_component.hpp"
#include "composition/listener_component.hpp"
#include "composition/talker_component.hpp"
#include "composition/server_component.hpp"
#include "rclcpp/rclcpp.hpp"

int main(int argc, char * argv[])
{
  // Force flush of the stdout buffer.
  setvbuf(stdout, NULL, _IONBF, BUFSIZ);

  // Initialize any global resources needed by the middleware and the client library.
  // This will also parse command line arguments one day (as of Beta 1 they are not used).
  // You must call this before using any other part of the ROS system.
  // This should be called once per process.
  rclcpp::init(argc, argv);

  // Create an executor that will be responsible for execution of callbacks for a set of nodes.
  // With this version, all callbacks will be called from within this thread (the main one).
  rclcpp::executors::SingleThreadedExecutor exec;
  rclcpp::NodeOptions options;

  // Add some nodes to the executor which provide work for the executor during its "spin" function.
  // An example of available work is executing a subscription callback, or a timer callback.
  auto talker = std::make_shared<composition::Talker>(options);
  exec.add_node(talker);
  auto listener = std::make_shared<composition::Listener>(options);
  exec.add_node(listener);
  auto server = std::make_shared<composition::Server>(options);
  exec.add_node(server);
  auto client = std::make_shared<composition::Client>(options);
  exec.add_node(client);

  // spin will block until work comes in, execute work as it becomes available, and keep blocking.
  // It will only be interrupted by Ctrl-C.
  exec.spin();

  rclcpp::shutdown();

  return 0;
}

看似main所在的可执行文件将诸如composition::Talker这些Node的具体实现都编译进去了,实则它只是编译进去了符号,具体逻辑还是在动态库中。

我们看CMakeLists.txt的实现

add_executable(manual_composition
  src/manual_composition.cpp)
target_link_libraries(manual_composition
  talker_component
  listener_component
  server_component
  client_component)
ament_target_dependencies(manual_composition
  "rclcpp")

对于talker_component、listener_component、server_component和client_component,链接过程会按需链接(-Wl,–as-needed)。它们也会隐式自动加载到进程中。

运行时分析

我们可以通过工具来分析。

先执行manual_composition。

./build/composition/manual_composition

在这里插入图片描述
然后查看该进程ID

ps -ef | grep manual_composition

在这里插入图片描述
然后查看运行时它加载了的动态库

lsof -p 728814 | grep talker_component
lsof -p 728814 | grep listener_component
lsof -p 728814 | grep server_component
lsof -p 728814 | grep client_component

在这里插入图片描述

依赖文件分析

ldd ./composition/build/composition/manual_composition 

在这里插入图片描述

汇编和符号分析

我们反汇编manual_composition到manual_composition.txt

objdump -S ./composition/build/composition/manual_composition > manual_composition.txt

然后沿着main函数去寻找线索

000000000000e5a9 <main>:
    e5a9:	f3 0f 1e fa          	endbr64
    e5ad:	55                   	push   %rbp
    e5ae:	48 89 e5             	mov    %rsp,%rbp
    e5b1:	53                   	push   %rbx
……
    e733:	e8 6c 14 00 00       	call   fba4 <_ZSt11make_sharedIN11composition6TalkerEJRN6rclcpp11NodeOptionsEEESt10shared_ptrINSt9enable_ifIXntsrSt8is_arrayIT_E5valueES8_E4typeEEDpOT0_>
……

然后一直追踪下去,会陆续找到:

  • ZNSt10shared_ptrIN11composition6TalkerEEC1ISaIvEJRN6rclcpp11NodeOptionsEEEESt20_Sp_alloc_shared_tagIT_EDpOT0
  • ZNSt12__shared_ptrIN11composition6TalkerELN9__gnu_cxx12_Lock_policyE2EEC1ISaIvEJRN6rclcpp11NodeOptionsEEEESt20_Sp_alloc_shared_tagIT_EDpOT0
  • ZNSt14__shared_countILN9__gnu_cxx12_Lock_policyE2EEC1IN11composition6TalkerESaIvEJRN6rclcpp11NodeOptionsEEEERPT_St20_Sp_alloc_shared_tagIT0_EDpOT1
  • ZNSt23_Sp_counted_ptr_inplaceIN11composition6TalkerESaIvELN9__gnu_cxx12_Lock_policyE2EEC1IJRN6rclcpp11NodeOptionsEEEES2_DpOT
  • ZSt10_ConstructIN11composition6TalkerEJRN6rclcpp11NodeOptionsEEEvPT_DpOT0
  • _ZN11composition6TalkerC1ERKN6rclcpp11NodeOptionsE
000000000000e3b0 <_ZN11composition6TalkerC1ERKN6rclcpp11NodeOptionsE@plt>:
    e3b0:	f3 0f 1e fa          	endbr64
    e3b4:	ff 25 96 9b 00 00    	jmp    *0x9b96(%rip)        # 17f50 <_ZN11composition6TalkerC1ERKN6rclcpp11NodeOptionsE@Base>
    e3ba:	66 0f 1f 44 00 00    	nopw   0x0(%rax,%rax,1)

我们在manual_composition中是找不到_ZN11composition6TalkerC1ERKN6rclcpp11NodeOptionsE的实现的

nm ./composition/build/composition/manual_composition | grep _ZN11composition6TalkerC1ERKN6rclcpp11NodeOptionsE

在这里插入图片描述
可以看到处于U状态,即未定义。
但是我们在动态链接库libtalker_component.so中可以找到它的实现

nm ./composition/build/composition/libtalker_component.so | grep _ZN11composition6TalkerC1ERKN6rclcpp11NodeOptionsE

在这里插入图片描述
所以我们看到例子manual_composition 虽然也是使用动态链接库的隐式加载,但是它没有使用Node工厂类的注册逻辑,而是直接依赖于符号。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1996783.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

仿RabbiteMq简易消息队列基础篇(gtest的使用)

TOC gtest介绍 gtest是google的一个开源框架&#xff0c;它主要用于写单元测试&#xff0c;检查自己的程序是否符合预期行为。可在多个平台上使用&#xff08;包含Linux&#xff0c;MAC OC&#xff0c;Windows等&#xff09;。它提供了丰富的断言&#xff0c;致命和非致命失败…

Spring框架的三种配置方式(二)---xml文件+注解

Spring框架有三种配置方式&#xff1a; 1.在spring2.5以前&#xff0c;用xml文件进行配置 2.在spring2.5以后&#xff0c;用xml文件和注解(annotation)共同进行配置 3.在spring3.0以后&#xff0c;用注解(annotation)和JavaConfig配置类进行配置 一、xml文件 见下一篇 二…

联通数科如何基于Apache DolphinScheduler构建DataOps一体化能力平台

各位小伙伴晚上好&#xff0c;我是联通数字科技有限公司数据智能事业部的王兴杰。 今天&#xff0c;我将和大家聊一聊联通数字科技有限公司是如何基于Apache DolphinScheduler构建DataOps一体化能力平台的。 今天的分享主要分为三个部分&#xff1a; 关于DataOps的一些思考&a…

视觉SLAM第五讲

本讲将讨论“机器人如何观测外部世界”&#xff0c;也就是观测方程部分。而在以相机为主的视觉SLAM中&#xff0c;观测主要是指相机成像的过程。 三维世界中的一个物体反射或发出的光线&#xff0c;穿过相机光心后&#xff0c;投影在相机的成像平面上。相机的感光器件接收到光…

主机加固是什么?主机加固与产线工控安全关系

1. 需求背景 随着工业4.0的发展&#xff0c;生产线日益智能化&#xff0c;生产网已经发展成一个复杂的计算机环境。尽管这些网络通常进行了物理隔离&#xff0c;但在实际操作中仍需要与外部进行数据交互。这种交互可能导致病毒和恶意软件的入侵&#xff0c;威胁工控主机和产线…

k8s分布式存储-ceph

文章目录 Cephdeploy-ceph部署1.系统环境初始化1.1 修改主机名&#xff0c;DNS解析1.2 时间同步1.3 配置apt基础源与ceph源1.4关闭selinux与防火墙1.5 **创建** ceph **集群部署用户** cephadmin1.6分发密钥 2. ceph部署2.1 **安装** ceph 部署工具2.2 **初始化** mon **节点**…

计算机毕业设计选题推荐-小型民营加油站管理系统-Java/Python项目实战

✨作者主页&#xff1a;IT研究室✨ 个人简介&#xff1a;曾从事计算机专业培训教学&#xff0c;擅长Java、Python、微信小程序、Golang、安卓Android等项目实战。接项目定制开发、代码讲解、答辩教学、文档编写、降重等。 ☑文末获取源码☑ 精彩专栏推荐⬇⬇⬇ Java项目 Python…

使用 Java Swing 创建一个最大公约数计算器 GUI 应用

使用Java语言,设计一个程序,实现求取两个正整数的最大公约数。 比较基础的一个Java小程序。 1、效果展示 2、程序代码 package demo; import javax.swing.*; import java.awt.*;

用python连接mysql的方法

如何将个人主机上的mysql服务发布到公网&#xff1a;frp内网穿透 用python连接mysql的方法 方法一&#xff1a; 1.设置清华镜像站&#xff1a;从国内下载安装包&#xff0c;提高下载和安装速度 pip3 config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simp…

航向角、前轮转角、偏航角的区别及其在MPC中的使用

目录 前言一、概念解析二、三种角度在MPC中的应用三、总结四、MPC算法流程 前言 航向角、偏航角、前轮转角是车辆控制中描述方向的关键概念。本文将简要介绍它们的区别及在MPC&#xff08;模型预测控制&#xff09;中的应用。 一、概念解析 φ 为车体的航向角&#xff1b; δ…

[ACP云计算]组件介绍

一、IaaS、PaaS、SaaS 二、交换机 三、VPC 四、ECS 云服务器ECS&#xff08;Elastic Compute Service&#xff09;是阿里云提供的性能卓越、稳定可靠、弹性扩展的IaaS&#xff08;Infrastructure as a Service&#xff09;级别云计算服务。云服务器ECS免去了您采购IT硬件的前期…

jupyter项目使用Anaconda环境内核

1、创建虚拟环境 conda create --name myjupyter python3.7 2、进入虚拟环境 conda activate myjupyter 3、切换到自己jupyter notebook项目想在的目录 E: cd E:\first\project\jupyter\jupyter01 4、安装IPython内核包&#xff0c;这是Jupyter Notebook使用Python内核所必需的…

【MySQL 03】库的操作 (带思维导图)

前置&#xff1a;之后的所有的 SQL 语句中&#xff0c;凡是被中括号 [ ] 括起来的均为可选项。 &#x1f308; 一、创建数据库 数据库创建语句 创建数据库本质就是在 /var/lib/mysql 中创建一个目录。 if not exists&#xff1a;如果指定数据库不存在则创建该数据库&#xf…

[Java]面向对象-static继承

Static static表示静态&#xff0c;是Java中的一个修饰符&#xff0c;可以修饰成员方法、成员变量 静态变量&#xff1a; 被static修饰的成员变量&#xff0c;叫静态变量 特点&#xff1a; 被该类所有对象共享 调用方式&#xff1a;1.类名调用 2.对象名调用 静态方法&…

PyFluent入门之旅(8) PyFluent API 分类与区别

PyFluent提供了两种主要的API来与Ansys Fluent进行交互&#xff1a; Settings APITUI API 通过这两种接口方式&#xff0c;可以控制 Ansys Fluent 的各个方面&#xff0c;包括从网格生成到后处理的所有操作。 分类 Settings API pyFluent 的 Settings API类似于 Ansys Flu…

线性表——数据结构

线性表 文章目录 线性表线性表的定义和基本操作线性表的定义线性表的基本操作 线性表的顺序表示顺序表的定义顺序表的实现——静态分配顺序表的实现——动态分配顺序表的特点 线性表的定义和基本操作 线性表的定义 线性表&#xff08;Linear List&#xff09;的定义 ​ 线性…

略谈set与map的pair封装与进入哈希

引子&#xff1a;之前我们讲了红黑树的自实现&#xff0c;与小小的接口实现&#xff0c;那set与map的pair封装是如何实现的呢&#xff1f;&#xff0c;今天我们来一探究竟&#xff0c;而且我们也要进入新章节--哈希 对于operator--()的封装&#xff1a; 注意&#xff1a;牢记思…

动手学深度学习V2每日笔记(批量归一化、ResNet)

本文主要参考沐神的视频教程 https://www.bilibili.com/video/BV1Uv411G71b/spm_id_fromautoNext&vd_sourcec7bfc6ce0ea0cbe43aa288ba2713e56d https://cv.gluon.ai/model_zoo/classification.html 文档教程 https://zh-v2.d2l.ai/ 本文的主要内容对沐神提供的代码中个人不…

【OpenHarmony】openharmony移植到RK3568------搭建开发环境

一、关于OpenHarmony OpenHarmony是由开放原子开源基金会&#xff08;OpenAtom Foundation&#xff09;孵化及运营的开源项目&#xff0c;目标是面向全场景、全连接、全智能时代&#xff0c;基于开源的方式&#xff0c;搭建一个智能终端设备操作系统的框架和平台&#xff0c;促…

各种高端链游 区块链游戏 休闲小游戏DAPP开发

【西游闯关】-高端区块链3D手游 【我朝有马】-高端区块链3D手游 【弹弹岛2】-高端区块链3D手游