一、Linux中的链接文件
1.1硬链接及应用场景
ln//创建硬链接
我们再创建一个硬链接生成的文件。
我们可以看到mlink.hard的inode和makefile.c的inode都是一样的,inode一样里面的数据自然也是一样。相当于对make.file进行了一个重命名,所以硬链接一定没有新建文件,因为其没有新建inode,所以硬链接新建的是文件名和源文件的inode建立了个映射关系。
也就变成了有两个文件名和一个inode建立了映射关系。
而权限之后的数字就是硬链接数,硬链接本质上就是在指定目录下,插入新的文件名和目标文件的映射关系,并让inode的引用计数,每次创建一个硬链接就++。
可我们可以发现,我们新建的文件默认硬链接数是1,这个1就是路径下的.
而当我们新创建一个文件夹4.5时会发现硬链接数为2。因为除了自身文件名和inode对应,在此当前目录下包含.文件作为硬链接,链接到自己。
此外可以看到,创建了4.5这个目录后,2024.4目录的硬链接数就变为了3,这是因为首先是2024.4指向inode,然后是目录下的.然后还有刚刚创建的4. 5中的..
这就是我们cd..可以回到上级目录的原因,因为..作为上级目录的硬链接指向其,inode,我们还可以看到2024.4目录下的..硬链接数为9,~目录的硬链接数为9。
所以一个目录下有多少个子目录,可以通过硬链接数-2得到。
注意,Linux中不允许用户给目录建立硬链接,比如在一个目录下建立一个dir硬链接链接到根目录,那我们在寻找查询一个文件的时候查询到dir就会回到根目录形成环路问题,也就是无穷的循环递归现象。除非系统自己建立,只要建立硬链接不管是.还是..都会形成环路问题,而.和..已经被系统做了特殊标识,操作系统会对.和..做特殊处理,而如果让用户自己建立操作系统就无法辨别。
1.2软链接及应用场景
ln -s//建立软链接
mlink.soft本质上是一个文件。
ll -li我们可以看到mlink.soft有自己的inode。
软链接本质就是一个独立的文件,软链接里面放的是目标文件的路径,就类似于windows中的桌面快捷方式。
软链接可以指向比较深的文件路径,直接./直接就可以运行或操作目标文件。
可以看到有很多软链接 。
二、动静态库
2.1什么是动静态库
ldd XXX//查看文件链接哪一个动态库
库被分为两种,动态库(后缀为.so),静态库(后缀为.a)。
一般云服务器,都是默认安装动态库,生成可执行程序时也是默认链接动态库。
我们每次生成的可执行程序,都用到了Linux中的C/C++的动态库。
我们可以通过gcc 文件名 -static 的方式来链接静态库,静态链接的可执行程序的大小是比动态链接的可执行程序是要大很多的。
一般判断一个库的名字都是去掉前缀lib,去掉后缀so.剩下的就是它的名字,比如libc.so.6去掉前后缀就是c,所以这就是我们的c语言的库。
2.2静态库的制作和使用
所以为什么要有库呢?
1.基于已经实现的库可以提高开发效率
2.隐藏源代码
[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 指定库名
测试目标文件生成后,静态库删掉,程序照样可以运行
所以库的本质就是把一堆.o打包形成一个文件,然后通过头文件来调用库。注意,库中不能包含main函数。
这里将mymath.o和mystdio.o打包形成名为libmyc.a的静态库,我们可以直接将头文件和.o文件传输给其他人,别人就可以在main函数中进行包含使用,当然如果直接用gcc编译的话会报错,因为gcc默认使用libc.so.6的库,编译器默认去lib64路径下去找库,此时肯定是找不到的。
需要gcc源文件,然后链接自己构造的库,-l链接文件名,-L .表明库文件在当前路径下。然后可以编译成功。
2.3动态库的制作和使用
gcc -c -FPIC文件名//形成同名的.o
gcc -o -shared libXXX.so XXX.o XXX.o//形成名为XXX的动态库
所以一个编写库的人未来交给别人的
我们也可以通过output将文件创建打包到一个目录下,不同类型的文件打包到不同的子目录下。
之后就可以直接将压缩包mylib.tgz上传转移等操作 ,之后拿到压缩包的人直接进行解压操作就可以拿到文件。
而在直接编译刚刚自己写的第三方库时编译器会进行报错,无法查找到mymath.c。因为编译器在编译时1.默认会到include所在路径下去找2.在当前路径下找,而头文件我们刚刚将其封装在了lib目录下,所以无法查找。
-I就是告诉编译器目标头文件在哪个路径下。
可是这种编译方式及其的繁琐复杂,这时可以采用更好的方式,将include目录和lib目录分别拷贝到include和lib64这样的系统指定的路径中,所以所谓的把库、软件安装到系统中,本质就是将对应的文件,拷贝到系统指定的路径中(一般都是系统)。
像类似与stdio.h等都在include路径下。
所以像节省编写时的繁杂操作,我们可以直接将相关文件拷贝到系统指定的路径下。
但编译形成可执行程序后,./去运行发现依然会报错。
因为对于动态库来说:
编译时的搜索路径为gcc
运行时的库搜索路径为os
两个路径可以一样,但对于自定义的库,需要用户即告诉编译器又告诉操作系统。
如果不想每次都手动去链接使用,有以下四种方法来解决:
1.将自定义库和cp拷贝到系统库(/lib64),既可以支持编译又可以支持运行。
2.使用环境变量
系统程序运行时 ,动态库查找的辅助路径,将不在系统默认搜索路径下的库路径,添加到LD_LIBRARY_PATH中。
3.在系统库下建立软链接
4.通过系统的配置文件路径的方案
推荐第一种和第三种方法,较为方便快捷。
当自定义静态库和动态库都存在且在同一路径下时 ,./运行时优先默认使用动态库。
如果非要静态链接必须使用static选项,如果只能对该库进行静态链接,但是程序不一定整体是静态链接的。
如果只提供动态库,默认只能动态链接,非得静态链接,会发生链接报错。