Linux中的算法分离手段

2023-05-16

0. 简介

参数分离对于绝大多数算法开发来说收益是非常大的,因为我们都知道,随着平台的更替,很多时候如果说数据流和算法交叠在一起(即接口与实现合在一起)。这将有可能会导致在迁移平台时候会导致代码难以维护,并有可能会造成莫名的Bug。为了使代码更易于维护和扩展,在修改通信接口时不需要修改相关的算法代码,本文的下面将会介绍几种常用的方法。

1. 通过动态链接库完成链接

动态链接库(Dynamic Link Library,简称DLL)是一种在操作系统中用于共享代码和数据的机制。它是一种可执行的二进制文件,可以被多个程序同时使用,以提高代码的重用性和模块化程度。在C++算法分离中,动态链接库可以用于将算法代码从应用程序中分离出来,使得算法可以独立开发、测试和优化,同时也方便应用程序的调用和升级。

使用动态链接库可以使得算法代码和应用程序代码分别编译和链接,从而实现分离。这样一来,算法代码的修改和升级不会对应用程序造成影响,而应用程序也不必重新编译和链接。动态链接库还可以提高代码的重用性和可维护性,因为同一份动态链接库可以被多个应用程序使用,而且如果需要更新动态链接库,只需替换原文件即可。

对于动态链接库来说,主要分成两步。首先,需要在算法代码中明确定义导出函数(Export Function),以供应用程序调用。

比如说我们会创建一个函数my_pack_test.cpp

#include <stdio.h>
void foobar(int i)
{
  printf("Printing from my_pack_test.so %d\n", i);
}

CMakeList.txt

# include_directories( 这个括号里添加此项目依赖的头文件路径 )
 include_directories(../include)
add_library(my_pack_test 
# SHARED 字段指定testJni为动态链接库
SHARED 
# my_pack_test,为testJni库的cpp文件(生成testJni所需要的cpp都写到此处)
my_pack_test.cpp
)
# libgadl.so 为该testJni库需要链接的so库
target_link_libraries(testJni /home/lib/libgdal.so)
install(TARGETS my_pack_test LIBRARY DESTINATION lib)

这样我们就可以生成一个.so文件了。然后我们就需要在应用程序中使用动态链接库的导入函数(Import Function),以便在程序运行时动态加载动态链接库,并调用其中的算法函数。最后,需要将动态链接库文件放置在应用程序能够搜索到的路径下,以便程序能够找到它。

#include <iostream>
#include "mytool.h" // include the lib header

// include shared lib load
#ifdef _WIN32
#include <windows.h>
#else
#include <dlfcn.h> # in linux, should also link to dl system library when build
#endif

// define shared lib load handler
typedef MyTool *(*CreateMyToolFunc)();

#ifdef _WIN32
HINSTANCE gDllHandler = nullptr;
const char *gDefaultSharedLibPath = "mytool.dll"; // here put it the same path
#else
void *gSoHandler = nullptr;
// 为上面生成的.so文件的绝对路径
const char *gDefaultSharedLibPath = "libmytool.so"; // here put it the same path, some linux must use ./libmytool.so
#endif

int main()
{

#ifdef _WIN32
	// load shared lib
	gDllHandler = LoadLibrary(gDefaultSharedLibPath);
	if (!gDllHandler)
		std::cout << "load shared lib failed" << std::endl;

	CreateMyToolFunc create_mytool = (CreateMyToolFunc)(GetProcAddress(gDllHandler, "CreateMyTool"));
	MyTool *my_tool = create_mytool(); // get the derived class instance from shared lib

	my_tool->fun1();
	int z = my_tool->fun2(2, 3);
	printf("z: %d", z);

	// when all done, unload shared lib
	FreeLibrary(gDllHandler);
	gDllHandler = nullptr;
#else
    // 加载指定的 .so 文件
	gSoHandler = dlopen(gDefaultSharedLibPath, RTLD_LAZY);
	if (!gSoHandler)
		std::cout << "load shared lib failed" << std::endl;

	CreateMyToolFunc create_mytool = (CreateMyToolFunc)(dlsym(gSoHandler, "CreateMyTool"));
    // 查找函数create_mytool,并返回函数指针
	MyTool *my_tool = create_mytool(); // get the derived class instance from shared lib
	// 调用对应的foobar函数打印输出
	my_tool->fun1();
	int z = my_tool->fun2(2, 3);
	printf("z: %d", z);

	// when all done, unload shared lib
	dlclose(gSoHandler);
	gSoHandler = nullptr;
#endif

	return 0;
}

