Linux静态库和动态库学习总结

一、废话

之前由于工作需要,要封装一个Linux加密解密转换的动态库,这个之前只做过Windows下面的,Linux下面还真没有做过,之后做了整一个晚上才算做好,不过其中也学到了不少东西,包括Linux下的动态库和静态库,MakeFile等等。之前就已经写了一个练习,之后怕又忘了,总结一下备忘,以后也好查。

很大部分内容都是收集的一些东西还有自己学习的体会,有什么错误或者问题请直接提出。

二、关于库的问题

1.库的原则

现实中每个程序都要依赖很多基础的底层库,不可能每个人的代码都从零开始。尽量不重复做别人已经做过的事,就是尽量充分利用别人的劳动成果。就是“站在巨人的肩膀上”做事情。

2.库的种类

根据链接时期的不同,库又有:静态库和共享库(动态库)

二者的不同点在于代码被载入的时刻不同

静态库的代码在编译过程中已经被载入可执行程序,因此体积较大

共享库的代码是在可执行程序运行时才载入内存的,在编译过程中仅简单的引用,因此代码体积较小。

3.静态库和动态库的比较

接静态库其实从某种意义上来说只不过它操作的对象是目标代码而不是源码而已。因为静态库被链接后库就直接嵌入可执行文件中了,这样就带来了两个问题。

(1)首先就是系统空间被浪费了。这是显而易见的,想象一下,如果多个程序链接了同一个库,则每一个生成的可执行文件就都会有一个库的副本,必然会浪费系统空间。

(2)再者,一旦发现了库中有bug,挽救起来就比较麻烦了。必须一一把链接该库的程序找出来,然后重新编译。

而动态库的出现正弥补了静态库的以上弊端。因为动态库是在程序运行时被链接的,所以磁盘上只须保留一份副本,因此节约了磁盘空间。如果发现了bug或要升级也很简单,只要用新的库把原来的替换掉就行了。

但是静态库也有自己的优点:

编译后的执行程序不需要外部的函数库支持,因为所有使用的函数都已经被编译进去了。

静态库的名字一般是libxxx.a(Linux)

动态库的名字一般是libxxx.so (Linux),有时候也是 libxxx.so.major.minor,xxxx是该lib的名称,major是主版本号, minor是副版本号

linux系统有几个重要的目录存放相应的函数库,如/lib /usr/lib

4.如何判断一个程序有没有链接动态库

(1)file命令

file程序是用来判断文件类型的,啥文件一看都清楚明了。

(2)ldd命令

看动态库,如果目标程序没有链接动态库,则打印“not a dynamic executable” (不是动态可执行文件)

Linux静态库和动态库学习总结 - 熊哥 - 熊哥

<file :run和run_dyn都是可运行文件,action.h上一个ASCII C++文件>

<ldd: run_dyn 使用了共享库,action.o是不动态可执行文件>

 

5.linux下库文件是如何产生的

(1)静态库

静态库的后缀是.a,它的产生分两步

Step 1.由源文件编译生成一堆.o,每个.o里都包含这个编译单元的符号表

Step 2.ar命令将很多.o转换成.a,成文静态库

(2)动态库

动态库的后缀是.so,它由gcc加特定参数编译产生。

三、我的学习例子

1.要用到的工具

g++/gcc

ar

gcc常用参数

-L 加载库文件路径

-l 指明库文件名字

-fPIC 达到动态链接的目的,还有一个什么要注意的,忘了

-I dir选项的功能,在头文件的搜索路径列表中添加 dir 目录

2.我的文件

(1)doThing

//dosomething.h

  1: #ifndef DOSOMETHING_H 
  2: #define DOSOMETHING_H 
  3:  
  4: #include <string> 
  5:  
  6: void doThing(const std::string& strThing); 
  7:  
  8: #endif // DOSOMETHING_H 
  9: 

//dosomething.cpp

  1: #include "dosomething.h" 
  2: #include<iostream> 
  3:  
  4: void doThing(const std::string& strThing) 
  5: { 
  6:   std::cout << "start do thing :" << strThing << std::endl; 
  7: } 
  8: 

(2)Action类,使用doThing函数

//action.h

  1: #ifndef ACTION_H 
  2: #define ACTION_H 
  3: #include<string> 
  4:  
  5: using namespace std; 
  6:  
  7: class Action 
  8: { 
  9:   public: 
 10:     void setAction(const string& strAction); 
 11:     void doAction(void); 
 12:      
 13:   private: 
 14:     string mstrAction; 
 15: }; 
 16:  
 17: #endif // ACTION_H 
 18: 

//action.cpp

  1: #include "action.h" 
  2: #include "dosomething.h" 
  3:  
  4: void Action::setAction(const string& strAction) 
  5: { 
  6:   mstrAction = strAction; 
  7: } 
  8:  
  9: void Action::doAction(void ) 
 10: { 
 11:   doThing(mstrAction); 
 12: } 
 13: 

(3)主文件

//main.cpp

  1: #include <iostream> 
  2: #include "action.h" 
  3:  
  4: int main(int argc, char **argv) 
  5: { 
  6:      
  7:   Action action; 
  8:   action.setAction("say hello!"); 
  9:   action.doAction(); 
 10:    
 11:   return 0; 
 12: } 
 13: 

 

linux下生成写库文件代码好像更容易些,不用写Windows下面那样的在头文件还要要写DLL导出,显得很干净。

3.使用静态库的方法

基本命令:

g++ –c –o –L –l -I

ar cr 打包

Linux静态库和动态库学习总结 - 熊哥 - 熊哥

最后生成了run,可以直接执行成功。

4.使用动态库

基本命令:

g++ –c –o –shared –fPIC –L –l –I

生成so时加 –shared –fPIC

Linux静态库和动态库学习总结 - 熊哥 - 熊哥

我在生成后立即执行有错误了。

原因:因为在动态函数库使用时,会查找/usr/lib、/lib目录下的动态函数库,而此时我们生成的库不在里边。

这个时候有好几种方法可以让他成功运行:

(1)最直接最简单的方法就是把so拉到/usr/lib或/lib中去,但这好像有点污染环境吧?

(2)export LD_LIBRARY_PATH=$(pwd)

(3)可以在/etc/ld.so.conf文件里加入我们生成的库的目录,然后/sbin/ldconfig

关于/etc/ld.so.conf

/etc/ld.so.conf里面存放的是链接器和加载器搜索共享库时要检查的目录,默认是从/usr/lib /lib中读取的,所以想要顺利运行,我们也可以把我们库的目录加入到这个文件中并执行/sbin/ldconfig 。

关于/etc/ld.so.cache

/etc/ld.so.cache里面保存了常用的动态函数库,且会先把他们加载到内存中,因为内存的访问速度远远大于硬盘的访问速度,这样可以提高软件加载动态函数库的速度了。

使用了第(2)种方法解决问题

Linux静态库和动态库学习总结 - 熊哥 - 熊哥

四、其它涉及到的东西

(1)dlopen方法的动态库显式调用

(2)gcc的各个参数

(3)makefile的编写

五、感谢

学习过程中参考了好多其它文章,由于之前存的TXT参考,无法查找出处给出链接,在这里谢谢作者,这里仅供本人学习。

您可以对本文随意转载修改或使用,但请保持正确性,不要误导他人。

本文出处:http://pppboy.blog.163.com/blog/static/302037962011112104720934/

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/352344.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java Date Nuances的痛苦提醒

这些天&#xff0c;我不再需要使用java.util.Date了&#xff0c;但是最近选择这样做&#xff0c;这让我想起了使用与Java Date关联的API的痛苦 。 在这篇文章中&#xff0c;我看了弃用的参数化Date构造函数的一些令人惊讶的API期望&#xff0c;该构造函数接受六个整数 。 在20…

