【Linux操作系统】动态库,静态库的制作和使用,软链接、硬链接简介


秃头侠们好呀,今天来说 软硬连接,动静态库

软硬链接

咋创建一个软链接?

ln -s log.txt log.s 这个意思就是让log.s->log.txt

在这里插入图片描述

unlink log.s删除软链接关系

软链接相当于Windows的快捷方式,比如在linux中有一个执行程序比较深,需要./xxx/xxx/xx/....才能运行,我就可以使用mytest->test,然后通过./mytest执行test

软链接文件具有独立的inode,所以软链接是一个独立的文件,只是它通过数据中保存的源文件路径,访问源文件,源文件被删除,则无法再访问。

咋创建一个软链接?

ln test.c hard 这就是硬链接

在这里插入图片描述
在这里插入图片描述
我们发现硬链接的inode和源文件的相同。
所以硬链接本质不是一个独立的文件,而是一个文件名和inode编号的映射关系。

创建硬链接做了什么?
本质是在特定目录下,填写一对文件名与inode的映射关系。
在这里插入图片描述我们来说一下这个数是啥玩意
在这里插入图片描述这个表示该文件对应的硬链接数(有几个文件名指向我),现在test有自己还有hard所以这个数为2。
这个数在inode的结构体内(引用计数)。

在这里插入图片描述为什么创建目录,它的默认硬链接数为2?
因为该目录里还有一个隐藏文件.也是指向当前目录的,如果在该目录再创建一个目录,则硬链接数变为3,因为里面的目录里还有一个..指向上级目录。

文件的三个时间

在这里插入图片描述
Access:
文件最近被访问的时间。
(但文件最经常被访问,所以这个时间要经常被改,那么OS会很慢,所以在较新的Linux内核中,Access时间不会立即更新,而是在一定的时间间隔,OS才会自动更新)。
Modify:
最近一次修改文件内容的时间(修改文件内容,很有可能更改文件的大小,那文件的属性就也变了,所以经常Modify时间改变,change时间也跟着变了)。
Change:
最近一次修改文件属性的时间。

所以现在我们知道我们Makefile中,它怎么知道你test.c是否是新修改的?就是通过test.c与test比较,如果test.c的Modify时间比test新,说明test.c被新修改了,否则就不准你make了,而make clean可以一直执行,那是因为让其不关心时间,直接执行就行了。
在这里插入图片描述当我们touch 一个存在的文件,那么三个时间都会改变,那你也就可以再make了。

总结一下:
Makefile和gcc会根据时间问题,来判断源文件和可执行程序谁更新,从而指导系统哪些源文件需要重新编译。

动静态库

静态库:是指编译链接时,把库文件的代码全部加入到可执行文件中,因此生成的文件比较大,但在运行时也就不再需要库文件了。其后缀名一般为“.a”。

动态库:与之相反,在编译链接时并没有把库文件的代码加入到可执行文件中,而是在程序执行时由运行时链接文件加载库,这样可以节省系统的开销。动态库一般后缀名为“.so”。

ldd test 显示可执行程序依赖的库
在这里插入图片描述Linux中一般分为:静态库 动态库

静态库:库文件是以.a作为后缀。
动态库:库文件是以.so作为后缀。
(库文件也是文件,就是一个正常的磁盘文件)

库文件的命名:libxxx.so libxxx.a

库的真实名字:去掉lib前缀,去掉.a- .so-(包含)的后缀剩下的就是库的名字。

c++的源文件后缀有.cc .cpp .cxx

如果想静态编译:
gcc -o test test.c -static
静态编译的体积较大
file test
在这里插入图片描述

制作静态库

库本身是二进制文件,那我们如何得知,一个库给我们提供了什么方法呢?

所以一套完整的库包含:
库文件本身+头文件+说明文档
(头文件是文本的,会说明库中暴露出来的方法和基本使用)。

