zoukankan      html  css  js  c++  java
  • 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  

     1 int add(int var1, int var2){                                                
     2     return var1 + var2;
     3 }

    sub.c

     1 int sub(int var1, int var2){                                                
     2     return var1 - var2;
     3 }

    mul.c

     1 int mul(int var1, int var2){                                                
     2     return var1 * var2;
     3 }

    div.c

     1 int div(int var1, int var2){                                                
     2     if(0==var2){
     3         return -1;
     4     }else{
     5         return var1 / var2;
     6     }
     7 }

    mod.c

     1 int mod(int var1, int var2){                                                
     2     return var1 % var2;
     3 } 

    cal.h

     1 #ifndef cal_h
     2 #define cal_h
     3                                                                             
     4 int add(int, int);
     5 int sub(int, int);
     6 int mul(int, int);
     7 int div(int, int);
     8 int mod(int, int);
     9 
    10 #endif

    testCal.c

     1 #include <stdio.h>
     2 
     3 #include "cal.h"
     4 
     5 int main(int argc, char **argv)
     6 {
     7     int var1;
     8     int var2;
     9     printf("please input the var1: ");
    10     scanf("%d", &var1);
    11     printf("please input the var2: ");
    12     scanf("%d", &var2);
    13     printf("%d add %d is %d
    ", var1, var2, add(var1, var2));
    14     printf("%d sub %d is %d
    ", var1, var2, sub(var1, var2));
    15     printf("%d mul %d is %d
    ", var1, var2, mul(var1, var2));
    16     printf("%d div %d is %d
    ", var1, var2, div(var1, var2));
    17     printf("%d mod %d is %d
    ", var1, var2, mod(var1, var2));               
    18 
    19     return 0;
    20 }

      这个是附加的文件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
    总用量 40
    -rw-r--r-- 1 munication munication   52 7月   9 12:39 add.c
    -rw-r--r-- 1 munication munication  132 7月   9 12:55 cal.h
    -rw-r--r-- 1 munication munication   91 7月   9 12:41 div.c
    -rw-r--r-- 1 munication munication  235 7月   9 14:55 makefile
    -rw-r--r-- 1 munication munication   52 7月   9 12:42 mod.c
    -rw-r--r-- 1 munication munication   52 7月   9 12:40 mul.c
    -rw-r--r-- 1 munication munication   52 7月   9 12:40 sub.c
    -rwxr-xr-x 1 munication munication 7388 7月   9 14:53 testCal
    -rw-r--r-- 1 munication munication  517 7月   9 13:02 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 2

      二、使用静态库文件,生成静态库。库文件一般以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
    总用量 764
    -rw-r--r-- 1 munication munication     52 7月   9 12:39 add.c
    -rw-r--r-- 1 munication munication    132 7月   9 12:55 cal.h
    -rw-r--r-- 1 munication munication     91 7月   9 12:41 div.c
    -rw-r--r-- 1 munication munication   4608 7月   9 15:10 libcal.a
    -rw-r--r-- 1 munication munication    235 7月   9 14:55 makefile
    -rw-r--r-- 1 munication munication     52 7月   9 12:42 mod.c
    -rw-r--r-- 1 munication munication     52 7月   9 12:40 mul.c
    -rw-r--r-- 1 munication munication     52 7月   9 12:40 sub.c
    -rwxr-xr-x 1 munication munication 740140 7月   9 15:16 testCal
    -rw-r--r-- 1 munication munication    517 7月   9 13:02 testCal.c

      可以很明显看出:使用静态库文件的可执行文件的大小为740140字节,超过700k字节

      执行可执行文件,使用命令:

    [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 2

      三、使用动态库文件:生成动态库文件。库文件一般以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
    总用量 56
    -rw-r--r-- 1 munication munication   52 7月   9 12:39 add.c
    -rw-r--r-- 1 munication munication  132 7月   9 12:55 cal.h
    -rw-r--r-- 1 munication munication   91 7月   9 12:41 div.c
    -rw-r--r-- 1 munication munication 4608 7月   9 15:10 libcal.a
    -rwxr-xr-x 1 munication munication 6832 7月   9 15:51 libcal.so
    -rw-r--r-- 1 munication munication  235 7月   9 14:55 makefile
    -rw-r--r-- 1 munication munication   52 7月   9 12:42 mod.c
    -rw-r--r-- 1 munication munication   52 7月   9 12:40 mul.c
    -rw-r--r-- 1 munication munication   52 7月   9 12:40 sub.c
    -rwxr-xr-x 1 munication munication 7296 7月   9 16:01 testCal
    -rw-r--r-- 1 munication munication  517 7月   9 13:02 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.1 (0xb777d000)
            libcal.so => /home/munication/WORKM/libDemo/libcal.so (0xb7745000)
            libc.so.6 => /usr/lib/libc.so.6 (0xb7585000)
            /lib/ld-linux.so.2 (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 环境变量:指定程序动态链接库文件搜索路径

      

  • 相关阅读:
    Asp.net弹出浏览器客户端确认对话框代码 Carlwave
    VS 2005 与SQL Server 2005整合优势在哪里?(from csdn.net) Carlwave
    如何让搜索引擎收录我的站点 Carlwave
    超强扩展性的DNNDotNetNuke模块功能分类列表(from 中国DNN) Carlwave
    DotNetNuke命名空间概述 Carlwave
    Most Popular Questions and Answers on ASP.NET Whidbey(from asp.net forums,write by ASP.NET Team) Carlwave
    火箭官方宣告麦蒂缺阵五周 季后赛前景蒙上阴影 Carlwave
    asp.net有效使用缓存(转) Carlwave
    《Business Rules Engine Overview》《业务规则引擎概述》write by Mark Kamoski Carlwave
    中国详细省市县自治区名称列表(含access数据库和sql2000备份数据库) Carlwave
  • 原文地址:https://www.cnblogs.com/guochaoxxl/p/7141447.html
Copyright © 2011-2022 走看看