【ARM 嵌入式 编译系列 3.2 -- glibc 学习】

文章目录

    • 1.1 GNU GLIBC 介绍
      • 1.1.1 GLIBC 与 POSIX
      • 1.1.2 GLIBC 常见接口
    • 1.2 lib文件常用命令
      • 1.2.1 lib 文件之 ar 命令
      • 1.2.2 lib 文件信息查看
      • 1.2.3 lib 文件生成及链接测试
      • 1.2.4 lib 文件冲突

上篇文章:ARM 嵌入式 编译系列 3.1 – GCC attribute((used)) 使用
下篇文章:ARM 嵌入式 编译系列 3.3 – gcc 动态库与静态库的链接方法介绍

1.1 GNU GLIBC 介绍

GLIBC,全名GNU C库,是GNU项目发布的一套C语言库。它定义了系统调用和基本运行时的C语言ABI(应用程序二进制接口),包括开放文件、分配内存、启动进程等函数。

glibc是Linux和许多其他操作系统的标准C库,它提供了许多重要的接口,如 POSIX 和 Single UNIX Specification等。并且它还实现了ISO C11、POSIX.1-2008和一些其他标准的许多可选扩展。

ISO C11是C语言的一个标准版本,它定义了语言的语法和语义,以及标准库的接口。这个标准只涉及到语言级别的特性,不涉及操作系统级别的特性

glibc除了包含常见的C库函数如printf、malloc 等之外,还包括一些Unix系统服务的封装,如线程、网络编程、进程管理、文件操作、动态链接等。

glibc是开源的,并且在GNU通用公共许可证(GPL)下发布。它是大部分Linux发行版的核心组件,也是GNU操作系统的一个重要部分。

1.1.1 GLIBC 与 POSIX

POSIX(Portable Operating System Interface)是一套定义了操作系统应该提供哪些接口给上层软件的标准,目的是尽可能地实现操作系统之间的兼容性。POSIX标准定义了一组系统调用、库函数和命令行工具,它包括了文件操作、进程管理、信号处理、线程、同步等许多方面。POSIX标准并没有指定任何特定的编程语言,但它的接口主要以C语言的形式给出,因此,POSIX和C语言有很紧密的联系。

glibc(GNU C Library)是一个实现了C标准库和POSIX标准的库。由于POSIX标准是操作系统接口的标准,因此,glibc中实现的许多函数其实就是对内核系统调用的封装。同时,glibc还提供了许多额外的特性和扩展,以支持更多的应用场景。

总的来说,glibc是POSIX标准在GNU/Linux系统中的一个主要实现,通过使用glibc,程序员可以编写出符合POSIX标准、具有良好移植性的程序。

GLIBC 官网(但是下载慢)
http://ftp.gnu.org/gnu/glibc/

(清华大学开源软件镜像站) 下载快
https://ftpmirror.gnu.org/libc/

1.1.2 GLIBC 常见接口

glibc 提供了许多常用的 C库函数,以下是其中的一些例子:

  • stdio.h:包含了基本的输入/输出函数,如printf、scanf、fopen、fclose等。
  • stdlib.h:包含了一些常用的通用功能,如malloc、free、exit、system等。
  • string.h:包含了字符串操作函数,如strcpy、strcmp、strcat、strlen等。
  • math.h:包含了数学函数,如pow、sqrt、sin、cos等。
  • time.h:包含了时间和日期函数,如time、clock、strftime等。
  • ctype.h:包含了字符操作函数,如isalpha、isdigit、tolower、toupper等。
  • errno.h:包含了错误码,如EINTR、ENOMEM、EINVAL等。
  • pthread.h:包含了线程相关的函数,如pthread_create、pthread_join等。
  • unistd.h:包含了对系统调用的封装,如read、write、fork、exec等。

以上只是 glibc 中的一小部分函数,实际上glibc提供了非常多的函数,涵盖了各种各样的功能。

1.2 lib文件常用命令

1.2.1 lib 文件之 ar 命令

ar -x 将库文件解压后可以删除某些.o文件,重新ar打包。
-d 从库中删除指定的文件
-t 将库的目录写至标准输出。如果指定文件名称

