三、Linux库文件的查找与使用1. 静态库 a. 编译时链接 静态库(Static library)是在程序编译时被链接到目标程序中的一部分。在程序执行时,静态库的代码会被复制到执行文件中,因此,程序运行时不需要再次加载静态库,这也就意味着,静态库中的代码只会被编译一次,并在程序执行时占用固定的内存空间。 在Linux 系统中,静态库通常以 `.a` 结尾。在编译程序时,编译器会自动找到静态库并进行链接。例如,如果你有一个名为 `libmymath.a` 的静态库,其中包含数学函数的实现,那么在编译程序时,你可以使用如下命令: ``` gcc -o myprogram myprogram.c -lmymath ``` 这里,`-lmymath` 告诉链接器要链接到 `libmymath.a` 静态库。
b. 运行时加载 尽管静态库在程序编译时已经链接到目标程序中,但在某些情况下,你可能需要动态地链接静态库。这通常涉及到两个步骤:首先,你需要一个特殊的静态库版本,它包含了运行时链接所需的辅助函数;其次,你需要在程序运行时使用这个特殊的静态库。 在Linux 系统中,这个特殊的静态库通常以 `.la` 结尾。当你使用这个特殊的静态库时,你需要运行 `ldconfig` 命令来动态地链接静态库。例如,如果你有一个名为 `libmymath.la` 的特殊静态库,那么你可以使用如下命令来运行程序: ``` ldconfig -r /path/to/libmymath.la ./myprogram ``` 这里,`-r` 选项告诉 `ldconfig` 递归地搜索指定路径下的静态库。
2. 动态库 a. 编译时链接 动态库(Dynamic library)是在程序编译时被标记为以后需要链接的部分。与静态库不同,动态库在程序执行时才会被加载,这意味着,程序运行时会占用更少的内存空间,因为动态库的代码不会被复制到每个执行文件中。 在Linux 系统中,动态库通常以 `.so` 结尾。在编译程序时,编译器会自动找到动态库并进行链接。例如,如果你有一个名为 `libmymath.so` 的动态库,其中包含数学函数的实现,那么在编译程序时,你可以使用如下命令: ``` gcc -o myprogram myprogram.c -lmymath ``` 这里,`-lmymath` 告诉链接器要链接到 `libmymath.so` 动态库。
b. 运行时加载 在程序运行时,动态库需要被加载到内存中。在Linux 系统中,这通常通过 `dlopen()` 函数实现。例如,如果你想加载一个名为 `libmymath.so` 的动态库,你可以使用如下命令: ``` void *handle = dlopen("libmymath.so", RTLD_LAZY); if (!handle) { fprintf(stderr, "Error: %s\n", dlerror()); } ``` 这里,`RTLD_LAZY` 是一个标志,表示动态库在需要时才会被加载。在加载动态库后,你可以使用 `dlsym()` 函数来获取函数的符号地址,例如: ``` void (*add)(int, int) = (void (*)(int, int))dlsym(handle, "add"); if (dlerror() != NULL) { fprintf(stderr, "Error: %s\n", dlerror()); } ``` 这里,`add` 是一个指向 `add` 函数的指针,`"add"` 是 `libmymath.so` 动态库中 `add` 函数的符号名称。在获取函数指针后,你可以使用它来调用函数: ``` int result = add(5, 3); ``` 最后,当你完成动态库的使用后,你应该使用`dlclose()` 函数来关闭动态库: ``` dlclose(handle); ``` 这样,动态库就会被释放,程序也会继续执行。 |