Linux C编程 | 库文件







一、库文件

预先编译好的方法的集合。在Linux下有两种库文件:静态库与共享库。

静态库是以 libxxx.a 的形式存在的库文件,在程序编译时(使用到的方法)会加载到程序中成为程序的一部分。
共享库是以 libxxx.so 的形式存在的库文件,在程序编译时不会加载的程序中,在程序运行时才进行加载

两种库文件各有优缺点,下表简单的归纳了以下两种库文件的特点:
(在windows中的库文件也是有静态库(xx.lib)和动态库(xx.dll) )

实现机制优点缺点
静态库libname.a将库文件中使用到的方法写入到可执行文件1. 程序一次编译完成,运行时无需额外加载,运行相对较快1.可执行程序相对较大,占用磁盘空间较大
2.程序运行时,库文件部分会被加载到内存,增加了内存的消耗
3.程序的每次更新都需要将整个程序重新编译一遍,维护不方便
共享库libname.so将库文件中使用到的方法在可执行文件中形成一份引用,在执行是加载1.可执行程序相对较小,占用磁盘空间小
2.程序运行时,用到库文件部分在内存中与其他程序共享一份“库”,节省内存消耗
3.程序更新时,只需重新编译动态库
1.每次运行都需要加载动态库,运行速度相对较慢

由于现在计算机的运行速度都很快,静态库的优点已不是那么明显了。但是一般来说针对一些小的可执行程序通常使用静态库,这样我们写好的程序提供给别人使用时就会很方便。

二、标准目录

在linux下,一般头文件放在 /usr/include/ 目录下。在C程序中使用 <xxx.h> 尖括号括起来的头文件,自动在该目录下检索对应的头文件。使用 "xxx.h" 引号括起来的头文件优先在程序所在目录检索对应头文件,找不到再在/usr/include/下查找。如果使用的头文件不再这两种目录内,在编译时使用 -I 参数指定头文件路径。
可执行程序/命令一般放在 /bin/usr/bin/ 目录下。同理我们在终端执行命令时优先在这些目录查找,所以我们在执行自己写的程序时通常会在程序前指定路径,如~/run 执行自己家目录下的run程序,./run 执行当前目录下的run程序。
库文件一般存放在 /lib/usr/lib/ 目录下。如果我们使用的是标准库文件,我们在编译时无需指定库文件路径即可编译成功。如果我们使用的是自己制作的库文件可使用参数 -L-l 的方式指定库文件路径和库名。在使用共享库时,通常把自己的库文件放在标准库文件目录下。

创建库文件:
创建静态库文件

使用ar命令创建静态库文件 ar crv libname.a 1.o 2.o ..... c – 创建库、r – 把方法添加到库中、v – 显示信息。
其中 libname.alib是库名前缀,库名是“name”,在使用是通过 “-l+库名”的方式使用。

下面是有关ar命令的参数:

$ ar -h

用法:ar [仿真选项] [-]{dmpqrstx}[abcDfilMNoPsSTuvV] [--plugin <名称>] [成员名] [计数] 归档 文件…
       ar -M [<mri-脚本]
 命令:
  d            - 从归档文件中删除文件
  m[ab]        - 在归档文件中移动文件
  p            - 打印在归档文件中找到的文件
  q[f]         - 将文件快速追加到归档文件中
  r[ab][f][u]  - 替换归档文件中已有的文件或加入新文件
  s            - 作为 ranlib 工作
  t            - 显示归档文件的内容
  x[o]         - 从归档文件中分解文件
 特定命令修饰符:
  [a]          - 将文件置于 [成员名] 之后
  [b]          - 将文件置于 [成员名] 之前 ([i] 相同)
  [D]          - 将 0 用于时间戳和 uid/gid(默认)
  [D]          - 使用实际时间戳和 uid/gid
  [N]          - 使用名称的实例 [数量]
  [f]          - 截去插入的文件名称
  [P]          - 在匹配时使用完整的路径名
  [o]          - 保留原来的日期
  [u]          - 只替换比当前归档内容更新的文件
 通用修饰符:
  [c]          - 不在必须创建库的时候给出警告
  [s]          - 创建归档索引 (cf. ranlib)
  [S]          - 不要创建符号表
  [T]          - 产生一个简单归档
  [v]          - 输出较多信息
  [V]          - 显示版本号
