linux下库文件的编程
编程到了一定的时候,总喜欢追求新的东西。将代码尽量模块化就是我的追求之一,原来只是满足于将代码从单文件中分离,通过头文件和实现文件实现模块化,后来发现最好的方法是打包成库文件,使用更加方便。尽管在linux和windows下都有大量的库文件,由于二者的工具不同,加上笔者主要是在linux下编程和教学,因此本文主要介绍Linux下的库文件的制作。
库文件在linux中主要有两种:静态库和动态库(共享库),二者的不同主要有:
1、载入时机不同:静态库是在编译时进行载入到代码中;共享库在运行时载入到代码中;
2、对生成的可执行文件的影响不同:静态库的缺失不会影响后期可执行文件的运行;共享库的缺失会影响可执行文件的执行;
3、对可执行文件大小改变不同:静态库在编译过程中将所有文件添加到可执行文件中,生成可执行文件偏大;共享库在编译过程中将所有文件链接到可执行文件中,生成的可执行文件几乎没有增大;
4、后期维护的影响不同:静态库可能会重复应用,浪费空间;共享库更容易引用使用,只需要一份库实现多个文件的共享使用;
5、后缀名称不同:静态库的后缀名是.a; 动态库的后缀名是.so;
6、生成方式不同:静态库主要是gcc将*.c文件形成*.o文件,使用ar命令打包成.a文件即可;动态库文件主要由gcc加上特定参数编译生成
7、形成的可执行文件的执行方式不同:静态库生成的可执行文件直接执行即可;动态库生成的可执行文件执行时须保证动态库文件能够被找到:可以将动态库文件链接或复制到/usr/lib或/lib目录,一般不这样做;设置环境变量LD_LIBRARY_PATH,使用命令export LD_LIBRARY_PATH=$(pwd);使用命令ldconfig目录,将制定目录下的动态链接库被系统共享起来sudo ldconfig /home/munication/WORKM/libDemo/;
作为现成的库文件,一般都具有成熟可靠、能够复用、接口明确等特点。因此,善于利用库文件,会让初学者很容易站在巨人的肩膀上。
下面为了更好的说明问题,通过三种方式来形成一个可执行文件testCal,功能很简单。
一、不是用库的方式,代码add.c、sub.c、mul.c、div.c、mod.c、cal.h testCal.c都是一样的:
add.c
int add(int var1, int var2){
return var1 + var2;
}
sub.c
int sub(int var1, int var2){
return var1 - var2;
}
mul.c
int mul(int var1, int var2){
return var1 * var2;
}
div.c
int div(int var1, int var2){
if(==var2){
return -;
}else{
return var1 / var2;
}
}
mod.c
int mod(int var1, int var2){
return var1 % var2;
}
cal.h
#ifndef cal_h
#define cal_h int add(int, int);
int sub(int, int);
int mul(int, int);
int div(int, int);
int mod(int, int); #endif
testCal.c
#include <stdio.h> #include "cal.h" int main(int argc, char **argv)
{
int var1;
int var2;
printf("please input the var1: ");
scanf("%d", &var1);
printf("please input the var2: ");
scanf("%d", &var2);
printf("%d add %d is %d\n", var1, var2, add(var1, var2));
printf("%d sub %d is %d\n", var1, var2, sub(var1, var2));
printf("%d mul %d is %d\n", var1, var2, mul(var1, var2));
printf("%d div %d is %d\n", var1, var2, div(var1, var2));
printf("%d mod %d is %d\n", var1, var2, mod(var1, var2)); return ;
}
这个是附加的文件makefile,文件名称为makefile
1 OBJ=testCal.o add.o sub.o mul.o div.o mod.o
2 testCal:$(OBJ) cal.h
3 gcc -o testCal $(OBJ)
4 testCal.o:testCal.c
5 add.o:add.c
6 sub.o:sub.c
7 mul.o:mul.c
8 div.o:div.c
9 mod.o:mod.c
10
11 .PHONY:cleanA clean
12 cleanA:
13 rm testCal $(OBJ)
14 clean:
15 rm $(OBJ)
如果有上边的makefile文件,下面的操作都是假设上边所有的文件:add.c cal.h div.c makefile mod.c mul.c sub.c testCal.c都在/home/munication/WORKM/libDemo/目录下
终端下到/home/munication/WORKM/libDemo/目录下,
使用下面的目录生成可执行文件,并有下面的提示信息:
make
cc -c -o testCal.o testCal.c
cc -c -o add.o add.c
cc -c -o sub.o sub.c
cc -c -o mul.o mul.c
cc -c -o div.o div.c
cc -c -o mod.o mod.c
gcc -o testCal testCal.o add.o sub.o mul.o div.o mod.o
如果其中的文件更改,可以使用同一个命令make即可重新编译生成新的执行文件,make会自动判断那些文件需要编译,如果需要把中间文件删除,使用命令make clean,提示信息为;
make clean #删除中间文件*.o,保留testCal可执行文件
make cleanA #删除所有生成文件,包括中间文件*.o,最终testCal可执行文件
rm testCal.o add.o sub.o mul.o div.o mod.o #删除中间文件*.o,保留testCal可执行文件
rm testCal testCal.o add.o sub.o mul.o div.o mod.o #删除所有生成文件,包括中间文件*.o,最终testCal可执行文件
如果不用makefile文件,可以使用手工命令:
gcc -c add.c sub.c mul.c div.c mod.c testCal.c #形成目标文件
gcc -o testCal testCal.o add.o sub.o mul.o div.o mod.o #生成可执行文件
rm testCal.o add.o sub.o mul.o div.o mod.o #删除中间文件*.o,保留testCal可执行文件
rm testCal testCal.o add.o sub.o mul.o div.o mod.o #删除所有生成文件,包括中间文件*.o,最终testCal可执行文件
查看文件大小:
[munication@develop libDemo]$ ls -l
总用量
-rw-r--r-- munication munication 7月 : add.c
-rw-r--r-- munication munication 7月 : cal.h
-rw-r--r-- munication munication 7月 : div.c
-rw-r--r-- munication munication 7月 : makefile
-rw-r--r-- munication munication 7月 : mod.c
-rw-r--r-- munication munication 7月 : mul.c
-rw-r--r-- munication munication 7月 : sub.c
-rwxr-xr-x munication munication 7月 : testCal
-rw-r--r-- munication munication 7月 : testCal.c
很明显,可以看出形成的可执行文件的大小是7388字节,7k字节的大小。
执行可执行文件,使用命令:
[munication@develop libDemo]$ testCal
please input the var1: 14
please input the var2: 3
14 add 3 is 17
14 sub 3 is 11
14 mul 3 is 42
14 div 3 is 4
14 mod 3 is
二、使用静态库文件,生成静态库。库文件一般以lib为前缀,紧接着是库的名称,扩展名为.a,例如我们这里要创建库名libcal.a的库,使用命令ar,具体如下:
ar rcs libcal.a add.o sub.o mul.o div.o mod.o
使用静态库,创建库文件的接口文件头文件,本文中是cal.h文件,使用库文件的文件testCal.c包含头文件cal.h文件即可,使用如下命令编译:
gcc -o testCal testCal.c -static -L. -lcal
其中上边命令的说明:
(1)、gcc -o testCal:使用gcc编译,-o指定文件名,后边的testCal就是最终生成的文件名
(2)、-static:指明使用静态库
(3)、-L.:-L指明使用库,后面的.表明库文件在当前目录
(4)、-lcal:表明是库文件的名称,其中-表明是选项,l是lib的简写,后边的cal才是真正的库文件名称,后缀名是不需要的
查看文件的大小:
[munication@develop libDemo]$ ls -l
总用量
-rw-r--r-- munication munication 7月 : add.c
-rw-r--r-- munication munication 7月 : cal.h
-rw-r--r-- munication munication 7月 : div.c
-rw-r--r-- munication munication 7月 : libcal.a
-rw-r--r-- munication munication 7月 : makefile
-rw-r--r-- munication munication 7月 : mod.c
-rw-r--r-- munication munication 7月 : mul.c
-rw-r--r-- munication munication 7月 : sub.c
-rwxr-xr-x munication munication 7月 : testCal
-rw-r--r-- munication munication 7月 : testCal.c
可以很明显看出:使用静态库文件的可执行文件的大小为740140字节,超过700k字节
执行可执行文件,使用命令:
[munication@develop libDemo]$ testCal
please input the var1:
please input the var2:
add is
sub is
mul is
div is
mod is
三、使用动态库文件:生成动态库文件。库文件一般以lib为前缀,紧接着是库的名称,扩展名为.so,例如我们这里要创建库名libcal.so的库,具体如下:
[munication@develop libDemo]$ make
cc -c -o testCal.o testCal.c
cc -c -o add.o add.c
cc -c -o sub.o sub.c
cc -c -o mul.o mul.c
cc -c -o div.o div.c
cc -c -o mod.o mod.c
gcc -o testCal testCal.o add.o sub.o mul.o div.o mod.o
以上,先运行make命令,通过makefile文件生成目标文件testCal.o add.o sub.o mul.o div.o mod.o,接着使用下面命令:
gcc -shared -fPIC -o libcal.so add.o sub.o mul.o div.o mod.o
其中上边命令的说明:
(1)、gcc -o libcal.so:使用gcc编译,-o指定文件名,后边的libcal.so就是最终生成的动态库名
(2)、-shared:指明生成动态库
(3)、-fPIC.:该选项告诉gcc产生的代码不要包含对函数和变量具体内存位置的引用,运行时进行地址链接
gcc -o testCal testCal.c -L. -lcal
其中上边命令的说明:
(1)、gcc -o testCal:使用gcc编译,-o指定文件名,后边的libcal.so就是最终生成可执行文件名称
(2)、没有使用-static:指明使用动态库
(3)、-L.:-L指明使用库,后面的.表明库文件在当前目录
(4)、-lcal:表明是库文件的名称,其中-表明是选项,l是lib的简写,后边的cal才是真正的库文件名称,后缀名是不需要的
查看文件大小:
[munication@develop libDemo]$ ls -l
总用量
-rw-r--r-- munication munication 7月 : add.c
-rw-r--r-- munication munication 7月 : cal.h
-rw-r--r-- munication munication 7月 : div.c
-rw-r--r-- munication munication 7月 : libcal.a
-rwxr-xr-x munication munication 7月 : libcal.so
-rw-r--r-- munication munication 7月 : makefile
-rw-r--r-- munication munication 7月 : mod.c
-rw-r--r-- munication munication 7月 : mul.c
-rw-r--r-- munication munication 7月 : sub.c
-rwxr-xr-x munication munication 7月 : testCal
-rw-r--r-- munication munication 7月 : testCal.c
可以很明显看出:使用动态库文件的可执行文件的大小为7296字节,超过7k字节,比不打包成库大了一点,多了链接信息,比静态库小了很多,差不多只有静态库的1%大小。
执行可执行文件时,可能会出现错误,提示找不到动态库文件libcal.so文件,解决方案主要有如下几种:
(1)、将生成的库文件libcal.so文件复制到目录/usr/lib或者/lib目录中,这种方式容易污染系统的库文件,也可以将自己作的库文件libcal.so链接到/usr/lib或/lib中,再次执行可执行文件就正常了;
(2)、连接器会搜索LD_LIBRARY_PATH指定的目录,将该环境变量设置为当前目录,具体命令为:
export LD_LIBRARY_PATH=$(pwd)
(3)、使用命令ldconfig目录,将制定目录下的动态链接库被系统共享起来,具体命令为:
sudo ldconfig /home/munication/WORKM/libDemo/
最后的附加:可以使用命令ldd查看可执行文件执行时调用的动态库,具体命令为:
[munication@develop libDemo]$ ldd testCal
linux-gate.so. (0xb777d000)
libcal.so => /home/munication/WORKM/libDemo/libcal.so (0xb7745000)
libc.so. => /usr/lib/libc.so. (0xb7585000)
/lib/ld-linux.so. (0xb777f000)
gcc编译时搜索库文件的顺序,可以通过一定的手段覆盖系统的库文件,一般不要这么做,后果可能会很严重。
静态库链接时搜索路径顺序:
(1). ld 会去找 GCC 命令中的参数-L
(2). 再找 gcc 的环境变量 LIBRARY_PATH
(3). 再找内定目录 /lib /usr/lib /usr/local/lib 这是当初 compile gcc 时写在程序内的
动态链接时、执行时搜索路径顺序:
(1). 编译目标代码时指定的动态库搜索路径;
(2). 环境变量 LD_LIBRARY_PATH 指定的动态库搜索路径;
(3). 配置文件/etc/ld.so.conf 中指定的动态库搜索路径;
(4). 默认的动态库搜索路径/lib;
(5). 默认的动态库搜索路径/usr/lib。
有关环境变量:
(1).LIBRARY_PATH 环境变量:指定程序静态链接库文件搜索路径
(2).LD_LIBRARY_PATH 环境变量:指定程序动态链接库文件搜索路径
linux下库文件的编程的更多相关文章
- Linux下库文件的设置 (/usr/bin/ld: cannot find -lxxx 的解决办法)
在软件编译过程中,经常会碰到类似这样的编译错误: /usr/bin/ld: cannot find -lhdf5 这表示找不到库文件 libhdf5.so,若是其它库文件,则是 cannot find ...
- linux下各文件夹的结构说明及用途介绍
linux下各文件夹的结构说明及用途介绍: /bin:二进制可执行命令. /dev:设备特殊文件. /etc:系统管理和配置文件. /etc/rc.d:启动的配 置文件和脚本. /ho ...
- 【转】linux下各文件夹的结构说明及用途介绍
linux下各文件夹的结构说明及用途介绍: /bin:二进制可执行命令. /dev:设备特殊文件. /etc:系统管理和配置文件. /etc/rc.d:启动的配 置文件和脚本. /home:用户主目录 ...
- linux下怎样对串口编程
Linux操作系统从一開始就对串行口提供了非常好的支持,本文就Linux下的串行口通讯编程进行简单的介绍. 串口简单介绍串行口是计算机一种经常使用的接口.具有连接线少.通讯简单.得到广泛的使用. 经常 ...
- Linux下各文件夹的结构说明及用途介绍(转载)
linux下各文件夹的结构说明及用途介绍: /bin:二进制可执行命令. /dev:设备特殊文件. /etc:系统管理和配置文件. /etc/rc.d:启动的配 置文件和脚本. /home:用户主目录 ...
- linux下各文件夹的结构说明及用途介绍:Linux目录结构介绍
linux下各文件夹的结构说明及用途介绍: /bin:二进制可执行命令. /dev:设备特殊文件. /etc:系统管理和配置文件. /etc/rc.d:启动的配 置文件和脚本. /home:用户主目录 ...
- 【ARM-Linux开发】linux下Eclipse进行C编程时动态链接库的生成和使用
linux下Eclipse进行C编程时动态链接库的生成和使用 引用 http://linux.chinaitlab.com/soft/864157.html 欢迎进入Linux社区论坛,与200万技术 ...
- Linux下的C语言编程
一.在Linux下的C语言编程所需工具(下面所列举的都是我编程所用的工具) 1.文本编辑器 Vim 2.编译链接工具 gcc 3.调试器 gdb 4.项目管理工具 make和makefile 二.VI ...
- Linux下的C Socket编程 -- server端的继续研究
Linux下的C Socket编程(四) 延长server的生命周期 在前面的一个个例子中,server在处理完一个连接后便会立即结束掉自己,然而这种server并不科学啊,server应该是能够一直 ...
随机推荐
- CSS层叠的问题、标准文档流、伪类选择器
一.层叠的问题 CSS有两个性质: 1.继承性 2.层叠性:选择器的一种选择能力,谁的权重大就选谁 层叠性又分为: 1).选不中:走继承性 (font.color.text.) 继承性的权重是0 若 ...
- 伟景行 citymaker 从入门到精通(2)——工程图层树加载
工程树是指explorer左边这棵树 本例子实现了图层树加载,点击节点切换可视状态 树控件使用easyui的树 html部分 onCheck:treeProjectTreeOnCheck是指树节点的o ...
- HashMap,Hashset,ArrayList以及LinkedList集合的区别,以及各自的用法
基础内容 容器就是一种装其他各种对象的器皿.java.util包 容器:Set, List, Map ,数组.只有这四种容器. Collection(集合) 一个一个往里装,Map 一对一对往里装. ...
- Oracle Recycle Bin
开启回收站RECYCLEBIN=ON,默认开启 ALTER SYSTEM SET RECYCLEBIN=OFF SCOPE=SPFILE; 一.从回收站还原表 还原删除的表和从属对象. 如果多个回收站 ...
- SQLite – GLOB子句
SQLite – GLOB子句 .与LIKE不同,GLOB是大小写敏感的,它遵循语法的UNIX指定以下通配符. The asterisk sign (*) The question mark (?) ...
- Dreamoon and MRT(二元枚举)
题目 数轴上有M个点a1.a2....am,另有一个数列p1.p2....pn,(1 ≤ pii ≤ M). 给定d1.d2....dn,对所有的 i (1 ≤ i ≤ n),已知 |api+1 - ...
- uva1153 Keep the Customer Satisfied
贪心加优先队列 (默认是小的在前,正好) //这里又很套路,设队列里的都是符合条件的考虑新加入的即可.再处理一下空队列的情况.很完美// 截止时间短的在前面,干的就多先根据截止日期排序优先队列根据完成 ...
- vue之组件的使用(转载)
在工程目录/src下的component文件夹下创建一个 firstcomponent.vue并写仿照 App.vue 的格式和前面学到的知识写一个组件. <template> <d ...
- java分段加载数据,循环和递归两种方式
package org.jimmy.autosearch2019.test; import java.util.ArrayList; public class Test20190328 { priva ...
- 【2018 CCPC网络赛】1003 - 费马小定理
题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=6440 这题主要是理解题意: 题意:定义一个加法和乘法,使得 (m+n)p = mp+np; 其中给定 ...