抛砖 ---- 在Alpine容器中安装glibc 的方法

字数 2441阅读 1240评论 0赞 0

静态链接和动态链接

熟悉 C/C++ 语言的人对于静态链接和动态链接一定不会陌生,相信很多人也曾经被静态链接和动态链接折磨过,那种滋味不好受,呵呵。

大体上可以认为,静态链接和动态链接以可执行程序和其所依赖的函数库的关系来划分。

如果函数库的一份拷贝是可执行文件的物理组成部分,称之为静态链接。

如果可执行文件只是包含了文件名,让载入器在运行时能够寻找程序所需要的函数库,称之为动态链接。

Linux 上静态链接库对应的后缀名为”.a”,动态链接库对应的后缀名为”.so”。

静态链接

静态链接当链接程序时,需要使用的每个库函数的一份拷贝被加入到可执行文件中。静态链接使用静态库进行链接,生成的程序包含程序运行所需要的全部库,可以直接运行,不过静态链接生成的程序体积较大(即使是在静态链接中,整个库文件也并没有全部装入到可执行文件中,所装入的只是需要的函数)。

生成静态链接的可执行程序流程大致如下图所示。

而生成后的可执行文件的空间分配大致如下图所示。

动态链接

动态链接允许系统提供一个庞大的函数库集合,可以提供许多有用的服务,程序在运行时寻找它们。动态链接使用动态链接库进行链接,生成的程序在执行的时候需要加载所需的动态库才能运行。动态链接生成的程序体积较小,但是必须依赖所需的动态库,否则无法执行。

生成动态链接的可执行程序的流程大致如下图所示。

动态链接的可执行程序的空间分配大致如下图所示。

静态链接优点和缺点

静态链接 :不同的程序开发者和部门能够相对独立地开发和测试自己的程序模块,大大促进了程序开发效率。

优点:

1、代码装载速度快,执行速度略比动态链接库快;

2、只需保证在开发者的计算机中有正确的.LIB文件,在以二进制形式发布程序时不需考虑在用户的计算机上.LIB文件是否存在及版本问题。

缺点:

1、浪费内存和磁盘空间、模块更新困难;

2、会给对程序的更新、部署和发布带来很多麻烦。

动态链接优点和缺点

优点:

1、解决了共享目标文件多个副本浪费磁盘和内存空间的问题;

2、使开发过程中各个模块 更加独立,耦合度变小,便于不同的开发者和开发组织之间独立进行开发和测试。

3、在内存中共享一个模块:节省内存,还可减少物理页面的换入换出,也可增加CPU缓存的命中率,因为不同进程间的数据和指令访问都集中在了同一个共享模块上。

4、加强程序的兼容性,一个程序在不同平台运行时可以动态地链接到由操作系统提供的动态链接库。

缺点:

如果使用载入时动态链接,程序启动时发现DLL不存在,系统将终止程序并给出错误信息。而使用运行时动态链接,系统不会终止,但由于DLL中的导出函数不可用,程序会加载失败;速度比静态链接慢。当某个模块更新后,如果新模块与旧的模块不兼容,那么那些需要该模块才能运行的软件,则会出现错误。

Glibc 和 Musl

Glibc = GNU C Library 是GNU项目(GNU Project),所实现的 C语言标准库(C standard library)。Glibc库基本都是以动态链接的形式,最常见的就是各种 .so 文件。 目前, 常见的桌面和服务器中的GNU/Linux类的系统中,例如 Redhat / CentOS / Debian / Ubuntu / Suse 等都是用的这套C语言标准库。 其实现了常见的C库的函数,支持很多种系统平台,功能很全,但是也相对比较臃肿和庞大。

Musl是从零开始设计的。一是希望让静态链接更高效;二是现有的C标准库在一些极端条件下表现很糟糕,竞态条件、资源不足时常常会出问题,而Musl试图避免它们来达到较高的实时鲁棒性。Musl 库设计的一个重要目标就是完美的支持静态链接。对静态链接的支持也让可移植单文件应用部署成为可能,而且不会使文件体积膨胀很多。有些Linux发行版使用Musl作为标准C库,例如Alpine Linux。对于链接到glibc的二进制程序,gcompat能让它们在基于Musl的发行版上运行。

Alpine中安装 glibc

虽然Glibc 和 Musl 库的设计目标非常清楚,但是实际使用中,偶尔也会遇到必须在Musl 库的环境中运行基于Glibc 的可执行程序。Alpine Linux 应该是目前最常遇到的使用 Musl 库的Linux发行版,尤其在容器的世界中,Alpine Linux 作为容器的基础镜像系统,使用很广泛。

当然,可以使用 gcompat 作为在Alpine Linux 中 Glibc 的替代库,但是 gcompat 和 glibc的兼容性并没有达到百分百,另外,在一些CPU架构上,例如 ppc64le 上, gcompat 并没有很好的实现和测试。

最近在移植 Mesos sphere 到 ppc64le 的过程中,就遇到了这样的问题,需要在 Alpine Linux 容器中安装 glibc 2.32 。

开始直接尝试在 Alpine 3.11 容器中编译 glibc 2.32 的源码,但是 Alpine 自带的 gcc 编译器不支持IBM定义的一种数据格式 long-double-128 ,所以行不通。

最终的解决方法,是首先在 Redhat 中编译出 glibc 2.32 的 .so 文件,然后再通过 Alpine 提供的包制作工具 ,参考 https://github.com/sgerrand/alpine-pkg-glibc
提供的 APKBUILD 文件,来制作成 apk 包。

由于Alpine的限制,在 apk 包安装过程中,是不允许安装路径中出现例如 lib64 这种文件夹的,所以需要在安装成功后,手动创建 lib64 相关目录,再把相关 .so 文件,拷贝到 lib64 目录下。

如果在x86上,可以直接下载安装 https://github.com/sgerrand/alpine-pkg-glibc

如果觉得我的文章对您有用,请点赞。您的支持将鼓励我继续创作!

0

添加新评论0 条评论

Ctrl+Enter 发表