linux编程lib的使用

摘要:
具体给一个例子,先看一下工程的目录结构:$ls-RF.:lib/main.cMakefile./lib:Makefile.aMakefile.sostring.hstrlen.cstrnlen.c在工程主目录下有main.c主控程序,Makefile文件和lib目录lib目录下有string.h头文件,strlen.c和strnlen.c,这三个文件里的函数就是我们想生成的库函数Makefile.a生成静态链接库的makefile文件Makefile.so生成动态链接库的makefile文件好,让我们看一看这些文件的具体内容:头文件string.h,声明相关函数原形$catlib/string.hintStrlen;intStrNlen;strlen.c:函数Strlen的实现,获取给定字符串的长度$catlib/strlen.c#include#includeintStrlen{unsignedlongulLength;assert(NULL!

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

静态链接库(一般命名为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

intStrlen(char*pStr);
intStrNlen(char*pStr,unsignedlongulMaxLen);



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

#include<stdio.h>
#include<assert.h>
intStrlen(char*pStr)
{
unsignedlongulLength;
assert(NULL!=pStr);

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



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

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


这三个文件是在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"//静态库对应函数的头文件


intmain(intargc,char*argv[])
{
charstr[]={"hello world"};
unsignedlongulLength=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);

return0;
}



总控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)



免责声明:文章转载自《linux编程lib的使用》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇使用阿里云私有docker镜像(个人版)JavaScript的三种代码书写格式下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

Linux系统挂载未分配硬盘空间

先查看未挂载之前的磁盘使用情况 发现磁盘使用率已经达到了96%,迫切需要扩容 查看分区情况fdisk –l 首先确保有可分配的磁盘空间 发现/dev/vda下有400多个G 的空间 所以将/dev/vda下的空间划分给/dev/mapper/centos-root ,即 / 目录 下面,我们要开始增加分区的操作了 1.首先如下命令: fdisk /d...

Android项目目录结构模板以及简单说明

1) src  文件   编写java代码的文件目录,遵循java的命名规范、分包 2) gen  文件      包含了android的资源文件的标识符,是不需要程序员维护,是自动添加的 3) assets 文件  源生资源文件;保存应用的资源文件,例如:音频文件、视频文件、不经常被用户修改的文件 4) bin 文件  包含编译生成apk的应用程序xx...

Linux 内存工作机制

内存工作的概述 Linux 内核给每个进程都提供了一个独立的虚拟地址空间,并且这个地址空间是连续的。这样,进程就可以很方便地访问内存,更确切地说是访问虚拟内存。 虚拟地址空间的内部又被分为内核空间和用户空间两部分,不同字长(也就是单个 CPU 指令可以处理数据的最大长度)的处理器,地址空间的范围也不同。比如最常见的 32 位和 64 位系统 通过这里可以...

linux命令集合

查找当前路径文件内容: find ./ -name "*" | xargs grep "kaka" 查找文件位置: locate ** 查看系统磁盘空间: df -h 查看某目录占用空间: du -h ./ 查看某文件夹内占用磁盘空间: du -sh * 查看指定文件夹占用磁盘空间:du -sh /company 查看文件夹内文件的个数: find ./...

自己动手设计并实现一个linux嵌入式UI框架(设计)

  看了“自己动手设计并实现一个linux嵌入式UI框架”显然没有尽兴,因为还没有看到庐山真面目,那我今天继续,先来说说,我用到了哪些知识背景。如:C语言基础知识,尤其是指针、函数指针、内存分布,linux 基础知识、如消息队列、framebuffer、多线程、多线程同步、等,数据结构、算法(如链表、队列等),window .netframework 框架...

YII框架的使用

YII框架的使用 spit: 吐痰,吐口水, 过去式: spat spat: 本身也可以作为一个单词, 意思是: “小打小闹”“小的吵闹”“小争吵” list函数,“列表”, 表示将数组中 对应的 元素值 相应的赋值给 多个变量... explode和implode是在数组和字符串之间转换, 转换的分隔符不能为空: 如果delimiter为空, 则 会...