zoukankan      html  css  js  c++  java
  • linux编程lib的使用

    今天由于要用到静态链接库,所以就学习了一下相关知识,总结如下:

    静态链接库(一般命名为libxxx.a)就是很多.o文件的集合,在你的项目中如果有一个子模快,这个子模块只是给总控模块提供一个函数接口,那么你就可以考虑把这个子模快编译成静态链接库libxxx.a,然后在总控模块中编译的时候,只需-L包含链接库所在的目录,再-lxxx引用链接库就行.

    当然,你也可以用动态链接库,具体的动态链接库创建和引用,做法和静态链接库大同小异,只是动态链接库是在程序执行的时候是动态的添加到内存的,所以可以实现进程之间的资源共享.
    另外动态链接库可以做到所有的函数本着“有需求才调入”的原则,于是大大节省了系统资源:也就是说什么时候或者什么情况下,链接载入哪个动态链接库函数,完全由程序员在程序代码中控制。这样,当你有一个相当大的工程,每次运行的时候,由于不同的操作需求,就只会有一小部分程序被载入内存。

    具体给一个例子,先看一下工程的目录结构:
    $ ls -RF
    .:
    lib/  main.c  Makefile

    ./lib:
    Makefile.a  Makefile.so  string.h  strlen.c  strnlen.c

    在工程主目录下有main.c主控程序,Makefile文件和lib目录
    lib目录下有string.h头文件,strlen.c和strnlen.c,这三个文件里的函数就是我们想生成的库函数
    Makefile.a生成静态链接库的makefile文件
    Makefile.so生成动态链接库的makefile文件



    好,让我们看一看这些文件的具体内容:

    头文件string.h,声明相关函数原形
    $cat lib/string.h

    int Strlen(char *pStr);
    int StrNlen(char *pStr, unsigned long ulMaxLen);



    strlen.c:函数Strlen的实现,获取给定字符串的长度
    $cat lib/strlen.c
     

    #include <stdio.h>
    #include <assert.h>
    int Strlen(char *pStr)
    {
        unsigned long ulLength;
        assert(NULL != pStr);

        ulLength = 0;
        while(*pStr++)
        {
            ulLength++;
        }
        return ulLength;
    }



    strnlen.c:函数StrNlen的实现,获取给定字符串的长度,如果输入字符串的长度大于指定的最大长度,则返回最大长度,否者返回字符串的实际长度
    $cat lib/strnlen.c

    #include<stdio.h>
    #include<assert.h>
    int StrNlen(char *pStr, unsigned long ulMaxLen)
    {
        unsigned long ulLength;
        assert(NULL != pStr);
        if(ulMaxLen <= 0)
        {
            printf("Wrong Max Length!\n");
            return -1;
        }
        ulLength = 0;
        while(*pStr++ && ulLength < ulMaxLen)
        {
            ulLength++;
        }
        return ulLength;
    }


    这三个文件是在lib/目录下.

    Makefile.a:生成静态链接库的makefile文件
    $ cat lib/Makefile.a

    libstr.a: strlen.o strnlen.o
        $(AR) r $@ $^
        $(RM) $^

    .PHONY : clean
    clean :
        rm -f libstr.a



    Makefile.so:生成动态链接库的makefile文件
    $ cat Makefile.so 

    libstr.so: strlen.o strnlen.o
        gcc -fpic -shared -o $@ $^
        $(RM) $^

    .PHONY : clean
    clean :
        rm -f libstr.so


    -fpic 使输出的对象模块是按照可重定位地址方式生成的
    -shared指定把对应的源文件生成对应的动态链接库文件libstr.so文件


    main.c:总控程序

    #include <stdio.h>
    #include "./lib/string.h" //静态库对应函数的头文件


    int main(int argc, char* argv[])
    {
        char str[] = {"hello world"};
        unsigned long ulLength = 0;

        printf("The string is : %s\n", str);
        ulLength = Strlen(str);
        printf("The string length is : %d(use Strlen)\n", ulLength);
        ulLength = StrNlen(str, 10);
        printf("The string length is : %d(use StrNlen)\n", ulLength);

        return 0;
    }



    总控Makefile
    $ cat Makefile 

    CC = gcc
    CFLAGS = -Wall -g
    LIBPATH = -L./lib
    LIB = -lstr

    main: main.o
        $(CC) $(CFLAGS) -o $@ main.o $(LIBPATH) $(LIB)
        $(RM) *.o

    .PHONY:clean
    clean:
        -rm -f main




    下面看一看怎么生成和使用静态链接库/动态链接库
    1.静态链接库的生成:
    $ cd lib
    $ make -f Makefile.a 
    cc    -c -o strlen.o strlen.c
    cc    -c -o strnlen.o strnlen.c
    ar r libstr.a strlen.o strnlen.o
    ar: creating libstr.a
    rm -f strlen.o strnlen.o
    这样就生成了静态链接库libstr.a了.

    2.静态链接库的使用:


    $ cat Makefile 
    CC = gcc
    CFLAGS = -Wall -g
    LIBPATH = -L./lib
    LIB = -lstr

    main: main.o
        $(CC) $(CFLAGS) -o $@ main.o $(LIBPATH) $(LIB)
        $(RM) *.o

    .PHONY:clean
    clean:
        -rm -f main

    -L指定库文件的路径
    -l引用库文件

    看看结果:
    $ make
    gcc -Wall -g   -c -o main.o main.c
    gcc -Wall -g -o main main.o -L./lib -lstr
    rm -f *.o
    $ ls
    lib  main  main.c  Makefile
    生成了可执行文件main
    $ ./main 
    The string is : hello world
    The string length is : 11(use Strlen)
    The string length is : 10(use StrNlen)


    3.动态链接库的生成:
    先删除刚才生成的静态链接库
    $ cd lib
    $ make clean -f Makefile.a
    rm -f libstr.a

    $ make -f Makefile.so 
    cc    -c -o strlen.o strlen.c
    cc    -c -o strnlen.o strnlen.c
    gcc -fpic -shared -o libstr.so strlen.o strnlen.o
    rm -f strlen.o strnlen.o
    $ ls
    libstr.so  Makefile.a  Makefile.so  string.h  strlen.c  strnlen.c
    生成了动态链接库libstr.so

    4.动态链接库的使用:
    使用方法和静态链接库一样,还用的是静态链接库的那个Makefile
    $ cat Makefile 
    CC = gcc
    CFLAGS = -Wall -g
    LIBPATH = -L./lib
    LIB = -lstr

    main: main.o
        $(CC) $(CFLAGS) -o $@ main.o $(LIBPATH) $(LIB)
        $(RM) *.o

    .PHONY:clean
    clean:
        -rm -f main

    -L指定库文件的路径
    -l引用库文件

    $ make
    gcc -Wall -g   -c -o main.o main.c
    gcc -Wall -g -o main main.o -L./lib -lstr
    rm -f *.o
    $ ls
    lib  main  main.c  Makefile
    生成了可执行文件main
    $ ./main 
    ./main: error while loading shared libraries: libstr.so: cannot open shared object file: No such file or directory


     

     

    这就是动态链接库和静态链接库使用时唯一的区别:
     

    在程序运行期间,也需要告诉系统去哪里找你的动态链接库文件.在UNIX下是通过定义名为LD_LIBRARY_PATH 的环境变量来实现的.只需将动态链接库的目录path赋值给此变量即可。
    为了让执行程序顺利找到动态库,有三种方法:
    1)把库拷贝到/usr/lib和/lib目录下.
    2)在LD_LIBRARY_PATH环境变量中加上库所在路径.例如动态库libstr.so在/home/xulei/test/lib目录下,以bash为例,使用命令:
    $export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/xulei/test/lib
    在环境变量LD_LIBRARY_PATH后添加/home/xulei/test/lib
    3) 修改/etc/ld.so.conf文件,把库所在的路径加到文件末尾
    然后sudo ldconfig
    这样,加入的目录下的所有库文件都可见.

    在我的ubuntu下是这样的:
    $ cat /etc/ld.so.conf
    include /etc/ld.so.conf.d/*.conf
    $ ls /etc/ld.so.conf.d/
    i486-linux-gnu.conf  libc.conf
    $ cat /etc/ld.so.conf.d/libc.conf
    # libc default configuration
    /usr/local/lib

    当然由于ld.so.conf包含/etc/ld.so.conf.d/*.conf,你也可以自己新建个文件vi /etc/ld.so.conf.d/myownlib.conf,然后在其中输入/home/xulei/test/lib

    我用的是第二种方法:
    $ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/xulei/test/lib
    $ ./main 
    The string is : hello world
    The string length is : 11(use Strlen)
    The string length is : 10(use StrNlen)


    最后,使用ldd命令查看可执行文件依赖于哪些库,
    $ ldd main
        linux-gate.so.1 =>  (0xb7f43000)
        libstr.so => /home/xulei/test/lib/libstr.so (0xb7f3f000)
        libc.so.6 => /lib/tls/i686/cmov/libc.so.6 (0xb7dd9000)
        /lib/ld-linux.so.2 (0xb7f44000)



  • 相关阅读:
    Visual Studio 20年
    cocos2d-x 重力感应 加速器的使用
    大规模高性能站点架构设计思路整理
    MySQL
    drools 的一个小demo
    springboot使用hibernate validator校验
    mybatis JdbcTypeInterceptor
    ColorPic 一套簡單好用的顏色選擇器!
    WebStorm ES6 语法支持设置
    css中单位em和rem
  • 原文地址:https://www.cnblogs.com/ahuo/p/2578172.html
Copyright © 2011-2022 走看看