dlopen:该函数将打开一个新库,并把它装入内存。该函数主要用来加载库中的符号,这些符号在编译的时候是不知道的。这种机制使得在系统中添加或者删除一个模块时,都不需要重新进行编译。
dlsym:在打开的动态库中查找符号的值。
dlclose:关闭动态库。
dlerror:返回一个描述最后一次调用dlopen、dlsym,或dlclose的错误信息的字符串。

2. 通过进程完成链接

2.1 fork()完成子进程和父进程的操作

pid_t fork(void);

0: 子进程
子进程PID(大于0的整数):父进程
-1: 出错

使用fork函数得到的子进程从父进程的继承了整个进程的地址空间,包括:
进程上下文、进程堆栈、内存信息、打开的文件描述符、信号控制设置、进程优先级、进程组号、当前工作目录、根目录、资源限制、控制终端等。
子进程与父进程的区别在于:
1、父进程设置的锁,子进程不继承(因为如果是排它锁,被继承的话,矛盾了)
2、各自的进程ID和父进程ID不同
3、子进程的未决告警被清除;
4、子进程的未决信号集设置为空集

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int glob = 6;
int main()
{
    int local;
    int pid;

    local = 88; 
    
    printf("parent[pid = %d]: before fork, glob(&glob) = %d(%p), local(&local) = %d(%p)\n",
        getpid(), glob, &glob, local, &local );
    
    if((pid = fork()) < 0) {
        perror("fail to fork");
        return -1; 
    }   
    
    if(pid == 0) { /* child process */
        printf("child[pid = %d]: after fork, glob(&glob) = %d(%p), local(&local) = %d(%p)\n",
            getpid(), glob, &glob, local, &local );
        glob++;
        local++;    
        printf("child[pid = %d]: changed data after fork, glob(&glob) = %d(%p), local(&local) = %d(%p)\n",
            getpid(), glob, &glob, local, &local );
    }else { /* parent process */
        sleep(2);
        printf("parent[pid = %d]: after fork, glob(&glob) = %d(%p), local(&local) = %d(%p)\n",
            getpid(), glob, &glob, local, &local );
    }   
    /* return euqal to exit(0), but exit may cause a compile warning
     * due to main() is declared to return with an integter 
     */
    
    return 0;  
}

在这里插入图片描述

2.2 exec函数族

