标题:[Linux] linux 软硬链接与动静态库
个人主页@水墨不写bug
(图片来源于网络)
/*
* _oo0oo_
* o8888888o
* 88" . "88
* (| -_- |)
* 0\ = /0
* ___/`---'\___
* .' \\| |// '.
* / \\||| : |||// \
* / _||||| -:- |||||- \
* | | \\\ - /// | |
* | \_| ''\---/'' |_/ |
* \ .-\__ '-' ___/-. /
* ___'. .' /--.--\ `. .'___
* ."" '< `.___\_<|>_/___.' >' "".
* | | : `- \`.;`\ _ /`;.`/ - ` : | |
* \ \ `_. \_ __\ /__ _/ .-` / /
* =====`-.____`.___ \_____/___.-`___.-'=====
* `=---='
*
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
* 佛祖保佑 永不宕机 永无BUG
*/
目录
正文开始:
(一)软硬链接
(1)见一见软硬链接
在具体讲解软硬链接之前,我们抛弃令人费解的概念不谈,先见一见软硬链接。
场景一:我们在一个项目目录中,编译编写的代码,形成mytest可执行程序:
但是我们想要在当前目录而不是在test_link目录中找到mytest,这就需要一个快捷方式,如何创建一个快捷方式?
场景二:Linux目录默认都会有当前目录和上一级目录,可是为什么呢?
在Linux目录下,我们可以通过指令创建软链接:
建立软链接:
ln -s 目标文件的位置和文件名 建立的软连接的名称
建立硬链接:
ln 目标文件的位置和文件名 建立的软连接的名称
对于场景一,可以在test_link的同级目录中创建一个软链接:
这样,对于建立的软链接的访问,就类似于直接对mytest的访问:
对于场景二,每一个目录中的本目录和上一级目录本质就是一个硬连接。
(2)软硬链接的本质?
软链接:
软链接是一个独立的文件,因为软链接形成的链接有独立的inode number。
硬链接:
硬连接不是一个独立的文件,因为硬链接没有独立的inode number。
软链接的内容是目标文件所对应的路径字符串,类似于windows的快捷方式。
硬连接是文件名和inode number的映射关系,添加硬连接就是在指定目录下,添加一个新的文件名与inode number的映射关系。
(3)软硬链接的应用?
a.软连接
i,链接各种库,linux的各种指令,本质上就是一个个的可执行程序文件,这些指令的运行需要库文件的支持,才能正常运行。
ii,创建快捷方式,可以帮我们快速找到深路径的文件。
b.硬连接
1)任何一个目录,刚开始创建的时候,我们会发现硬连接引用计数为2:
在目录中创建目录,会使其引用计数+1,因为新建的目录中会有指向本目录的硬连接。
于是,可以推导出:
目录内有几个目录,等于其引用计数-2
同时,需要注意,linux中不能给目录建立硬连接,防止系统在查找文件的时候形成路径环绕。
(二)动静态库
接下来的分享以笔记形式进行!
/*
* ::
* :;J7, :, ::;7:
* ,ivYi, , ;LLLFS:
* :iv7Yi :7ri;j5PL
* ,:ivYLvr ,ivrrirrY2X,
* :;[email protected]: :ivu@kexianli.
* :iL7::,:::iiirii:ii;::::,,irvF7rvvLujL7ur
* ri::,:,::i:iiiiiii:i:irrv177JX7rYXqZEkvv17
* ;i:, , ::::iirrririi:i:::iiir2XXvii;L8OGJr71i
* :,, ,,: ,::[email protected]:i:::j1jri7ZBOS7ivv,
* ,::, ::rv77iiiriii:iii:i::,[email protected]
* ,, ,, ,:ir7ir::,:::i;ir:::i:i::rSGGYri712:
* ::: ,v7r:: ::rrv77:, ,, ,:i7rrii:::::, ir7ri7Lri
* , 2OBBOi,iiir;r:: ,irriiii::,, ,iv7Luur:
* ,, i78MBBi,:,:::,:, :7FSL: ,iriii:::i::,,:rLqXv::
* : iuMMP: :,:::,:ii;2GY7OBB0viiii:i:iii:i:::iJqL;::
* , ::::i ,,,,, ::LuBBu BBBBBErii:i:i:i:i:i:i:r77ii
* , : , ,,:::rruBZ1MBBqi, :,,,:::,::::::iiriri:
* , ,,,,::::i: @arqiao. ,:,, ,:::ii;i7:
* :, rjujLYLi ,,:::::,:::::::::,, ,:i,:,,,,,::i:iii
* :: BBBBBBBBB0, ,,::: , ,:::::: , ,,,, ,,:::::::
* i, , ,8BMMBBBBBBi ,,:,, ,,, , , , , , :,::ii::i::
* : iZMOMOMBBM2::::::::::,,,, ,,,,,,:,,,::::i:irr:i:::,
* i ,,:;u0MBMOG1L:::i:::::: ,,,::, ,,, ::::::i:i:iirii:i:i:
* : ,iuUuuXUkFu7i:iii:i:::, :,:,: ::::::::i:i:::::iirr7iiri::
* : :[email protected]:::::, ,:ii:::::::i:::::i::,::::iirrriiiri::,
* : 5BMBBBBBBSr:,::rv2kuii:::iii::,:i:,, , ,,:,:i@petermu.,
* , :r50EZ8MBBBBGOBBBZP7::::i::,:::::,: :,:,::i;rrririiii::
* :jujYY7LS0ujJL7r::,::i::,::::::::::::::iirirrrrrrr:ii:
* ,: :@kevensun.:,:,,,::::i:i:::::,,::::::iir;ii;7v77;ii;i,
* ,,, ,,:,::::::i:iiiii:i::::,, ::::[email protected];7:i,
* , , ,,,:,,::::::::iiiiiiiiii:,:,:::::::::iiir;ri7vL77rrirri::
* :,, , ::::::::i:::i:::i:i::,,,,,:,::i:i:::iir;@Secbone.ii:::
*/
(还是讲解一下比较好,所以还是正常的blog形式)
(1)什么是库?
我们平时使用的各种库,但是这些库到底是怎么运行的?
库本质是语言层面的开发者写好并编译形成的.o 文件(可重定向目标文件),以及头文件。对于头文件,本质上是一个手册,因为我们用户不能直接看懂.o文件(二进制的文件),所以这个.o文件到底有什么作用,我们用户不知道如何使用这个库!!于是需要头文件来解释,头文件为用户提供了库文件的使用方法(比如函数声明,宏定义,类声明等)。
.o文件提供了实现,.h文件提供了说明。
用户只需要补上一个main函数文件,在这个文件中调用头文件提供的方法,然后和 库提供的.o 文件进行链接,最终就可以形成我们自己的可执行程序。
总而言之,所谓库文件,本质就是把多个.o文件打包。目的是提高开发效率。
Linux下的动静态库:
静态库(.a):程序在编译链接的时候把库的代码拷贝到可执行文件中,程序运行的时候将不再需要静态库。
动态库(.so) :程序在运行的时候才去链接动态库的代码,多个程序共享使用库的代码。(动态库删掉后程序无法正常运行) 一个与动态库链接的可执行文件仅仅包含它用到的函数入口地址的一个表,而不是外部函数所在目标文件的整个机器码。 在可执行文件开始运行以前,外部函数的机器码由操作系统从磁盘上的该动态库中复制到内存中,这个过程称为 动态链接(dynamic linking) 。
库的命名规则:
如:libc.so -> c库,去掉前缀lib,去掉后缀.so,.a
动态库的优势:(动态库使用较多,为什么?)
动态库可以在多个程序间共享,所以动态链接使得可执行文件更小,节省了磁盘空间。
操作系统采用虚拟内存机制允许物理内存中的一份动态库被要用到该库的所有进程共用,节省了内存和磁盘空间 ,所以在实际场景中,项目大多使用动态库。(链接库的内存层面具体细节在以后会分享)
(2)如何制作动静态库?
我们实现了add.c add.h sub.c sub.h 并自己添加了main函数,如何生成自己的静态库,并在编译后链接到main文件中?
ddsm@ddsm-alicloud:~/_10_29_blog$ ls
add.c add.h main.c sub.c sub.h
ddsm@ddsm-alicloud:~/_10_29_blog$ gcc -c add.c -o add.o
ddsm@ddsm-alicloud:~/_10_29_blog$ gcc -c sub.c -o sub.o
a,生成静态库
ddsm@ddsm-alicloud:~/_10_29_blog$ ar -rc libmymath.a add.o sub.o
ar是gnu归档工具,rc表示(replace and create)
查看静态库中的目录列表
ddsm@ddsm-alicloud:~/_10_29_blog$ ar -tv libmymath.a
rw-r--r-- 0/0 1240 Oct 15 16:53 2024 add.o
rw-r--r-- 0/0 1240 Oct 15 16:53 2024 sub.o
t:列出静态库中的文件
v:verbose 详细信息
使用静态库
ddsm@ddsm-alicloud:~/_10_29_blog$ gcc main.c -L. -lmymath
-L 指定库路径
-l 指定库名
b,生成动态库
ddsm@ddsm-alicloud:~/_10_29_blog$ gcc -fPIC -c sub.c add.c ddsm@ddsm-alicloud:~/_10_29_blog$ gcc -shared -o libmymath.so*.o ddsm@ddsm-alicloud:~/_10_29_blog$ ls add.c add.h add.o libmymath.so main.c sub.c sub.h sub.o
shared: 表示生成共享库格式
fPIC:产生位置无关码(position independent code)
库名规则:libxxx.so
使用动态库
L:链接库所在的路径.
l:链接动态库,只要库名即可(去掉lib以及版本号)
运行动态库
1、拷贝.so文件到系统共享库路径下, 一般指/usr/lib
2、更改 LD_LIBRARY_PATHddsm@ddsm-alicloud:~/_10_29_blog$ export LD_LIBRARY_PATH=. ddsm@ddsm-alicloud:~/_10_29_blog$ gcc main.c -lmymath ddsm@ddsm-alicloud:~/_10_29_blog$ ./a.out add(10, 20)=30 sub(100, 20)=80
3、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
(3)库的路径搜索
无论是动态库还是静态库,在编译的时候都需要告诉编译器库的位置信息,一旦编译成功,静态链接的程序可以不受库的限制,可以随意使用。
首先需要告诉编译器动态库的位置,才能编译成功。但是这只是第一步。虽然编译成功,但是OS无法找到库,依然是无法正常运行程序的。
如何让操作系统会在如下的目录中查找库:
1)由环境变量指定的目录 (LIBRARY_PATH)
2)由系统指定的目录
/usr/lib
/usr/local/lib
可以通过多种方式让操作系统找到库,根据前文的讲解,你或许已经知道了如何操作,这里给出5种方法:
完~
未经作者同意禁止转载