linux下封装函数库——动态库.so和静态库.a(代码实现及链接方式)

简介: 在linux环境下的链接库分为静态链接库(.a库)和动态链接库(.so库),其作用是把C程序编译好做成一种可执行链接文件,主程序文件调用这些程序的函数接口是可以使用a库或so库,在主程序中只需要include含有库中提供的函数接口声明的头文件即可。所以学会如何将自己的源代码封装成库进行使用很重要

在linux环境下的链接库分为静态链接库(.a库)和动态链接库(.so库),其作用是把C程序编译好做成一种可执行链接文件,主程序文件调用这些程序的函数接口是可以使用a库或so库,在主程序中只需要include含有库中提供的函数接口声明的头文件即可。所以学会如何将自己的源代码封装成库进行使用很重要,接下来就来介绍一下然后进行库的封装:

1、动态链接库的制作:

首先,生成一个简单的函数实现mymax(a,b),将它封装成库来进行举例:

代码如下:


1 int mymax(int a, int b)
  2 {
  3     if(a > b)
  4         return a;
  5     return b;
  6 }

             


这里可以通过gcc命令才生成.so库,也可以编写Makefile生成so库,Makefile如下:

1 CC = gcc
  2 SRCS = mymax.c
  3 OBJS = $(SRCS:.c=.o)
  4 EXEC = libmymax.so//这里要注意生成的库文件开头必须lib开头,后缀.so
  5 start:$(OBJS)
  6         $(CC) -o $(EXEC) $(OBJS) -shared//这表明是一个动态库
  7 .c.o:
  8         $(CC) -o $@ -c $< -fPIC//表示编译函数时没有偏移地址
  9 clean:
 10         rm -rf $(OBJS)



当然也可以直接使用指令:

20180916094638826.png

这里一定要注意so库的前缀必须为lib,然后将.so库链接到主程序main.c中,这里需要注意一下,因为动态库的特性,编译器会到指定的目录去寻找动态库,目录的地址在/etc/ld.so.conf.d/ 目录里的libc.conf文件里,你可以在里面加一行地址表示你so库的位置,更改完conf文件里的内容,记得输入命令行:ldconfig。

你还可以将so库复制到默认的目录下。这里是将so库复制到了默认目录下,生成可执行文件并运行,最后进行编译链接使用Makefile如下:

1 CC = gcc
  2 SRCS = mylib.c
  3 OBJS = $(SRCS:.c=.o)
  4 EXEC = myapp
  5 start:$(OBJS)
  6         $(CC) -o $(EXEC) $(OBJS) -L. -lmymax
  7 .c.o:
  8         $(CC) -o $@ -c $< 
  9 clean:
 10         rm -rf $(OBJS)



这样就生成了可执行程序myapp,

注意:在加载动态链接库的时候,有可能会遇到加载不到的错误,原因在于系

统默认加载的动态链接库路径里没有找到你的动态库,有三种解决方法:

**1.在执行gcc main.c -L. -ltest -o main 前,执行 export **

LD_LIBRARY_PATH=$(pwd)

2.将你so所在的目录写到/etc/ld.so.conf文件里,然后执行ldconfig。

3.将你的so放在/etc/ld.so.conf里的路径位置里。


最后可以通过指令ldd查看执行程序的链接库都有哪些:

20180916095257327.png

静态链接库和动态链接库的区别在于,主程序在运行前,静态链接库的链接固定写入在程序中,而动态链接库则是在每次程序运行再加载链接。

接下来制作静态链接库:

20180916100211500.png

最后使用nm命令可以查看程序依赖的库信息:

20180916100524144.png从中可以找到我们进行链接的静态库信息。


最后,如果对其他一些细节还需要详细了解的话,推荐一个博客,我觉得写得真的很相信,http://www.cnblogs.com/skynet/p/3372855.html


加载动态库需要指定路径的问题

gcc中的rpath参数可以用编译时指定动态库的搜索路径,这样运行时就不需要export LD_LIBRARY_PATH了。

解决方案


  • 方案一

编译时增加参数-Wl,-rpath=’.’


可执行程序运行时会搜索当前工作目录(不是进程所在目录),所以如果在其它目录运行该可执行程序时会提示找不到动态库(同样,如果建立一个软连接ln -s时,也会提示找不到动态库)。


  • 方案二

编译时增加参数-Wl,-z,origin -Wl,-rpath=’$ORIGIN’


