目录

前言

一、库是个啥?

①最开始的库是用来解决啥问题?

②库的基本构成

③动态库与静态库

二、如何生成库

0、相关知识

①生成静态库

②生成动态库

三、库的使用

①修改环境变量

②拷贝.so文件到系统共享库路径下, 一般指/usr/lib

③ldconfig 配置/etc/ld.so.conf.d/,ldconfig更新(配置文件)



前言

当你勤勤恳恳完成需求后,要交付你的成果时,你突然发现了一个问题,如果直接把源代码给乙方,他就可以直接进入你的代码,然后狠狠的学习再“借鉴”,甚至修改,你的头发的产物就被别人盗取了。这该如何是好?


一、库是个啥?

①最开始的库是用来解决啥问题?

由程序员第一准则:绝不造重复的轮子。我们可以推出了在编程中,一旦一个东西被广泛的应用,甚至成为标配时,就意味着这个东西一定有种不可替代或者使用面广的的功能。

就如“前言”中所说,在用户端的代码如果不隐藏和高程度的封装,都是不行的,对于编写者不能保护其知识产权,对于用户也不能方便的使用。

而“库”这一概念就被引了出来,库的编写者们将各种各样的需求转化为各种函数或对象,在把它们如何使用的接口放入一个.h头文件中,再把这些接口的实现封装在一起,在打包或者加密隐藏其实现的源代码,而这个就是库的基本模型了。

②库的基本构成

在①的最后,我们知道了库的基本实现原理,那如果我们想手动搞一个简单的库呢?

想本质的了解库,我们先来看看编译是如何的。

对于编译的过程想必大家都了然于心,分别是 预处理、编译、汇编、链接,这四部曲每一步都会生产对应的文件。

各步骤对应的gcc 命令(我们平时使用-o命令,是直接将所有步骤合在一起了)

不同步骤时产生的对应文件后缀

从上图我们可以知道,预处理、编译、汇编、链接生成的文件后缀分别是,.i、.s、.o和最后的可执行文件.exe,而库的打包就是在Linking(链接)这一步完成的。

简而言之,库 = .o文件的集合(接口的实现)+ .h接口文件(告诉用户我有那些接口)

③动态库与静态库

在了解库的本质后,后续我们根据库的使用方法和形成方式分为了2种库:动态库(.so)与静态库(.a)

静态库(.a):程序在编译链接的时候把库的代码链接到可执行文件中。程序运行的时候将不再需要静态库。
动态库(.so):程序在运行的时候才去链接动态库的代码,多个程序共享使用库的代码。

特别的:

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

二、如何生成库

为了方便演示以下用Linux命令行的形式做演示。

0、相关知识

库搜索路径

  • 从左到右搜索-L指定的目录。
  • 由环境变量指定的目录 (LIBRARY_PATH)
  • 由系统指定的目录(计算机上的默认库的存放)
    • /usr/lib
    • /usr/local/lib

①生成静态库

[root@localhost linux]# ls
add.c add.h main.c sub.c sub.h
[root@localhost linux]# gcc -c add.c -o add.o
[root@localhost linux]# gcc -c sub.c -o sub.o
生成静态库
[root@localhost linux]# ar -rc libmymath.a add.o sub.o
ar是gnu归档工具,rc表示(replace and create)
查看静态库中的目录列表
[root@localhost linux]# ar -tv libmymath.a
rw-r--r-- 0/0 1240 Sep 15 16:53 2017 add.o
rw-r--r-- 0/0 1240 Sep 15 16:53 2017 sub.o
t:列出静态库中的文件
v:verbose 详细信息
[root@localhost linux]# gcc main.c -L. -lmymath
-L 指定库路径
-l 指定库名
测试目标文件生成后,静态库删掉,程序照样可以运行。

其中libmymath.a即是我们依赖add.o和sub.o形成的静态库了。

②生成动态库

动态库不同于静态库,该库在使用时还需要OS去参与外部的链接,来实现共享,所以我们除了把相关的.o文件打包以外,还需要给其加一个共享的格式,又因为动态库的内部查找是偏移量的方式,所以还要加一个与位置无关码。

  • shared: 表示生成共享库格式
  • fPIC:产生位置无关码(position independent code)
  • 库名规则:libxxx.so(生成动态库命令时,必须要前面的lib和后面的.so)
[root@localhost linux]# gcc -fPIC -c sub.c add.c [root@localhost linux]# gcc -shared -o libmymath.so*.o
[root@localhost linux]# ls add.c add.h add.o libmymath.so main.c sub.c sub.h sub.o

三、库的使用

由于静态库是直接在编译链接的时候把库的代码链接到可执行文件中。所以直接拷贝库到系统共享库路径下即可(一般指/usr/lib),程序运行的时候将不再需要静态库,即可直接使用。

但是静态库由于编译链接时不把库的代码链接到可执行文件中,而是在运行时,由操作系统从磁盘上的该动态库中复制到内存中(动态链接),所以除了我们在生成动态库告诉可执行文件库的存在,还需要告诉操作系统库的存在与路径

而告诉操作系统主要分为3个方式

①修改环境变量

在环境变量中,有着与外部库的路径这一变量(LD_LIBRARY_PATH)。

[root@localhost linux]# export LD_LIBRARY_PATH=.

不过默认的为了环境变量的纯净,每一次启动环境变量都会重写,这就导致了我们的第三方库每一次启动机器后都要改(当然也可以修改环境变量的配置去实现永久修改,不过就跟麻烦了)。

②拷贝.so文件到系统共享库路径下, 一般指/usr/lib

