百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术文章 > 正文

Linux 下高版本glibc库应用程序在低版本环境下运行方法

nanshan 2024-12-01 01:32 12 浏览 0 评论


整个Linux底层基于gcc 编译器编译C和C++程序构造的,因此 gcc 通用c类库是最基本,最重要的类库,称为glibc库.不仅一般的应用程序,各种操作系统的命令行工具也是基glibc的构建的.

在部署C/C++应用时,经常碰到这样问题,就是开发环境 的glibc版本较高,但是实际部署的运行环境 有的glibc,版本高,有的glibc版 本低,强行运行会显示如下提示,

./ResolverService: /lib/aarch64-linux-gnu/libc.so.6: version GLIBC_2.28' not found (required by /usr/lib/libQt5Network.so.5)

这就是因为运行环境 最高支持GLIBC 2.26,而程序是在2.31的环境 编译的,这是一个非常常见的问题.如何解决?


高成本解决方案


升级系统glibc库

最容易想到是升级系统glibc库,这危险性相当于自己给自己做心脏手术,基本做到一半,所有系统工具都无法工作,导致系统崩掉,只能重装系统,所以严重不推荐.

使用虚拟机环境

在服务端部署经常采用的办法,就是在操作系统之上再运行一层虚拟机,比如 Docker,KVM,在虚拟机运行是统一glibc库版 本,这个方法缺点就需要系统资源较多,安装成本比较高.在嵌入式Linux下并不适用.


低成本解决办法 -- 修改应用程序


解决的思路就是让应用程序 不去装载默认glibc的入口程序 ,一般固定是在/lib目录下,通常是名字是 ld-linux打头动态库文件.

转而让应用程序 去寻找用户自己安装的glibc目录下的装载程序.

这个方法只需在用gcc编译应用程序,链接选项就可以一次性解决所有动态库版本不符问题,而且哪怕你没有源码只有运行程序,也可以同样用patchelf这个工具 给应用程序 打补丁即可.代价非常低.

比如我一个QT应用程序 ,使用了几十个Qt 的so动态库,很多都 引用高版本的glibc函数,只需要在编译最终应用程序加一句就行.不需要重新编译Qt类库,是不是很方便?

步骤1:准备高版本的glibc

可以在安装高版本的环境直接把文件拷出来即可,比如我ARM64板上glibc 2.31需要如下库,其中 ld-linux-aarch64.so.1 就是入口可执行,假设我把这一些文件放在 /home/hxy/glibc-2.31 目录下.大体有如下文件

ld-2.31.so               libc.so.6           libpthread.so.0
ld-linux-aarch64.so.1    libdl-2.31.so       libresolv-2.31.so
libc-2.31.so             libdl.a             libresolv.a
libc.a                   libdl.so            libresolv.so
libc_nonshared.a         libdl.so.2          libresolv.so.2
libcrypt.a               libgcc_s.so.1       librt-2.31.so
libcrypto.so.1.1         libm-2.31.so        librt.a
libcryptsetup.so.12      libm.a              librt.so
libcryptsetup.so.12.5.0  libm.so             librt.so.1
libcrypt.so              libm.so.6           libstdc++.so.6
libcrypt.so.1            libpthread-2.31.so  libstdc++.so.6.0.28
libcrypt.so.1.1.0        libpthread.a
libc.so                  libpthread.so

找不到对应glibc动态库,可以这个开源项目下 https://github.com/matrix1001/glibc-all-in-one 取得自己的想要的版本编译一下.或者直接搜索相应的 deb安装包


步骤2: 编译时加入对另一版本glibc 的引用

需要增加两个gcc 的链接参数:

  1. 显式链接指定动态库加载器 -Wl,--dynamic-linker

显式链接是相对用 -L -l c 隐式链接而言, 隐式链接就是编译后的应用程序ELF可执行文件只保存链接库名字,不带路径,加径顺序按缺省规则来进行. 一般是 /lib --> ld.so.conf-->LD_LIBRARY_PATH 这样顺序进行.而使用--dynamic-linker表示这是带路径动态库加载器直接装入即可.

在我的例子是,这样就跳开了/lib下同名动态glibc入口的引用,直接引用我的目录名字

-Wl,--dynamic-linker=/home/hxy/glibc-2.31/ld-linux-aarch64.so.1


2.指定动态库的装载目录 -Wl,--rpath

相当其它未带路径so,优先从这个目录装入,这一句也很重要因为ld-linux-xxx.so动态库需要装入同目录下其它glibc的动态,因此必须设置这个目录,否则又去装入/lib的动态库导致运行失败

 -Wl,--rpath=/home/hxy/glibc-2.31/

以上两句是要同时放在一个链接语句当中,顺便提一下,如果你是Linux 下Qt 项目,只需在pro文件增加一句QMAKE_LFLAGS的定义即可在最终的编译语句达到这样效果

QMAKE_LFLAGS = -Wl,--dynamic-linker=/home/hxy/glibc-2.31/ld-linux-aarch64.so.1  \
                  -Wl,--rpath=/home/hxy/glibc-2.31/


