【Linux系统化学习】动静态库 | 软硬链接

2024-02-20 23:52

本文主要是介绍【Linux系统化学习】动静态库 | 软硬链接,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

硬链接和软链接

硬链接

软链接 

动态库和静态库

静态库

静态库的生成

静态库的使用

将库打包和使用

动态库

动态库的生成

动态库的使用 

库搜索路径


硬链接和软链接

硬链接

上篇文章我们说到真正找到磁盘上的文件并不是文件名,而是inode。其实在Linux中可以让多个文件名对应同一个inode,这样的方式就是硬链接

指令:ln 

总结: 

  • 硬链接不是一个独立的文件 ,就是在指定目录内部的一组映射关系。相当于引用计数;当没有文件名和inode映射时表示该文件被真正的删除。

  • 硬连接的作用是允许一个文件拥有多个有效路径名,这样用户就可以建立硬连接到重要文件,以防止“误删”的功能。

注:硬链接只可以链接文件不可以链接目录;因为引入了对目录的硬连接就有可能在目录中引入循环,在目录遍历的时候系统就会陷入无限循环当中,这样导致无法定位到访问目录。但是我们的Linux系统可以硬链接目录;每个目录文件中含有两个隐藏文件,分别为当前目录和上级目录,当前目录隐藏文件就和当前目录硬链接。

软链接 

硬链接是通过inode引用另外一个文件,软链接是通过名字引用另外一个文件。

指令:ln -s

总结:

软连接是一个独立的文件,有独立的inode;软连接内容时指向目标文件的路径,类似于Windows的快捷方式


动态库和静态库

在之前的文章中我们提到过系统库,当时只是简单的讲解了下静态库和动态库的优缺点;这篇文章我们要从一个库的制作者和使用者来详细介绍第三方库的制作和使用。

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

静态库

我们以一个库的制作者的角度自己编写一个可以实现整数加减的库;就是将实现整数加减的两个函数声明和定义分开,声明放在头文件中,实现放在源文件中。

头文件

  1 #pragma once 2 #include<stdio.h>                                                        3 extern int Add(int,int);
 1 #pragma once 2 #include<stdio.h>                                                        3 extern int Sub(int,int);

源文件 

  1 #include"Add.h"2 int Add(int x,int y)3 {4     return x+y;                                                          5 }
  1 #include"Sub.h"2 int Sub(int x,int y)3 {4     return x-y;                                                          5 }

当我们以库的制作者的身份将库写好后;我们就以普通程序员的身份使用这个库编写简单的程序。

  1 #include"Add.h"2 #include"Sub.h"3 int main()4 {5     int x =10;6     int y=20;7     printf("%d + %d = %d\n",x,y,Add(x,y));8     printf("%d - %d = %d\n",x,y,Sub(x,y));                               9     return 0;10 }

第一种使用方法就是将我们自己编写的源代码和库的源代码一起编译链接形成一个可执行程序即可。

但是这种使用方法我们要拿到库的源代码;再将库的每个源代码和我们的源代码一起预处理、编译、链接形成可执行程序。对于我们这种小库可能没什么影响,对于一些大的库源文件很多,每个源文件都进行这三部操作的话,很是浪费时间。

静态库的生成

对于上面的问题我们可以很好的解决;不是库的源文件浪费时间么,同时作为库的制作者我们也不想将我们的源代码公开,那我们可以将我们的库先编译成为二进制文件(.O)文件,将二进制文件和库使用者的二进制文件进行连接即可形成可执行程序

  makefile1 test:Add.o Sub.o testmain.o2     gcc -o $@ $^3 %.o:%.c4     gcc -c $<  

但是当我们库很大源文件很多时,形成的二进制文件也特别多;要是我们给库使用者二进制文件少给一个呢?

当我们想要这个库时候是不是只需要将我们的源文件编译成.o文件和库文件进行链接即可。因此我们可以将库的源文件编译成.o文件打包交给程序员即可。

    makefile    static-lib=libmymath.a2 $(static-lib):Add.o Sub.o3     ar -rc $@ $^                                                         6 %.o:%.c7     gcc -c $<8 .PHONY:clean9 clean:10     rm -rf *.o test