● 创建一个库

  ar -v -q lib.a  strlen.o strcpy.o

● 解压缩库成员

  ar -v -x lib.a strcat.o strcpy.o

● 删除一个成员

  ar -v -d lib.a strlen.o

1.2.2 lib 文件信息查看

● lib 运行架构大小端查看:

readelf.exe -A target.lib

nm POC.lib | grep “.o” 可以参看当前有哪些.c文件

● 将静态库 mbtk.a 的头信息重定向到arch_info.txt文件中中查看:

fromelf.exe -s mbtk.a > arch_info.txt

fromelf是ARM开发套件(如ARM Developer Suite,ADS)中的一个工具,主要用于处理ELF(可执行与可链接格式)文件。fromelf可以将ELF文件转换为其他格式,例如二进制(bin)格式或十六进制(hex)格式,这些格式的文件可以被程序员下载到目标硬件中。此外,fromelf还可以从ELF文件中提取各种信息,例如符号表、段和节的信息等。

例如,如果你有一个名为output.elf的ELF文件,你可以使用以下命令将其转换为二进制格式:

fromelf --bin -o output.bin output.elf

你也可以使用fromelf来查看ELF文件的符号表:

fromelf --symbols output.elf

注意,fromelf是ARM特有的工具,其他平台可能有类似的工具,例如在GNU工具链中,objcopy和objdump可以完成类似的任务。

● 用户也可以使用 nm 命令来查看lib文件信息
● 使用功 ldd 可以查看可执行文件使用了哪些库文件

1.2.3 lib 文件生成及链接测试

● work.c:

#include 

void DoThing(void)
{ 
	printf ("%s work \n", __func__); 
}

● main.c

#include 
void DoThing(void);

int main(void)
{
    printf("%s start \n", __func__);
    DoThing();
    printf("%s finished \n", __func__);
    return 0;
}

1)在当前目录生成两个 .o 文件

gcc -c main.c -o main.o
gcc -c work.c -o work.o

2)将两个.o文件生成 lib文件

ar rc libmain.a main.o
ar rc libwork.a work.o

3)链接两个lib文件生成可执行文件

gcc -s -L. -o main.exe -lmain -lwork  

-L .” 指定当前库文件目录, 默认使用静态库链接;
-l” 选项用于指定要链接的库。在链接阶段,“-l” 选项后面跟着的是库名,GCC会搜索库名来链接到你的程序。

完成上面三步之后生成的 main.exe 可以正常执行,如果直接编译 gcc main.c 是编译不过的,会报出函数DoThing 没定义。

如果使用 gcc -s -L. -o main.exe -lwork -lmain 进行链接,会报出 undefined symbol `DoThing,因为接器如果发现当前库中使用了没有被定义的符号,它只会向后查找。

1.2.4 lib 文件冲突

● work.c:

#include 

void DoThing(void)
{ 
	printf ("%s work \n", __func__); 
}

● main.c

#include 
void DoThing(void);

int main(void)
{
    printf("%s start \n", __func__);
    DoThing();
    printf("%s finished \n", __func__);
    return 0;
}

● conflict.c 中实现:

#include 

void DoThing(void) 
{ 
	printf("conflict \n"); 
}
gcc -c main.c -o main.o
gcc -c work.c -o work.o
gcc -c conflict.c -o conflict.o
ar rc libconflict.a conflict.o
gcc -s -L. -o main.exe -lmain -lwork -lconflict

按照上面步骤编译链接后也可以生成可执行文件main.exe并正常执行,需要注意的是这时 main.o中链接的是 work.c中定义的 DoThing 函数,并不是conflict.c中定义的函数。如果使用下面链接方式则正好相反:

gcc -s -L. -o main.exe -lmain -lconflict -lwork

上篇文章:ARM 嵌入式 编译系列 3.1 – GCC attribute((used)) 使用
下篇文章:ARM 嵌入式 编译系列 3.3 – gcc 动态库与静态库的链接方法介绍

你可能感兴趣的:(#,ARM,BSP,编译系列介绍,arm开发,gcc,-L,posix,GLIBC)