一、什么是 glibc

glibc 是 gnu 发布的 libc 库,即 C 运行库。它是 linux 最底层的 api,它包括很多规范,例如 system V、ISO C、POSIX 等。其他很多的函数库,都依赖 glibc,在其基础上进行各种拓展,如 X 库等。

glibc 是一种按照 LGPL 许可协议发布的,自由的,公开源码的,方便下载的 C 编译程序,是 GNU/Linux 操作系统的一个重要的组成部分。GNU C 运行库,是一种 C 函数库,是程序运行时使用到的一些 API 集合,它们一般是已预先编译好,以二进制代码形式存在 Linux 系统中,GNU C 运行库通常作为 GNU C 编译程序的一个部分发布。

glibc 除了封装 linux 操作系统所提供的系统服务外,还有其他必要的功能性服务:

  1. string,字符串处理
  2. signal,信号处理
  3. dlfcn,管理共享库的动态加载
  4. direct,文件目录操作
  5. elf,共享库的动态加载器,即 interpreter
  6. iconv,不同字符集的编码转换
  7. inet,socket 接口的实现
  8. intl,国际化,即 gettext 的实现
  9. io
  10. linuxthreads
  11. locale,本地化
  12. login,虚拟终端设备的管理,以及系统的安全访问
  13. malloc,动态内存的分配与管理
  14. nis
  15. stdlib,其他基本功能

libc、glibc(eglibc) 、glib 的关系和 libstdc++

libc 和 glibc 都是 linux 下的 C 函数库。libc 是 Linux 下的 ANSI C 函数库glibc 是 Linux 下的 GNU C 函数库


ANSI C 函数库是基本的 C 语言函数库,包含了 C 语言最基本的库函数。包含的头文件都是很熟悉的、很常用的头文件,一共有 15 个部分:

  1. <ctype.h>:包含用来测试某个特征字符的函数的函数原型,以及用来转换大小写字母的函数原型;
  2. <errno.h>:定义用来报告错误条件的宏;
  3. <float.h>:包含系统的浮点数大小限制;
  4. <math.h>:包含数学库函数的函数原型;
  5. <stddef.h>:包含执行某些计算 C 所用的常见的函数定义;
  6. <stdio.h>:包含标准输入输出库函数的函数原型,以及他们所用的信息;
  7. <stdlib.h>:包含数字转换到文本,以及文本转换到数字的函数原型,还有内存分配、随机数字以及其他实用函数的函数原型;
  8. <string.h>:包含字符串处理函数的函数原型;
  9. <time.h>:包含时间和日期操作的函数原型和类型;
  10. <stdarg.h>:包含函数原型和宏,用于处理未知数和类型的函数的参数列表;
  11. <signal.h>:包含函数原型和宏,用于处理程序执行期间可能出现的各种条件;
  12. <setjmp.h>:包含可以绕过一般函数调用并返回序列的函数的原型,即非局部跳转;
  13. <locale.h>:包含函数原型和其他信息,使程序可以针对所运行的地区进行修改;
  14. <
  15. <assert.h>:包含宏和信息,用于进行诊断,帮助程序调试。

glibc 是 linux 下面 C 标准库的实现,即 GNU C Library。glibc 本身是 GNU 旗下的 C 标准库,后来逐渐成为了 Linux 的标准 C 库,而 Linux 下原来的标准 C 库 Linux libc 逐渐不再被维护。

Linux 下面的标准 C 库不仅仅只有这一个,例如 uclibc、klibc,以及上面的 Linux libc,但是 glibc 无疑是用的最多的。glibc 在 /lib 目录下的 .so 文件是 libc.so.6。

主流的 Debian、Ubuntu、RedHat、CentOS 等用的 C 标准库都默认是 glibc(或者是其变种)

例如:在 C 代码中直接使用 fopen 函数就能打开文件,这是因为其在调用了系统中的 sys_open 系统调用,而 fopen 就是通过 glibc 来完成中间的处理过程的。

拓展(eglibc)

eglibc 就是一种变种的 glibc 标准 C 库,这里的 e 是 Embedded 的意思。