指令:ar -rc libmymath.a add.o sub.o
ar是gnu归档工具,rc表示(replace and create)

当我们库的源文件很多时,我们可以使用makefile,将我们的源代码自动生成二进制文件,再将我们的二进制文件全部形成我们的静态库。这里我们库的源文件很少,我就直接给大家手动生成。

通过上面的操作我们就可以将库的源文件生成二进制文件,进行生成静态库。

静态库的使用

将生成好的二进制文件和头文件拷贝到,我们的使用者编写的源代码下就可以使用库了。但是我们在使用静态库时还有很多小细节要注意。

将静态库和我们的源文件进行链接时首先要表用链接库的名称,和静态库的路径。其中库的名称是去掉后缀(.a)和lib。

  • -l 静态库的名称   代表我们链接哪一个静态库
  • -L 路径    代表所要链接静态库的所在路径

将库打包和使用

上面只是进行了二进制文件的打包当我们库源文件很多时,头文件也很多;因此我们可以将头文件和二进制文件分开存储在一个目录中打包交给使用的程序员。这里我们就不打包了,我们只将其放在同一个目录中使用。

    static-lib=libmymath.a2 $(static-lib):Add.o Sub.o3     ar -rc $@ $^6 %.o:%.c7     gcc -c $<8 .PHONY:output9 output:10     mkdir -p mymath_lib/include11     mkdir -p mymath_lib/lib 12     cp -f *.h mymath_lib/include13     cp -f *.a mymath_lib/lib14 .PHONY:clean15 clean:16     rm -rf *.o test mymath_lib

但是打包好的头文件和二进制文件在统一目录下,而我们的源文件并不在统一目录下,因此我们在使用的时候还要加上一些选项。

注:头文件的查找在当前目录下或者指定目录下查找,因此我们加上头文件的路径。

-I 头文件路径

 

动态库

动态库的生成

动态库也是将所有的的源文件形成二进制文件文件生成的;但是和动态库的生成方式和使用方式略有差异。 

注意:动态库的生成是使用gcc编译器来完成的,因此比较重要

makefile1 dy-lib=libmymath.so 2 $(dy-lib):Add.o Sub.o3     gcc -shared -o $@ $^4 %.o:%.c5     gcc -fPIC -c $<6 .PHONY:output7 output:8     mkdir -p mymath_lib/include9     mkdir -p mymath_lib/lib 10     cp -f *.h mymath_lib/include11     cp -f *.a mymath_lib/lib12 .PHONY:clean13 clean:14     rm -rf *.o *.so mymath_lib                                
~                                   

  • shared: 表示生成共享库格式
  • fPIC:产生位置无关码(position independent code)
  • 库名规则:libxxx.so

有了上面静态库的生成,静态库的生成我们就不过多赘述,只是生成动态库执行的选项不一样而已。

动态库的使用 

动态库的使用也是有很多的小细节,使用不当也会产生找不到动态库或者找不到头文件的问题。 

就像下面我们直接使用使用静态库的方法使用动态库,系统还是找不到我们的库在哪里。 

 

原因:

静态库是直接和我们的可执行程序链接在一起的,在连接的时候告诉我们的编译器我们库的路径编译器就可以找到。但是对于动态库不是链接在可执行程序中,可执行程序和库必须都加载到内存中,我们告诉了gcc编译器我们的库在哪里,但是操作系统要将我们的库加载到内存中,操作系统却不知道我们的库在哪里,系统默认找不到。因此我们要解决系统找不到我们库的问题。

库搜索路径

方法一:将头文件和库文件安装到系统中 

  • /usr/include
  • /lib64

在我们这两个系统路径下分别存放着库的头文件和二进制文件,我们可以将我们的二进制文件和头文件分别拷贝到上面的系统路径下即可。

方法二:建立一个软链接

在生成可执行程序的目录下建立一个库的软链接即可。

方法三:修改环境变量

LD_LIBRARY_PATH

执行我们的可执行程序系统不仅会在指定的路径下寻找我们的动态库,还会在一个环境变量中寻找。Linux中存在这样一个环境变量记录着动态库的存储路径。我们可以将我们的动态库添加到这一环境变量中即可。