创建共享库文件

使用 gcc 可以创建动态库,gcc -shared -fPIC -o libname.so 1.o 2.o ...
其中,-fPIC 作用于编译阶段,告诉编译器产生与位置无关代码(Position-Independent Code),则产生的代码中,没有绝对地址,全部使用相对地址,故而代码可以被加载器加载到内存的任意位置,都可以正确的执行。

三、库文件实例

下面通过三个实例来了解静态库与共享库。

实例一:多文件编译

a.c 文件中:

#include <stdio.h>

/* a.c file */
void afun()
{
	printf("this is a.c file\n");
}

b.c 文件中:

#include <stdio.h>

/* b.c file */
void bfun()
{
	printf("this is b.c file\n");
}

main.c 文件中:

#include <stdio.h>

/* 声明外部函数 */
void afun();
void bfun();

int main()
{
	afun();
	bfun();
	return 0;
}

编译程序并运行:
在这里插入图片描述

实例二:制作静态库

使用 ar crv libfile.a a.o b.o 命令将之前的 a.ob.o 文件制作成为静态库。
在这里插入图片描述
main.o 文件与 libfile.a 库文件放在同一个目录下,进行链接操作。
gcc -o run main.c -L. -lfile 参数-L指定库文件位置,参数 -l指定库名。
在这里插入图片描述

实例三:制作共享库

使用 gcc -shared -fPIC -o libfile.so a.o b.o 命令将之前的 a.ob.o 文件制作成为共享库。
在这里插入图片描述
可以看到 libfile.so 共享库文件已经创建完成。
下面我们创建一个 test2 目录,把共享库文件和 main 主程序相关文件 拷贝到该目录下。
在这里插入图片描述
现在我们使用共享库对程序进行链接。同样的使用命令 gcc -o run main.c -L. -lfile 。参数-L指定库文件位置,参数 -l指定库名。
执行链接后的 run 可执行程序。
在这里插入图片描述
可以看到执行失败了,提示信息为“libfile.so: cannot open shared object file: No such file or directory”。提示我们没有找到 libfile.so 库文件。还记得上文提到的共享库的特点吗,在运行时才加载,编译时知识生成一份引用。

我们用ldd 命令查看程序使用了哪些共享库。
在这里插入图片描述
这里显示libfile.so 文件因为不在标准库文件目录下,所以没有找到库文件的地址。其他三个库文件所在的目录都是在环境变量中设置好的搜索路径。

我们将libfile.so动态库添加到 /usr/lib/标准库文件目录下。(管理员模式)
在这里插入图片描述
我们在管理员模式下,使用 mv libfile.so /usr/lib/ 命令将 libfile.so 文件剪切到 /usr/lib/ 目录下。现在使用 ldd 命令查看程序所需的共享库文件是否可以找到。并测试程序是否可以成功运行。
在这里插入图片描述

实例四:优先使用共享库

在链接时,如果静态库与共享库同名,优先使用共享库进行编译。

我们将两种库文件放在同一目录下,对主程序文件进行链接,查看生成的可执行程序。
在这里插入图片描述
如图所示,在 test3 目录下有三个文件,分别是 libfile.a 静态库文件、libfile.so 共享库文件、main.o 主程序文件。使用 gcc -o run main.o -L. -lfile 命令对程序进行链接,生成run程序。

注:ldd 命令只可以查看程序使用的共享库的情况,这里显示 libfoo.so,证明使用了共享库文件 libfile.so

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我叫RT

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值