eglibc 主要特性是为了更好的支持嵌入式架构,可以支持不同的 shell (包括嵌入式),但它是二进制兼容 glibc 的,就是说如果代码之前依赖 eglibc 库,那么换成 glibc 后也不需要重新编译。

ubuntu 系统用的就是 eglibc(而不是 glibc),可以用 ldd -version 或者在 (32位系统)/lib/i386-linux-gnu/libc.so.6 (64位系统)/lib/x86_64-linux-gnu/libc.so.6 看看,可以显示 eglibc/glibc 的版本信息。


glib 和 glibc 基本上没有太大的联系,都是 C 编程需要调用的库而已。

glib 是 GTK+ 库和 GNOME 的基础,可以在多个平台下使用,如 Linux、Unix、Windows 等。

glib 是 GTK+ 库的基础库它由基础类型、对核心应用的支持、实用功能、数据类型和对象系统五个部分组成,是一个综合用途的实用的轻量级 C 程序库。它提供 C 语言常用的数据结构的定义、相关的处理函数,有趣而使用的宏,可移植的封装和一些运行时机能(如事件循环、线程、动态调用、对象系统等的 API)。

GNOME 也是需要依靠 glib 库的,是图形化相关的库,不再此记述。


libstdc++ 和 glibc 有什么关系呢?

libstdc++ 与 gcc 是捆绑在一起的,也就是说安装了 gcc 的时候会把 libstdc++ 装上。那为什么 glibc 和 gcc 没有捆绑在一起?

相比 glibc,libstdc++ 虽然提供了 C++ 程序的标准库,它她并不与内核打交道。对于系统级别的事件,libstdc++ 首先是会与 glibc 交互,才能和内核通信,说白了 C++ 在 C 的基础上,libstdc++ 就需要在 glibc 的支持。

拓展(gcc、g++)

C 代码 .c 文件通过 gcc 首先转化为会变 .S 文件,之后汇编器 as 将 .S 文件转化为机械代码 .o 文件,生成的 .o 文件再与其他的 .o 文件,或者之前提到的 libc.so.6 库文件通过 ld 链接器链接在一块生成可执行文件。(在你编译代码使用 gcc 的时候,gcc 命令已经帮你把这些细节全部做好。)

那 g++ 呢?不要以为 gcc 只能编译 C 代码,g++ 只能编译 C++ 代码。

后缀为 .c 的,gcc 把它当做是 C 程序,而 g++ 会当做 C++ 程序;后缀为 .cpp 的文件,两者都会认为是 C++ 程序。虽然 C++ 是 C 的超集,但两者对语法的要求还是有些区别的。在编译阶段,g++ 会调用 gcc,对于 C++ 代码,两者是等价的,但是因为 gcc 命令不能自动与 C++ 程序使用的库联接,所以需要这样:gcc -lstdc++,所以在 Makefile 文件并没有手动加上 libstdc++ 库,一般就会提示错误,要求你安装 g++ 编译器了。

关于 /usr/lib64/libstdc++.so.6:version ‘GLIBCXX_3.4.21’ not found 的报错和如何升级 GCC 可以浏览另一篇文章:http://fsemouse.com/wordpress/2019/03/05/centos-7-%e5%ae%89%e8%a3%85%e5%8d%87%e7%ba%a7-gcc/

二、怎么查看系统的 GLIBC(可能会导致环境出错,看完再操)

解决”libc.so.6: version `GLIBC_2.24′ not found”问题

glibc 版本太低了,需要升级

一般 glibc 的 .so 文件是在 /lib64/libc.so,查看系统 glibc 库版本可使用如下命令:

检查 libc.so 的结构,可以发现其是用软链的,这也就提供了多版本 glibc 的可能,高版本的 glibc 需要在官网上下载源码进行编译:http://ftp.gnu.org/gnu/glibc/

编译安装完后,可以建立软链接到安装目录里生成的 /opt/libc-2.32/lib/libc-2.32.so,也可以复制 .so 文件到 /lib64 中,方便多版本软链切换。

注意:删除 libc.so.6 之后可能导致系统命令不可用的情况,可使用一下方法解决:

如果上述更新失败可使用如下命令还原: