【Linux】 —— 在Linux下创建自己动态库和静态库

我们在学习 Linux编译器gcc/g++ 时也提到了动态库和静态库,但是当时我们只是简单的介绍了一下他们的概念,以及二者的优缺点,今天我们先来简单的回顾一下什么是静态库,什么是动态库,再来学一下怎么打包一个静态库和动态库

动态库和静态库

  • 静态库(.a):程序在编译链接的时候把库的代码链接到可执行文件中。程序运行的时候将不再需要静态库
  • 动态库(.so):程序在运行的时候才去链接动态库的代码,多个程序共享使用库的代码。
  • 一个与动态库链接的可执行文件仅仅包含它用到的函数入口地址的一个表,而不是外部函数所在目标文件的整个机器码
  • 在可执行文件开始运行以前,外部函数的机器码由操作系统从磁盘上的该动态库中复制到内存中,这个过程称为动态链接(dynamic linking)
  • 动态库可以在多个程序间共享,所以动态链接使得可执行文件更小,节省了磁盘空间。操作系统采用虚拟内存机制允许物理内存中的一份动态库被要用到该库的所有进程共用,能够大大节省内存和磁盘空间

库

接下来我们试着来生成一个静态库:

测试程序
 /////////////add.h/////////////////
 #ifndef __ADD_H__
 #define __ADD_H__
 int add(int a, int b);
 #endif // __ADD_H__
 /////////////add.c/////////////////
 #include "add.h"
 int add(int a, int b)
 {
	 return a + b;
 }
 /////////////sub.h/////////////////
 #ifndef __SUB_H__
 #define __SUB_H__
 int sub(int a, int b);
 #endif // __SUB_H__
 /////////////add.c/////////////////
 #include "add.h"
 int sub(int a, int b)
 {
 	return a - b;
 }
 ///////////main.c////////////////
 #include <stdio.h>
 #include "add.h"
 #include "sub.h"

 int main( void )
 {
 	 int a = 10;
 	 int b = 20;
	 printf("add(10, 20)=%d\n", a, b, add(a, b));
  	 a = 100;
 	 b = 20;
	 printf("sub(%d,%d)=%d\n", a, b, sub(a, b));
 }
生成自己的静态库libmymath.a

静态库

来看看怎么用我们自己创建的静态库
  • 首先我们来创建一个other_person的文件夹,在这使用我们自己的静态库
    静态库
  • 接着我们修改一下Makefile
    在这里插入图片描述
  • 我们执行一下output之后将生成的lib库给到other_person
    静态库的使用
  • 现在我们可以开始使用我们自己写的库了
    静态库的使用
  • 如果我们直接创建main函数,使用我们自己的静态库,很明显系统会提示我们找不到我们需要的头文件和库,所以这里我们就需要介绍三个命令了然后加上这三个命令之后我们再来试一下
  • -L 指定库路径
  • -l 指定库名
  • -I 指定头文件路径
    静态库
  • 至此我们就成功创建了一个静态库并且也成功使用了这个静态库,接下来我们来验证一下静态库的属性,一个是依赖静态库生成的可执行文件较大,这个我们等会生成动态库之后来验证,现在我们来把我们的库删掉,看看可执行文件是否可以运行。静态库
  • 这里我们可以看到删除库之后,程序依然能够运行,说明:程序在编译链接的时候把库的代码链接到可执行文件中。程序运行的时候将不再需要静态库

动态库

生成自己的动态库

生成动态库

来用一下自己的动态库

  • 按照之前使用静态库的模式一样使用动态库

  • 此时我们运行一下我们的可执行程序,发现运行不了,报的错误是找不到对应的文件和目录,但是我们事实上已经指定了的库路径和目录了,但是为啥会找不到呢,这就是使用动态库和静态库的区别
    动态库

  • 这里在介绍一个ldd命令,可以查看当前可执行程序所依赖的库:

  • 这里我们可以看到我们虽然可以找到我们库的名字,但是后面却并没有跟路径,其实这里我们要明白,我们make中的路径是告诉编译器的,这里我们明显可执行程序已经生成,编译器的使命也就达成了,这里找不到是系统找不到这个库,所以我们要把我们库的路径导入到系统的默认路径下。在这里插入图片描述

  • 这里我们用LD_LIBRARY_PATH来将我们的路径导入系统默认路径下,在运行可执行程序发现就可以正常运行了。
    在这里插入图片描述

  • 这里我们看依赖动态库的可执行文件没有比静态库的小很多,是因为我们自己创建的库不大,所以即便可执行程序拷贝一份,也不会占用太大的空间,若是库很大,差距就会很明显
    动态库

  • 依赖动态库生成的文件对库依赖很大,我们将库删除可以看到我们的程序就无法运行了。
    在这里插入图片描述

总结

这里我们来总结下今天博客所讲的东西

  • 一就是动静态库的区别以及二者的优缺点
    依赖静态库生成的可执行文件体积大,但是对库的依赖性小,即便库丢失,仍能正常运行
    依赖动态库生成的可执行文件体积小,但是对库依赖性大,一旦库丢失则无法运行
  • 二是如何创建一个自己的静态库并使用自己的静态库
  • 三是如何创建一个自己的动态库并使用自己的动态库
  • 说实话,我们能力有限,应该不存在写库给别人使用的情况,学着如何创建动静态库其实就是为了深入了解一下二者,为以后我们使用他人写的库打下一定的基础。
发布了167 篇原创文章 · 获赞 175 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/chenxiyuehh/article/details/90701745
今日推荐