python 与别的程序通信_《Python》进程之间的通信(IPC)、进程之间的数据共享、进程池...

一、进程间通信---队列和管道&#xff08;multiprocess.Queue、multiprocess.Pipe&#xff09; 进程间通信&#xff1a;IPC&#xff08;inter-Process Communication&#xff09; 1、队列 概念介绍&#xff1a; 创建共享的进程队列&#xff0c;Queue是多进程的安全的队列&#…

Matlab里evalin和assignin的用法

原文地址&#xff1a;Matlab里evalin和assignin的用法作者&#xff1a;了凡春秋assignin与evalin MATLAB通常的基本工作空间是base空间。MATLAB在程序运行过程中&#xff0c;将为每个函数分配它自己的函数工作空间&#xff08;从基本空间中分割出的一块&#xff0c; 以函数…

判断一个程序员水平高低的标准?

a.结果导向 胜者为王&#xff0c;败者为寇。也可以理解为做过什么NB的项目&#xff0c;带来了多少价值。b.竞赛比武 在同一平台下&#xff0c;大家八仙过海各显神通。c.广度和深度 在平时工作或交谈中&#xff0c;逼格最高者被大家膜拜。d.熟练度 …

git编辑器选哪个_[Git]Git创建和修改代码库

有了上一篇的简易Git使用指南&#xff0c;接下来我们就可以创建自己的代码库了创建代码库1.把文件夹变成git文件夹git init 这样子就这里面的内容就可以git了2.把要git的文件放入暂存区 git有三个空间: Working Directory工作区&#xff0c;Staging Area暂存区&#xff0c;Repo…

Q 语言初学者系列:(1)开门篇

声明&#xff1a;本系列文章全部参考自官方教程&#xff0c;由于缺乏中文资料而且本人E文实在太菜&#xff0c;对于E文较好的朋友可以直接通过下面的链接访问官方网站提供的教程&#xff0c; 欢迎大家一起学习讨论。 hhttps://code.kx.com/trac/wiki/QforMortals2/contents 用户…

Java 将数据写入磁盘并读取磁盘上的文件

