转自:网络
什么是libc?
libc是C语言标准库(C standard library)的缩写,它是C语言程序开发中常用的库之一。libc提供了一系列的函数和常量,用于处理字符串、内存操作、输入输出、数学运算、日期时间等常见的编程任务。
C语言标准库包含了一些核心的头文件,如<stdio.h>、<stdlib.h>、<string.h>等,这些头文件定义了许多常用的函数和类型。通过包含这些头文件,开发者可以使用库中提供的函数来完成各种任务,而无需从头开始编写相关的代码。
libc的实现会因不同的操作系统和编译器而有所差异,但它们都遵循C语言标准,提供了一致的接口和功能。开发者可以在编写C语言程序时直接调用这些库函数,以提高开发效率并简化代码编写过程。
glibc、glib、libc之间的区别?
glibc、glib和libc是三个不同的库,它们在不同的上下文中有不同的含义和作用。下面是它们之间的区别:
glibc(GNU C库):glibc是GNU发布的C语言标准库,也被称为GNU libc。它是Linux系统中最基础的API之一,几乎所有的运行库都依赖于glibc。glibc不仅封装了Linux操作系统提供的系统服务,还提供了许多其他必要功能的实现,如字符串处理、内存管理、文件操作、网络通信、多线程支持等。glibc的实现遵循C语言标准,提供了一致的接口和功能,可以帮助开发者快速编写高效、可靠的程序。在Linux系统中,glibc扮演着非常重要的角色,是Linux系统运行的基石之一。
glib:glib是一个通用的C语言工具库,它是为了解决C语言中一些常见问题而设计的。glib提供了一些数据结构、线程支持、内存管理、字符串处理、文件操作等功能。它是一个跨平台的库,可以在不同的操作系统上使用。glib被广泛应用于GNOME桌面环境和许多其他开源项目中。
libc(ANSI C标准库):libc是C语言标准库(C standard library)的缩写,它是C语言程序开发中常用的库之一。libc提供了一系列的函数和常量,用于处理字符串、内存操作、输入输出、数学运算、日期时间等常见的编程任务。它是C语言程序的基础库,提供了许多常用的功能和接口。
总结来说,glibc是Linux系统中最底层的C语言标准库,提供了丰富的系统服务和功能实现;glib是一个通用的C语言工具库,提供了一些常见问题的解决方案;而libc是C语言标准库,提供了基础的函数和常量,用于处理常见的编程任务。
ANSI C和GNU C的区别
ANSI C和GNU C是两种不同的C语言标准和实现,它们之间的区别如下:
ANSI C:ANSI C是C语言的标准化版本,由美国国家标准协会(ANSI)于1989年发布。ANSI C标准规定了C语言的语法、语义和标准库,使得不同的编译器可以在不同的平台上生成相同的代码。ANSI C标准化了C语言,使得C语言成为一种通用的编程语言,被广泛应用于系统编程、嵌入式系统、网络编程等领域。
GNU C:GNU C是GNU项目发布的C语言编译器,也称为gcc。GNU C是ANSI C的扩展版本,它提供了一些ANSI C没有定义的语言特性和扩展库。GNU C编译器是一个跨平台的编译器,可以在不同的操作系统上使用,如Linux、Windows、Mac OS等。GNU C编译器是开源的,可以自由使用和修改。
例如新增语法
1.零长度和变量长度数组
2.case范围
3.语句表达式
4.typeof关键字
5.可变参数宏
...还有很多,自己查
下面是一些示例代码来演示GNU C的扩展特性:
1. 零长度和变量长度数组:
// 零长度数组
struct ZeroLengthArray {
int len;
int data[0]; // 零长度数组
};
// 变量长度数组
void variableLengthArray(int size) {
int array[size]; // 变量长度数组
}
2. case范围:
int number = 5;
switch (number) {
case 1 ... 5: // 使用范围匹配多个case标签
printf("Number is between 1 and 5\n");
break;
case 6:
printf("Number is 6\n");
break;
default:
printf("Number is not in the range\n");
break;
}
3. 语句表达式:
int result = ({
int a = 5;
int b = 10;
a + b; // 语句表达式,返回a + b的结果
});
printf("Result: %d\n", result);
4. typeof关键字:
int number = 10;
typeof(number) newNumber; // 使用typeof获取number的类型
newNumber = number + 5;
printf("New Number: %d\n", newNumber);
5. 可变参数宏:
#include <stdio.h>
#include <stdarg.h>
#define SUM(...) sum(__VA_ARGS__)
int sum(int count, ...) {
va_list args;
va_start(args, count);
int total = 0;
for (int i = 0; i < count; i++) {
total += va_arg(args, int);
}
va_end(args);
return total;
}
int main() {
int result = SUM(1, 2, 3, 4, 5);
printf("Sum: %d\n", result);
return 0;
}
这些示例代码展示了GNU C的扩展特性的用法。请注意,这些特性可能不被所有C编译器支持,因此在使用时请确保目标平台和编译器的兼容性。
libc.so.6的坑
接下来说一下我几年前遇到的一个坑
在移植CentOS 7.9到RK3399上,并使用RK提供的updateEngine进行OTA升级时,遇到了一些问题。
首先,编译生成的updateEngine工具在CentOS上无法运行,缺少libpng.so库。为了解决这个问题,尝试将libpng.so库拷贝到系统中,但是发现libc.so等库的版本太低。因此决定升级这些库。
下载了glibc的源码,并按照以下步骤进行编译:
1. 运行../configure
2. 运行make
3. 运行make install
如果出现错误,您通过搜索解决了这些问题
升级完成后,updateEngine可以正常使用。然而,在发布给测试进行测试,但是在过程中遇到了一些问题。例如,hwclock工具出现段错误,lspci工具重定向出错,以及lspci -vvv | grep命令失败并报错。此外,运行yum update导致系统崩溃,卸载软件时会意外卸载其他系统工具等。
然后发现旧版本的CentOS不存在这些问题,并且可以通过重新编译hwclock和lspci等工具来解决。然而,由于yum update会导致系统不稳定,最后决定还原回去,问题得到解决。
反思方案
针对updateEngine的问题,有三种解决方案:
1.使用CentOS的库来编译updateEngine,只要它不依赖于较高版本的libc特性。可以修改Makefile来实现这一点。
2.进行静态编译,即将updateEngine可执行文件所需的动态链接库部分提取出来,链接到可执行文件中,使其在运行时不依赖于动态链接库。同样,可以修改Makefile来实现静态编译。
3.修改配置文件去除updateEngine的UI界面所需的libpng库,因为并不需要它。
方案选择
最后选择了第三种方法
总结起来,CentOS之所以使用较旧的系统库,是为了保证稳定性,服务器OS首先centos。如果需要更新的话,可以考虑使用CentOS 8或更高版本,因为它们的系统库已经比较新了。请记住,更新系统存在一定的风险,需要谨慎操作。