和静态库的使用一样,也是拷贝到这个路径下。

③ldconfig 配置/etc/ld.so.conf.d/,ldconfig更新(配置文件)

直接写入库的对应路径即可

[root@localhost linux]# cat /etc/ld.so.conf.d/bit.conf
/root/tools/linux
[root@localhost linux]# ldconfig

特别的:这些库是用来支持项目的相关接口,所以库的配置其实也就是我们熟悉的“安装”的一个重要部分,将相应的库拷贝到系统的相应目录。

库到底是个啥?为啥要链接,链接库的本质又是个啥?相关推荐

  1. linux 编译查看链接库详情,Linux环境下的编译,链接与库的使用

    链接参数控制 链接器中提供了-dn -dy 参数来控制使用的是动态库还是静态库,-dn表示后面使用的是静态库,-dy表示使用的是动态库 例: g++ -Lpath -Wl,-dn -lx -Wl,-d ...

  2. GCC 连接器、链接标准库 gcc -l、链接手动创建库(指定目录的库 gcc -L)

    1. 链接器 链接器把多个二进制的目标文件(object file)链接成一个单独的可执行文件. 在链接过程中,它必须把符号(变量名.函数名等一些列标识符)用对应的数据的内存地址(变量地址.函数地址等 ...

  3. 因链接静态库先后顺序不正确,引起符号定义找不到

    问题 项目中需要链接多个静态库,在编译的时候报错如下 sdi_io.cpp:(.text._ZN13sdi_H264EncIO7DataPopEPm+0x30):对'H264ENC_StatusGet ...

  4. Keil5.15使用GCC编译器链接.a库文件

    我们知道,当使用第三方的代码时,人家有可能会扔个Lib文件给你.这时候,别人仅仅要提供header文件给你,则你就能够通过Lib文件及header的函数声明,对Lib中的函数进行调用.在Keil中假设 ...

  5. 链接静态库时__imp_前缀错误

    visual studio 中链接静态库, 出现找不到 __imp_函数名 的错误, extern "C"也增加了 找到一段 Logically, the next questio ...

  6. linux 静态编译 glibc,GCC静态链接glibc库

    如果你的编译环境是高版本的glibc库,而运行程序的环境(机器)安装的glibc是低版本的话,在运行程序的时候,就会告诉你 cannot find GLIBC_2.14 类似这样的错误,上面的2.14 ...

  7. UE4链接第三方库(lib和dll)

    摘要: 写这个文章主要是被UE官方的wiki和answerhub误导了很久,这本来是一个很常见和基本的问题,但是无论是官方的wiki或者是论坛上的提问都十分散乱并且充斥各种错误,因此记录下这个在开发中 ...

  8. 【OpenGL】八、初始化 OpenGL 渲染环境 ( 导入 OpenGL 头文件 | 链接 OpenGL 库 | 将窗口设置为 OpenGL 窗口 | 设置像素格式描述符 | 渲染绘制 ) ★

    文章目录 一.导入 OpenGL 的两个头文件 二.链接 OpenGL 库 三.将 Windows 桌面窗口改成 OpenGL 窗口 四.获取窗口设备 五.设置像素格式描述符 六.设置像素格式 七.创 ...

  9. 【Android NDK 开发】Android Studio 使用 CMake 导入动态库 ( 构建脚本路径配置 | 指定动态库查找路径 | 链接动态库 )

    文章目录 I . CMake 引入动态库与静态库区别 II . Android Studio 中 CMake 引入动态库流程 III . 指定动态库查找路径 IV . 链接函数库 V . 完整代码示例 ...

最新文章

  1. python -- 青少年如何使用 Python 开始游戏开发
  2. 华为电视测试软件,华为智慧屏电视安装第三方软件,简单实测可行攻略
  3. IOS第二天多线程-04简化单例模式
  4. vue node --- 前后端联系的知识梳理
  5. 工业机器人工具中心点标定的意义_如何理解工业机器人的工具中心点
  6. php判断数组中的键是否是某个字符串,php判断数组中是否存在指定键(key)的方法...
  7. 我的世界暮色森林java下载_我的世界暮色森林mod1.7.2下载-暮色森林整合包下载...
  8. android 通过短信找回密码,我的android手机短信被我加密了,忘记密码了,在不刷机恢复出厂设置的情况下如何解决?急急急!!!!!...
  9. int long long 的取值范围
  10. Linux电源管理-Linux Regulator Framework代码分析
  11. 产品经理,没有那么牛逼
  12. PS魔棒工具的使用方法
  13. 你们要的日文AI实时字幕来了,谷歌浏览器VS小白浏览器AI大比拼
  14. asdfasdfasdf
  15. C语言 四种不同方法来判断闰年
  16. Ubuntu16.04 终端命令行 文件重命名
  17. Assigned 函数
  18. 用 Delphi 学设计模式 之 简单工厂篇- -
  19. 应届毕业生注意了,这些典型的学生思维正在阻碍你的职业发展
  20. 《RabbitMQ》什么是死信队列

热门文章

  1. [电路/定理] BUCK两级滤波器电路的心得
  2. 【轻松一刻】Giriboy、Heize《We don't talk together》MV
  3. ubuntu下使用ASUS Xtion PRO
  4. 男士如何提高个人形象
  5. ModuleNotFoundError: No module named ‘d2l’
  6. 实施ERP系统常见的误区
  7. Java对GIF的简单删帧操作
  8. [乐意黎]Windows 里的环境变量以及%USERPROFILE%等变量设置
  9. 对超宽输入范围DC/DC转换器的需求
  10. 统计学习方法第十章隐马尔可夫模型