package test; import java.io.BufferedReader;import java.io.FileReader;import java.io.FileWriter;import java.util.ArrayList;import java.util.List; public class test { public static void main(String[] args) { //创建集合 List<String> listnew ArrayList&l…

simulink怎么生成vxworks的执行程序_Matlab/Simulink基础了解(五):基础Simulink模型搭建及Embedded基础使用...

为了方便大家阅读&#xff0c;从这章开始在章节名中添加该章节要讲的主要的东西。本章给大家讲一个最简单的Simulink模型&#xff1a;在处理应用逻辑时常常会判断车速信号来得到车是否静止&#xff0c;如果车已经跑起来了&#xff0c;很多功能都会被禁用&#xff0c;比如诊断&a…

Q 语言初学者系列:(2)基本数据类型

明&#xff1a;本系列文章全部参考自官方教程&#xff0c;由于缺乏中文资料而且本人E文实在太菜&#xff0c;对于E文较好的朋友可以直接通过下面的链接访问官方网站提供的教程&#xff0c; 欢迎大家一起学习讨论。 hhttps://code.kx.com/trac/wiki/QforMortals2/contents 用户名…

Megacli恢复RAID0磁盘数据

今天干了一件蠢事&#xff0c;距离删库跑路&#xff0c;只差一步。把一块RAID0的磁盘给拔掉了,拔掉之后发现这是一块数据盘&#xff0c;幸好这个数据库是一台备库。赶紧动手恢复&#xff0c;以下是恢复的过程。 首先把拔下来的盘插回去&#xff0c;通过Megacli查看状态是这样的…

内核堆栈 用户堆栈_堆栈痕迹从何而来?

内核堆栈 用户堆栈我相信&#xff0c;阅读和理解堆栈跟踪是每个程序员都必须具备的一项基本技能&#xff0c;以便有效地解决每种JVM语言的问题&#xff08;另请参阅&#xff1a; 过滤日志中无关的堆栈跟踪行和首先记录引起根的异常 &#xff09;。 那么我们可以从一个小测验开始…

Java中使用log4j记录日志

在项目开发中&#xff0c;记录错误日志是一个很有必要功能。一是方便调试&#xff1b;二是便于发现系统运行过程中的错误&#xff1b;三是存储业务数据&#xff0c;便于后期分析&#xff1b; 在java中&#xff0c;记录日志&#xff0c;有很多种方式。 比如&#xff0c;自己实…

python如何输出两列数据_如何用python将一列数据分为两列?

引用来自“Ashkandi”的评论[{date: c[:10], time: c[11:]} for c in Col] 引用来自“vx2008”的评论 谢谢回复&#xff0c;这行代码执行完了以后&#xff0c;日期和时间都村到哪里了呢&#xff1f; 我是了一下&#xff0c;调用date&#xff0c;提示没有定义date&#xff0c;请…

Q 语言初学者系列:(3)Lists 初级

声明&#xff1a;本系列文章全部参考自官方教程&#xff0c;由于缺乏中文资料而且本人E文实在太菜&#xff0c;对于E文较好的朋友可以直接通过下面的链接访问官方网站提供的教程&#xff0c; 欢迎大家一起学习讨论。 hhttps://code.kx.com/trac/wiki/QforMortals2/contents 用户…

数据库图书管理建表与修改表

根据调研选定实体及相应属性画出E-R图 ​ 2、将E-R模型转换为对应关系模型&#xff0c;并指出主码和外码 图书book&#xff08;书号&#xff0c;类别&#xff0c;出版社&#xff0c;作者&#xff0c;书名&#xff0c;定价&#xff0c;备注&#xff09;&#xff1b; 读者reade…

如何指南:Apache Drill入门

Apache Drill是一种引擎&#xff0c;可以连接到许多不同的数据源&#xff0c;并为它们提供SQL接口。 它不仅是想跳入任何复杂事物的SQL接口&#xff0c;而且是一个功能强大的接口&#xff0c; 其中包括对许多内置函数和窗口函数的支持。 尽管它可以连接到您仍然可以使用SQL查询…

python3编程入门_在类Unix系统上开始Python3编程入门

>>> s Hello >>> x len(s) >>> print("The length of %s is %d" % (s,x)) The length of Hello is 5 看看《Python基础编程》中对格式化输出的总结&#xff1a; (1). %字符&#xff1a;标记转换说明符的开始 (2). 转换标志&#xff1a;-…

visual studio 调试时提示 已加载“C:\Windows\SysWOW64\ntdll.dll”。无法查找或打开 PDB 文件。

问题描述 “Win32Project3.exe”(Win32): 已加载“D:\software\VS2013\VS2013 文档\Win32Project3\Debug\Win32Project3.exe”。已加载符号。 “Win32Project3.exe”(Win32): 已加载“C:\Windows\SysWOW64\ntdll.dll”。无法查找或打开 PDB 文件。 “Win32Project3.exe”(Wi…

matlab的一个疑问?

把逻辑值放入一个已知矩阵&#xff0c;为啥结果是&#xff1a;真就取矩阵的值&#xff0c;假就不取值&#xff1f; K>> aaaarandi(10,10,2) aaaa 6 3 10 4 6 7 5 2 6 3 8 2 1 2 9 4 2 9 5 5 K>> aaaa9 ans 102 logical array 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 …

如何使用log4j记录日志

【1】从零开始 a). 新建Java Project>>新建package>>新建java类&#xff1b; b). import jar包&#xff08;一个就够&#xff09;&#xff0c;这里我用的是log4j-1.2.14.jar&#xff0c; c). 新建log4j.properties&#xff0c;置于project根目录下&#xff1b; log…