我们在写C/C++代码时,为何要.h放声明,.cpp放实现?
:因为我们要制作库,方便设计,私密和方便维护。

如果我们想把我们实现的方法卖给别人用:
第一种:源代码+头文件。
第二种:只给你提供.o(二进制)文件,可以让你链接,将所有.o打包就是静态库+头文件。

现在要开始创建静态库了!
我们先在Static_lib目录下创建sum.h sum.c sub.h sub.c文件,分别是加法的定义,加法实现,减法定义,减法实现。

现在创建Makefile
在这里插入图片描述在这里插入图片描述

现在我们就已经制作出一个静态库libmymath.a
并且把静态库和头文件打包到output文件中。

静态库的使用

我们把这个output文件拷贝到目标目录下,比如这个目录名是friend,则该目录下,有output和你朋友的可执行程序test.c

在这里插入图片描述此时静态库的使用也就完成了。

但是我们之前写的代码也用库了,为什么就没有指明选项呢?

因为之前的库就在默认路径下/lib64 /usr/lib64…编译器是能识别这些路径的,我们也可以把头文件和库文件写到默认路径,但不建议。

上面的过程也就是一般软件的安装过程。

所以总结一下:
静态库的使用就是:我们给别人交付的其实就是一个库文件(二进制)+一套头文件。

制作动态库

同样我们先在Dynamic_lib目录下创建sum.h sum.c sub.h sub.c文件,分别是加法的定义,加法实现,减法定义,减法实现。

现在创建Makefile
在这里插入图片描述在这里插入图片描述
然后把lib打包好的动态库拷贝到你friend目录下。
在这里插入图片描述

动态库的使用

在这里插入图片描述编译链接跟静态库一样。

但是我们发现,编译正常,但是./mytest为什么无法运行!?
因为:
在这里插入图片描述./mytest ->加载器,所以需要在运行的时候,进一步告诉系统我们的库在哪里!
怎么办?

方法一:

LD_LIBRARY_PATH ->指明程序启动后,库的搜索路径。
进入我们刚才打包好的的lib,然后把当前路径加入到环境变量中。

export LD_LIBRARY_PATH=/home/zhoukeren/Dynamic_lib/friend/lib

在这里插入图片描述

这样就解决了。
当然这个方法是临时的,当我们退出终端,再看一下:
echo $ LD_LIBRARY_PATH刚才加的路径就没了,但这个方法比较推荐。

方法二:

永久添加(到配置文件)不推荐。

/root
cd /etc/ld.so.conf.d/
touch zkr.conf
vim zkr.conf

在这里把刚才那个lib路径添加进来,这样就永久配置了。

总结一下:
我们一直都在直接或间接使用库(C/C++)
如何使用?拿别人的库和头文件,加入到自己的项目中。

如何制作:所有源代码,都要先被编译成.o(可重定向目标文件)
1、先把自己的所有源文件编译成.o
2、制作动静态库的本质:就是将所有的.o打包,使用ar -rc ; gcc -shared
3、交付:头文件+.a或者.so文件

编译器默认使用动态链接,如果想用静态,就手动加-static

为什么我们之前所写的所有代码都没有报错呢?
默认是使用动态链接,而我们一定有动态库,因为系统中有很多命令是用C写的,而且是动态链接的。

  • gcc -shared -o libmytest.so test.o生成动态库。
  • ar -rc libmytest.a test.o 生成静态库。
  • 库文件不能有main()函数,因为库文件会被其他主程序使用,因此包含main()会造成冲突。
  • gcc -o test test.c -I./lib -L./lib -l mytest

动态库的优点

共享、开发模式好、减少页面交换
动态库被加载在内存中,可以供多个使用库的程序共享映射到自己的虚拟地址空间去使用,因此可以减少页面交换以及降低内存中代码冗余,并且因为与源程序模块分离,因此开发模式比较好。


⭐感谢阅读,我们下期再见
如有错 欢迎提出一起交流

  • 7
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 9
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

周周汪

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值