…详情请参照古月居

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Linux中的算法分离手段 的相关文章

  • 尝试 SSH 时设备的 ioctl 不合适

    我正在尝试通过 SSH 连接几台服务器并尝试获取sudo l每个服务器的输出 下面是我正在执行的脚本 bin bash serverlist tmp servers while IFS read r server netgroup user
  • libusb 和轮询/选择

    我正在使用 Linux 操作系统 想知道是否有任何文件描述符可以轮询 选择 当数据等待从 USB 设备读取时会触发这些文件描述符 我也在使用 libusb 库 但尚未找到可以使用的文件描述符 Use libusb 的轮询函数 http li
  • :: 右侧的非法标记

    我有以下模板声明 template
  • 命令行参数中的“-”(破折号)有什么魔力?

    例子 创建 ISO 映像并将其直接刻录到 CD mkisofs V Photos r home vivek photos cdrecord v dev dev dvdrw 更改到上一个目录 cd 侦听端口 12345 并解压发送到该端口的数
  • 类似 wget 的 BitTorrent 客户端或库? [关闭]

    这个问题不太可能对任何未来的访客有帮助 它只与一个较小的地理区域 一个特定的时间点或一个非常狭窄的情况相关 通常不适用于全世界的互联网受众 为了帮助使这个问题更广泛地适用 访问帮助中心 help reopen questions 是否有任何
  • Linux shell 命令逐块读取/打印文件

    是否有一个标准的 Linux 命令可以用来逐块读取文件 例如 我有一个大小为 6kB 的文件 我想读取 打印第一个 1kB 然后是第二个 1kB 看来猫 头 尾在这种情况下不起作用 非常感谢 你可以这样做read n在循环中 while r
  • 如何查找或计算Linux进程的页表大小和其他内核占用?

    我怎样才能知道 Linux 进程页表有多大 以及任何其他可变大小的进程统计 如果您真的对页表感兴趣 请执行以下操作 cat proc meminfo grep PageTables PageTables 24496 kB
  • bash双括号问题

    我对 bash 脚本非常陌生 在使用双括号时遇到了问题 我似乎无法让它们在 Ubuntu Server 11 10 中工作 我的下面的脚本位于 if test sh 中 bin bash if 14 14 then echo FOO fi
  • 在64位操作系统上以32位模式和64位模式编译ioctl函数的执行有什么不同?

    我有 64 位 Enterprise SuSE 11 我有一个应用程序 它打开 HIDRAW 设备并在其上操作 ioctl 函数以从该设备获取原始信息 如下所示 struct hidraw devinfo devinfo int fd op
  • 在键盘热插拔上加载模块

    我正在尝试学习如何为 Linux 系统编写模块和驱动程序 类似于this https unix stackexchange com questions 120839 usb kernel module does not load on de
  • Mono 和 WebRequest 速度 - 测试

    在 mono 4 6 2 linux 中 我注意到 wget 下载文件的速度与webclient DownloadString 所以我做了一个小测试来调查 为什么 wget 明显比 C 快 根据我自己的实验 使用 wget 下载 手动读取文
  • 是否可以找到哪个用户位于 localhost TCP 连接的另一端?

    这是一个编程问题 但它是 Linux Unix 特定的 如果我从本地主机获得 TCP 连接 是否有一种简单的方法可以告诉哪个用户在 C 程序内建立了连接而无需 shell 我知道这对于 Unix 域套接字来说并不太难 我已经知道远程 IP
  • 使用 C++ 输出字符串覆盖 Linux 终端上的最后一个字符串

    假设我有一个命令行程序 有没有办法让我说的时候 std cout lt lt stuff 如果我不做std cout lt lt n 在另一个之间std cout lt lt stuff 东西的另一个输出将覆盖同一行上的最后一个东西 清理行
  • 我在哪里可以学习如何使 C++ 程序与操作系统 (Linux) 交互

    我是一个 C 初学者 我想创建与操作系统交互的小程序 使用 Kubuntu Linux 到目前为止 我还没有找到任何教程或手册来让 C 与操作系统交互 在 PHP 中 我可以使用命令 exec 或反引号运算符来启动通常在控制台中执行的命令
  • 使用netcat将unix套接字传输到tcp套接字

    我正在尝试使用以下命令将 unix 套接字公开为 tcp 套接字 nc lkv 44444 nc Uv var run docker sock 当我尝试访问时localhost 44444 containers json从浏览器中 它不会加
  • 退出 bash 脚本但保持进程运行

    我正在运行服务器 需要使用参数执行以下命令 这些脚本目前工作得很好 但问题是当我运行脚本时我无法返回到控制台 它在控制台中保持运行 如果我强行停止它 那么该过程也会停止 我想继续运行该进程并返回到控制台 bin sh php home st
  • 静态链接共享对象?或者损坏的文件?

    我有一个从专有来源获得的库 我正在尝试链接它 但出现以下错误 libxxx so 文件无法识别 文件格式无法识别 Collect2 ld 返回 1 退出状态 确实 ldd libxxx so statically linked 这究竟意味着
  • 使用脚本自动输入 SSH 密码

    我需要创建一个自动向 OpenSSH 输入密码的脚本ssh client 假设我需要通过 SSH 进入myname somehost用密码a1234b 我已经尝试过 bin myssh sh ssh myname somehost a123
  • 如何在 Linux x86_64 上模拟 iret

    我正在编写一个基于 Intel VT 的调试器 由于当 NMI Exiting 1 时 iret 指令在 vmx guest 中的性能发生了变化 所以我应该自己处理vmx主机中的NMI 否则 guest会出现nmi可重入错误 我查了英特尔手
  • Windows 与 Linux 文本文件读取

    问题是 我最近从 Windows 切换到 Ubuntu 我的一些用于分析数据文件的 python 脚本给了我错误 我不确定如何正确解决 我当前仪器的数据文件输出如下 Header 有关仪器等的各种信息 Data 状态 代码 温度 字段等 0