注意

当我们退出我们的云服务器,重新登录后添加的环境变量就将会重置。 

方法四:更改配置文件

Linux下含有一个文件夹其中包含有关动态库加载的配置文件,里面只含有一个路径。我们可以在其目录下创建一个相同格式的空白文件,再将我们库的路径填入其中保存即可。


今天对Linux下动静态库的分享到这就结束了,希望大家读完后有很大的收获,也可以在评论区点评文章中的内容和分享自己的看法;个人主页还有很多精彩的内容。您三连的支持就是我前进的动力,感谢大家的支持!!!  

这篇关于【Linux系统化学习】动静态库 | 软硬链接的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/729951

相关文章

windows和Linux使用命令行计算文件的MD5值

《windows和Linux使用命令行计算文件的MD5值》在Windows和Linux系统中,您可以使用命令行(终端或命令提示符)来计算文件的MD5值,文章介绍了在Windows和Linux/macO... 目录在Windows上:在linux或MACOS上:总结在Windows上:可以使用certuti

Linux之systemV共享内存方式

《Linux之systemV共享内存方式》:本文主要介绍Linux之systemV共享内存方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、工作原理二、系统调用接口1、申请共享内存(一)key的获取(二)共享内存的申请2、将共享内存段连接到进程地址空间3、将

快速修复一个Panic的Linux内核的技巧

《快速修复一个Panic的Linux内核的技巧》Linux系统中运行了不当的mkinitcpio操作导致内核文件不能正常工作,重启的时候,内核启动中止于Panic状态,该怎么解决这个问题呢?下面我们就... 感谢China编程(www.chinasem.cn)网友 鸢一雨音 的投稿写这篇文章是有原因的。为了配置完

Java学习手册之Filter和Listener使用方法

《Java学习手册之Filter和Listener使用方法》:本文主要介绍Java学习手册之Filter和Listener使用方法的相关资料,Filter是一种拦截器,可以在请求到达Servl... 目录一、Filter(过滤器)1. Filter 的工作原理2. Filter 的配置与使用二、Listen

Linux命令之firewalld的用法

《Linux命令之firewalld的用法》:本文主要介绍Linux命令之firewalld的用法,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录linux命令之firewalld1、程序包2、启动firewalld3、配置文件4、firewalld规则定义的九大

Linux之计划任务和调度命令at/cron详解

《Linux之计划任务和调度命令at/cron详解》:本文主要介绍Linux之计划任务和调度命令at/cron的使用,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录linux计划任务和调度命令at/cron一、计划任务二、命令{at}介绍三、命令语法及功能 :at

Linux下如何使用C++获取硬件信息

《Linux下如何使用C++获取硬件信息》这篇文章主要为大家详细介绍了如何使用C++实现获取CPU,主板,磁盘,BIOS信息等硬件信息,文中的示例代码讲解详细,感兴趣的小伙伴可以了解下... 目录方法获取CPU信息:读取"/proc/cpuinfo"文件获取磁盘信息:读取"/proc/diskstats"文

Linux内核参数配置与验证详细指南

《Linux内核参数配置与验证详细指南》在Linux系统运维和性能优化中,内核参数(sysctl)的配置至关重要,本文主要来聊聊如何配置与验证这些Linux内核参数,希望对大家有一定的帮助... 目录1. 引言2. 内核参数的作用3. 如何设置内核参数3.1 临时设置(重启失效)3.2 永久设置(重启仍生效

kali linux 无法登录root的问题及解决方法

《kalilinux无法登录root的问题及解决方法》:本文主要介绍kalilinux无法登录root的问题及解决方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,... 目录kali linux 无法登录root1、问题描述1.1、本地登录root1.2、ssh远程登录root2、

Linux ls命令操作详解

《Linuxls命令操作详解》通过ls命令,我们可以查看指定目录下的文件和子目录,并结合不同的选项获取详细的文件信息,如权限、大小、修改时间等,:本文主要介绍Linuxls命令详解,需要的朋友可... 目录1. 命令简介2. 命令的基本语法和用法2.1 语法格式2.2 使用示例2.2.1 列出当前目录下的文