O R I G I N 表 示 会 搜 索 进 程 所 在 目 录 ( 同 样 也 可 以 设 置 − r p a t h = ’ ORIGIN表示会搜索进程所在目录(同样也可以设置-rpath=’ORIGIN表示会搜索进程所在目录(同样也可以设置−rpath=’ORIGIN/lib’)。此方案不会出现方案一中软链接找不到动态库的情况。


  • 补充

通常情况下使用第二种方案是比较理想的,但是为了防止提升权限的漏洞,一旦进行了提升权限操作(比如chown root ping ;chmod u+s ping),则ORIGIN的设置会失效,运行可执行程序,会提示找不到动态库,即使使用export LD_LIBRARY_PATH设置了路径也无效。


要解决此问题:


  • 使用绝对路径(此方案不可取,所以没有亲自试验,应该是-rpath时指定绝对路径)
  • 将所依赖的so文件拷贝到操作系统默认会搜索的目录下,比如/lib或者/lib64等目录

查看编译好的动态库或者进程的rpath的方法

linux
readelf -d xxx.lib
solaris
greadelf -d xxx.lib


动态库的搜索路径的顺序

编译目标代码时指定的动态库搜索路径;
环境变量 LD_LIBRARY_PATH 指定的动态库搜索路径;
配置文件 /etc/ld.so.conf 中指定的动态库搜索路径;
默认的动态库搜索路径 /lib ;
默认的动态库搜索路径 /usr/lib


大家共同进步

20180916100944502.jpg

相关文章
|
7天前
|
Linux C++
linux C/C++静态库制作
linux C/C++静态库制作
|
7天前
|
网络协议 Linux 网络安全
远程链接linux
远程链接linux
|
7天前
|
Unix Linux 开发工具
Linux 命令 `ctags`:代码导航的利器
`ctags` 是一款Unix工具,用于生成代码标签,方便在Vim、Emacs等编辑器中快速跳转到函数、变量定义。在Linux上,可通过包管理器安装。使用`ctags -R`生成`tags`文件,然后在Vim中用`Ctrl+]`跳转,`Ctrl+T`返回。Emacs则使用`M-.`和`M-,`。`ctags`可自定义语言映射和排除规则,是提升编程效率的利器。
|
7天前
|
Linux C语言
探索Linux命令c2ph:将C代码转换为PostScript或PDF的奇妙工具
`c2ph`是Linux下的工具,能将C代码转换为PostScript或PDF,便于阅读和分享。通过pretty-print技术美化源代码。安装需从源码编译,使用`c2ph -o &lt;output&gt; &lt;source.c&gt;`生成PostScript文件,再用`ps2pdf`转为PDF。注意它可能不支持复杂格式设置,大型文件处理可能慢,且兼容性有限。适合偶尔需要打印代码副本的情况。
|
7天前
|
Linux vr&ar 开发者
Linux 命令 `ar` 详解:静态库的管理利器
`ar` 命令是 Linux 管理静态库的工具,常用于创建、修改和提取 `.a` 文件。基本语法为 `ar [选项] 目标文件 [成员...]`。常用选项包括:`rcs` 创建(更新)静态库,`t` 列出成员,`x` 提取成员,`d` 删除成员。注意文件顺序、创建索引、备份和跨平台兼容性。学习和掌握 `ar` 命令能提升系统开发效率。
|
8天前
|
Ubuntu JavaScript Linux
linux 命令行下载BT种子和磁力链接 ubuntu linux 命令行下载种子
linux 命令行下载BT种子和磁力链接 ubuntu linux 命令行下载种子
|
15天前
|
Java Linux
Linux下如何定位最耗CPU的JAVA代码
Linux下如何定位最耗CPU的JAVA代码
32 0
|
22天前
|
存储 网络协议 Linux
【Linux 网络】网络基础(一)(局域网、广域网、网络协议、TCP/IP结构模型、网络传输、封装和分用)-- 详解(下)
【Linux 网络】网络基础(一)(局域网、广域网、网络协议、TCP/IP结构模型、网络传输、封装和分用)-- 详解(下)
|
22天前
|
存储 网络协议 安全
【Linux 网络】网络基础(一)(局域网、广域网、网络协议、TCP/IP结构模型、网络传输、封装和分用)-- 详解(上)
【Linux 网络】网络基础(一)(局域网、广域网、网络协议、TCP/IP结构模型、网络传输、封装和分用)-- 详解(上)
|
22天前
|
安全 Linux vr&ar
【Linux 系统】基础 IO(动静态库)-- 详解
【Linux 系统】基础 IO(动静态库)-- 详解