随机推荐

  • 阿里技术大牛最爱的“闲书”,你看过多少?

    在忙碌的写代码 修bug生活里 xff0c 你有多久没有闲下来 xff0c 读读 闲书 xff0c 取悦自己了呢 xff1f 正如梁文道所说 xff0c 读一些无用的书 xff0c 做一些无用的事 xff0c 花一些无用的时间 xff0c
  • blackbox_exporter 黑盒监测

    一 简介 blackbox exporter blackbox exporter是Prometheus 官方提供的 exporter 之一 xff0c 可以提供 http dns tcp icmp 的监控数据采集 xff0c blackbo
  • Python 与Django环境搭建

    系统 xff1a Windows 10 python环境搭建 1 python安装步骤 python包下载链接 xff1a https www python org downloads windows 下载版本 xff1a python 3
  • prometheus图

    Prometheus Server 框架图 xff0c 只要能提供对应的metrics接口 xff0c promehteus就能接入监控 xff0c prometheus会把抓取到的指标数据持久化到本地磁盘中 xff0c 跟其它数据库一样它
  • 经典文献阅读之--BEVDistill(BEV蒸馏)

    0 简介 之前作者前段时间在研究BEV的相关算法 xff0c 当时就觉得BEV算法好是好 xff0c 但是所需要的内存以及计算资源实在是太大了 xff0c 无法实时在真实场景中运行 我们知道多视图 xff08 multi view 三维目标
  • 经典文献阅读之--FastFlowNet(轻量光流估计)

    0 简介 密集的光流估计在许多机器人视觉任务中起着关键作用 随着深度学习的到来 xff0c 已经比传统方法以令人满意的精度预测了它 然而 xff0c 当前的网络经常占用大量参数并且需要沉重的计算成本 这些缺点阻碍了在功率或内存受限的移动设备
  • Matlab与ROS(1/2)---Message(三)

    0 简介 消息是ROS中交换数据的主要容器 主题和服务使用消息在节点之间传输数据 为了标识其数据结构 xff0c 每条消息都有一个消息类型 例如 xff0c 来自激光扫描仪的传感器数据通常以sensor msgs LaserScan类型的消
  • Matlab与ROS(1/2)---发布者和订阅者数据通信(四)

    0 简介 我们在前面一节介绍了Matlab与Message的通信 xff0c 而我们这一节主要来介绍发布者和订阅者在Matlab中的操作 这部分我们主要来看一下ROS1和ROS2中分别是如何使用Topic的 1 ROS1的消息订阅与发布 1
  • Matlab与ROS(1/2)---服务端和客户端数据通信(五)

    0 简介 在前几讲我们讲了Matlab中的Message以及Topic的相关知识 而ROS主要支持的通信机制还有服务这一类 服务通过允许请求以及响应的通信方式 xff0c 来给整个系统完成更紧密的耦合 服务客户端向服务服务器发送请求消息并等
  • Matlab与ROS---Action与Gazebo(六)

    0 简介 对于ROS1而言 xff0c 其在Matlab当中相较于ROS2还有一些比较高级的用法 xff0c 比如说我们接下来要说的Action和Gazebo仿真 1 ROS Action ROS的Action行为模式当中也存在有一个客户端
  • Matlab与ROS---TF坐标系(七)

    0 简介 我们上面讲了最基础的通信机制以及在Matlab中如何使用这些通信 xff0c 下面我们这一讲来主要介绍ROS当中最常用的TF坐标系在Matlab中的使用 tf是分布式的 xff0c 因此所有的坐标帧信息对ROS网络中的每个节点都是
  • OCR如何读取皱巴巴的文件?深度学习在文档图像形变矫正的应用详解

    阿里妹导读 xff1a OCR作为智能审核的重要环节 xff0c 其识别准确率影响着最终审核效果的好坏 xff0c 而来自扫描仪 智能手机的文档图像多存在卷曲 折叠 本文旨在利用深度学习算法对文档图像的形变进行矫正 xff0c 从而提高OC
  • 经典文献阅读之--VGICP(体素化的ICP匹配)

    0 简介 之前我们在以前的文章中介绍了很多有关于点云匹配相关的知识 xff0c 最近两年处理GICP这一大一统的ICP匹配方法以外 xff0c 还有一个工作对体素化和ICP这两者打起了心思 xff0c Voxelized GICP for
  • 经典文献阅读之--Orbeez-SLAM(单目稠密点云建图)

    0 简介 对于现在的VSLAM而言 xff0c 现在越来越多的工作开始聚焦于如何将深度学习结合到VSLAM当中 xff0c 而最近的这个工作就给出了一个比较合适的方法 Orbeez SLAM A Real time Monocular Vi
  • 经典文献阅读之--NORLAB-ICP(重力约束ICP)

    0 简介 最近几年IPC相关的文章也出了不少 xff0c 最近作者有看到了一篇比较有意思的ICP论文 Gravity constrained point cloud registration xff0c 这篇论文将传统的ICP考虑了重力因素
  • 常见的3d bounding box标注工具

    0 简介 对于3d bounding box而言 xff0c 近几年随着自动驾驶的火热 xff0c 其标注工具也日渐多了起来 xff0c 本篇文章不讲具体的算法 xff0c 这里主要聚焦于这些开源的3d bounding box标注工具 x
  • 经典文献阅读之--A Lifelong Learning Approach to Mobile Robot Navigation(终生学习轨迹导航)

    0 简介 终生学习作为近年来比较火的一种深度学习方式 xff0c 导航终身学习 LLfN 旨在解决标准导航问题的一种新变体 xff0c 在该问题中 xff0c 智能体在有限的内存预算下 xff0c 通过学习提高在线经验或跨环境的导航性能 而
  • 避免使用第三方工具完成电脑环境检测

    0 简介 在之前配置各种深度学习环境的时候经常需要先检测一下电脑的软硬件环境 xff0c 其实整个过程比较重复和固定 xff0c 所以我们是否有可能一键检测Python版本 PIP版本 Conda版本 CUDA版本 电脑系统 CPU核数 C
  • 经典文献阅读之--PCAccumulation(动态三维场景构建)

    0 简介 多波束激光雷达传感器 xff0c 常用于自动驾驶汽车和移动机器人 xff0c 获取三维范围扫描序列 xff08 帧 xff09 由于角度扫描分辨率有限和遮挡 xff0c 每帧只稀疏地覆盖场景 稀疏性限制了下游过程的性能 xff0c
  • Linux中的算法分离手段

    0 简介 参数分离对于绝大多数算法开发来说收益是非常大的 xff0c 因为我们都知道 xff0c 随着平台的更替 xff0c 很多时候如果说数据流和算法交叠在一起 xff08 即接口与实现合在一起 xff09 这将有可能会导致在迁移平台时候