编译好在目标主机上也建立一个/home/hxy/glibc-2.31 并放入动态库.即可运行

补充步骤2: 只有可执行文件 ,用patchelf 打补丁

当没有源码编译或者编译很麻烦的情况,可以直接对可执行elf文件打补丁加上上述两个参数,效果一样的 ,首先安装patchelf

sudo apt-get install patchelf


elf 的interpreter字段是指明动态加载器路径,修改这个字段的作用等同于 -Wl,--dynamic-linker

rpath字段就是对应-Wl,--rpath的内容,假设应用程序名叫ResolverService,补丁指令如下


patchelf --set-interpreter /home/firefly/glibc-2.31/ld-linux-aarch64.so.1

--set-rpath /home/firefly/glibc-2.31 ResolverService?


以上两种方法bluedrum即在RK3399的高版本环境运行成功,同时又能切换到RK3308低版 本下环境 运行.

相关推荐

0722-6.2.0-如何在RedHat7.2使用rpm安装CDH(无CM)

文档编写目的在前面的文档中,介绍了在有CM和无CM两种情况下使用rpm方式安装CDH5.10.0,本文档将介绍如何在无CM的情况下使用rpm方式安装CDH6.2.0,与之前安装C5进行对比。环境介绍:...

ARM64 平台基于 openEuler + iSula 环境部署 Kubernetes

为什么要在arm64平台上部署Kubernetes,而且还是鲲鹏920的架构。说来话长。。。此处省略5000字。介绍下系统信息;o架构:鲲鹏920(Kunpeng920)oOS:ope...

生产环境starrocks 3.1存算一体集群部署

集群规划FE:节点主要负责元数据管理、客户端连接管理、查询计划和查询调度。>3节点。BE:节点负责数据存储和SQL执行。>3节点。CN:无存储功能能的BE。环境准备CPU检查JDK...

在CentOS上添加swap虚拟内存并设置优先级

现如今很多云服务器都会自己配置好虚拟内存,当然也有很多没有配置虚拟内存的,虚拟内存可以让我们的低配服务器使用更多的内存,可以减少很多硬件成本,比如我们运行很多服务的时候,内存常常会满,当配置了虚拟内存...

国产深度(deepin)操作系统优化指南

1.升级内核随着deepin版本的更新,会自动升级系统内核,但是我们依旧可以通过命令行手动升级内核,以获取更好的性能和更多的硬件支持。具体操作:-添加PPAs使用以下命令添加PPAs:```...

postgresql-15.4 多节点主从(读写分离)

1、下载软件[root@TX-CN-PostgreSQL01-252software]#wgethttps://ftp.postgresql.org/pub/source/v15.4/postg...

Docker 容器 Java 服务内存与 GC 优化实施方案

一、设置Docker容器内存限制(生产环境建议)1.查看宿主机可用内存bashfree-h#示例输出(假设宿主机剩余16GB可用内存)#Mem:64G...

虚拟内存设置、解决linux内存不够问题

虚拟内存设置(解决linux内存不够情况)背景介绍  Memory指机器物理内存,读写速度低于CPU一个量级,但是高于磁盘不止一个量级。所以,程序和数据如果在内存的话,会有非常快的读写速度。但是,内存...

Elasticsearch性能调优(5):服务器配置选择

在选择elasticsearch服务器时,要尽可能地选择与当前业务量相匹配的服务器。如果服务器配置太低,则意味着需要更多的节点来满足需求,一个集群的节点太多时会增加集群管理的成本。如果服务器配置太高,...

Es如何落地

一、配置准备节点类型CPU内存硬盘网络机器数操作系统data节点16C64G2000G本地SSD所有es同一可用区3(ecs)Centos7master节点2C8G200G云SSD所有es同一可用区...

针对Linux内存管理知识学习总结

现在的服务器大部分都是运行在Linux上面的,所以,作为一个程序员有必要简单地了解一下系统是如何运行的。对于内存部分需要知道:地址映射内存管理的方式缺页异常先来看一些基本的知识,在进程看来,内存分为内...

MySQL进阶之性能优化

概述MySQL的性能优化,包括了服务器硬件优化、操作系统的优化、MySQL数据库配置优化、数据库表设计的优化、SQL语句优化等5个方面的优化。在进行优化之前,需要先掌握性能分析的思路和方法,找出问题,...

Linux Cgroups(Control Groups)原理

LinuxCgroups(ControlGroups)是内核提供的资源分配、限制和监控机制,通过层级化进程分组实现资源的精细化控制。以下从核心原理、操作示例和版本演进三方面详细分析:一、核心原理与...

linux 常用性能优化参数及理解

1.优化内核相关参数配置文件/etc/sysctl.conf配置方法直接将参数添加进文件每条一行.sysctl-a可以查看默认配置sysctl-p执行并检测是否有错误例如设置错了参数:[roo...

如何在 Linux 中使用 Sysctl 命令?

sysctl是一个用于配置和查询Linux内核参数的命令行工具。它通过与/proc/sys虚拟文件系统交互,允许用户在运行时动态修改内核参数。这些参数控制着系统的各种行为,包括网络设置、文件...

取消回复欢迎 发表评论: