一、库文件

库是一组预先编译好的函数的集合,这些函数都是按照可重用的原则编写的。在库中的函数是相互关联的,通过这些函数的组成可以实现相应的功能,如屏幕处理函数库(curses和ncurses库)、数据库访问例程(dbm库)。
在Linux中,标准的库文件一般存放在/lib和usr/lib的目录中。c语言编译器gcc(更确切的说是链接程序)需要知道要搜索哪些库文件,因为默认情况下,它只搜索标准C语言库。仅仅把库文件放在标准目录中就希望C语言编译器gcc能够找到它是不够的,库文件必须遵循特定的命名规范并且需要在命令行中明确指定。
gcc -o hello hello.c /usr/lib/libm.a
1.库文件的名字总是以lib开头,随后分别指明这是什么库(如c代表C语言库,m代表数学库);
2. .a 代表传统的静态函数库
3. .so 代表共享函数库
4. 函数库通常以静态库和共享库两种格式存在,可以通过完整的库文件路径名或用-l标志来告诉C语言编译器gcc要搜索的库文件,如gcc -o hello hello.c /usr/lib/libm.a命令要求在编译hello.c源文件编译成hello的可执行文件的过程中,编译器除了会搜索标准的C语言函数库以外,还会搜索数学库以解决函数引用的问题。gcc -o hello hello.c -lm命令是命令gcc -o hello hello.c /usr/lib/libm.a的简写方式,-lm标志代表的是标准库目录中名为libm.a的函数库,同时使用-lm标志另一个好处是如果有共享库,编译器会自动选择共享库。
5. 虽然库文件和头文件一样,通常都保存在标准位置,但是我们可以通过使用-L标志为gcc编译器增加库的搜索路径。如gcc -o hello -L/usr/hello/lib hello.c -lm这条命令是用/usr/hello/lib目录中的libm库来编译和链接可执行程序hello。

二、静态库

静态库,保存在/lib和/usr/lib目录中,也叫归档文件(archive),以.a结尾。使用ar(代表archive,即建立归档文件)程序和使用gcc -c命令对函数分别进行编译。
在Linux中如何创建静态库?

  1. 为两个函数分别创建各自的源文件(fred.c、 bill.c)
    fred.c源代码:
#include<stdio.h>

void fred(int arg)
{
  printf("fred: we passed %d\n",arg);
}

bill.c源代码:

#include<stdio.h>

void bill(char *arg)
{
   printf("bill:we passed %s\n",arg);
}

2.编译这些文件以产生要包含在库文件中的目标文件,可以通过调用-c选项的C语言编译器gcc来阻止编译器创建一个完整的可执行程序。
gcc -c bill.c fred.c
ls *.o
输出:bill.o fred.o
3.创建库文件的头文件(lib.h)
库文件的头文件lib.h:

void bill(char *);

void fred(int);

该头文件将声明库文件中的函数,同时该头文件需要被可执行程序所包含,把该头文件包含在源文件fred.c和bill.c中可以帮助编译器发现所有错误。
4.创建调用程序(program.c)
program.c源文件:

#include <stdlib.h>
#include "lib.h"

int main()
{
     bill("Hello World");
     exit(0);
}

5.编译,测试该程序
gcc -c program.c
gcc -o program program.o bill.o
./program
输出:
we passed Hello world
首先使用gcc -c program.c命令将program.c文件编译成program.o的目标文件,然后再用gcc -o program program.o bill.o命令将 program.o目标文件和 bill.o目标文件链接起来,最后用./program运行名为program的可执行程序。
6.创建一个静态库文件
ar crv libfoo.a bill.o fred.o
输出:
a - bill.o
a - fred.o
ar crv libfoo.a bill.o fred.o命令是创建一个归档文件(静态库)并将名为bill.o、fred.o目标文件添加到名为libfoo的归档文件中,ar程序是将若干个单独的文件归并到一个大的文件中以创建归档文件或集合。当然,ar程序也可以创建任何类型文件的归档文件。
7.为函数库生成一个内容表
ranlib libfoo.a
使用ranlib libfoo.a命令可以为 libfoo库生成一个内容表。在Linux中,使用GNU的软件开发工具是,这个步骤并不是必须的,做了也没关系。
8.使用静态函数库
方法一:
gcc -o program program.o libfoo.a
./program
输出:
bill:we passed Hello World
使用gcc -o program program.o libfoo.a命令是将目标文件 program.o和库文件libfoo.a链接起来生成名为program的可执行程序。
方法二:
gcc -o program program.o -L. -lfoo
gcc -o program program.o -L. -lfoo命令中的-L.选项是告诉编译器gcc在当前目录中查找函数库,-lfoo选项是告诉编译器使用名为libfoo.a的函数库。
9.查看哪些函数包含在目标文件、函数库、可执行文件中
查看目标文件中包含了哪些函数的命令:
nm program.o
查看函数库中包含了哪些函数的命令:
nm libfoo.a
查看可执行程序中包含了哪些函数的命令
nm program
10.Linux和Windows的区别

项目LinuxWindows
目标文件func.oFUNC.OBJ
静态函数库lib.aLIB.LIB
可执行程序programPROGRAM.EXE

11.静态库的缺点
当同时运行多个应用程序并且它们都使用同一个静态库中的函数时,内存中就会有同一个函数的多份副本,而且程序文件自身也有多份同样的副本。这会消耗大量宝贵的内存和磁盘空间。

三、共享库

共享库,保存位置和静态库一致,都是在/lib和/usr/lib目录中,后缀名为.so,标准数学共享库为/usr/lib/libm.so。
共享库如何链接?
库本身不再包含函数代码,而是引用运行时可访问的共享代码。当编译好的程序被装载到内存中执行时,函数引用被解析并产生对共享库的调用,如果有必要,共享库才被加载到内存中。
共享库优点:
1.系统可以值保留共享库的一份副本供许多应用程序同时使用,并且磁盘上也仅保存一份。
2.共享库的更新可以独立于依赖它的应用程序。如(/lib/libm.so.N,其中N代表主版本号)
动态装载器

动态装载器负责装载共享库并解析客户程序函数引用的程序。在Linux中动态装载器可能是ld.so、ld-linux.so.2、ld-lsb.so.2或ld-lsb.so.3。
搜索共享库的额外位置
可以在/etc/id.so.conf文件中配置,修改之后执行命令ldconfig来处理它。(如安装了X视窗系统后需要添加X11共享库)
查看一个程序需要的共享库
ldd program
输出:
linux-gate.so.1 => (0xb76e2000)
libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0xb751a000)
/lib/ld-linux.so.2 (0xb76e3000)
根据输出可以看到,标准C语言函数库(libc)是共享库,程序需要的是主版本号6.
Linux中的共享库和windows中的动态库
Linux中的共享库后缀名为.so,windows中的动态库后缀名为.DLL,它们都是在程序运行时加载。

GitHub 加速计划 / li / linux-dash
10.39 K
1.2 K
下载
A beautiful web dashboard for Linux
最近提交(Master分支:2 个月前 )
186a802e added ecosystem file for PM2 4 年前
5def40a3 Add host customization support for the NodeJS version 4 年前
Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