一、软硬链接内容与特点
1、创建软硬链接
软链接:ln -s 目标文件 软链接名
硬链接:ln 目标文件 硬链接名
2、软硬链接内容
软链接:存放目标文件路径字符串,类似windows中的快捷方式。
硬链接:存放目标文件名和inode映射关系。
3、软硬链接特点
上图中我们发现创建的软链接是独立文件,与目标文件的inode不同。
硬链接不是独立文件,inode与目标文件相同。
在文件权限的右边数字是硬链接数,是文件磁盘级引用计数(有多少文件名字符串通过inode_number 指向 inode)
4、软硬链接作用
(1)软链接:快速找到对应文件
(2)硬链接:构建Linux路径,可以让我们用 . .. 来进行路径定位。一般用来做文件备份。
注意:Linux不允许给目录建立硬链接,防止路径环绕。但由于 . .. 是固定名称,指令都认识,所以防止了路径环绕,也就能给目录建立硬链接。
5、总结
定位一个文件有两种方式
(1)通过路径(软链接)
(2)找到inode_number(硬链接)
用来找到inode,最后找到文件。
6、目录的引用计数
上图是目录结构,用Linux指令我们发现 dir 目录的引用计数是3,otherdir 目录引用计数是2。
一个目录创建时引用计数是2(自己和自己目录下的 . )
目录A内部创建一个目录,A目录引用计数+1(新目录下的 .. 指向A目录)
所以一个目录包含的目录个数是目录引用计数-2
二、文件写入和二进制写入
文件写入是语言层概念,是通过函数 fprintf() printf() 等调用系统调用的方法向文件中写入一些字符
二进制写入是把数据转化成二进制写入,与字符写入有本质区别。
int a = 0; scanf("%d", a);
我们从键盘中输入字符(文件写入),函数通过ASCII表转换成二进制写入。
三、动静态库
1、库
所谓的库就是把实现函数的 .c 文件编译成 .o 文件打包,头文件是手册提供函数声明,.o 文件提供函数实现,我们写一个 main.c 文件调用方法与.o 文件链接。
2、静态库的生成与使用
(1)生成静态库
sr -rc libmyc.a *.o
ar:相当于打包
-r:文件存在就替换
-c:文件不存在就创建
libmyc.a:库名,开头是lib,结尾是 .a
*.o:编译好的所有 .o 文件
(2)使用静态库
若已经把库安装到系统目录下
gcc main.c -l myc
-l:gcc只认识默认安装的c库,自己的库要带 -l
myc:库名要去掉 lib 和 .a
若未安装到系统目录
gcc main.c -I ./mylib/include -L ./mylib/lib -l myc
-I:大写i,指定用户自定义头文件路径
-L:指定用户自定义库文件路径
-l:小写l ,确定第三方库名
3、动态库的生成与使用
(1)生成动态库
编译.o文件
gcc -fPIC -c *.c
-fPIC:产生位置无关码
打包形成动态库
gcc -shared *.o libmyc.so
-shared:生成共享库格式
(2)使用动态库
不仅要在gcc编译main.c时指明头文件路径,库路径,库名,还要告诉操作系统动态库的位置。
方法如下
a、把动态库拷贝到 /lib64 目录(里面放有c标准库)
b、建立动态库软链接(最推荐)
c、环境变量 LD_LIBRARY_PATH 添加库路径
d、修改 .bashrc 中环境变量就能永久生效
e、/etc/ld.so.conf.d 新增配置文件 xxx.conf,里面加库路径,最后 ldconfig
四、动态库加载
一个动态库 支只加载一份共享库在内存,通过页表映射到进程地址空间。
我们的可执行程序,编译成功但没加载运行时,二进制代码中就已经存在地址。
我们编译形成ELF可执行程序,编译的二进制文件有自己的固定格式,ELF有可执行程序头部和属性。
可执行程序编译后会形成许多汇编语句,每条汇编语句都有地址,编址范围 000....000~FFF...FFF
是绝对编址,也叫做平坦模式。
ELF绝对编址(头部信息)+ 加载器就能知道虚拟地址空间中各个区域的起始地址和终止地址,还有main()函数入口地址。
mm_struct 作为一个结构体,里面分配空间的字段在一开始并不知道要分配多少空间,只有可执行程序自己知道,所以一开始初始值从程序头部信息来。
所以虚拟地址空间是由OS,加载器,编译器共同支持。
所以程序加载到物理内存时分配了物理地址,加上一开始程序自带的虚拟地址就可以填页表。
CPU中pc指针记录代码运行下一条语句的虚拟地址(一开始是main)
虚拟地址->物理地址->读指令
总结
(1)进程创建阶段,初始化地址空间,CPU知道main函数地址。
(2)加载到内存之后,每一行代码有了物理地址,与虚拟地址构成页表。
库函数的调用
库中记录函数相对于库地址的偏移量,当正文部分识别调用库函数时就是找到对应库地址,再加上偏移量就能找到函数。
静态库是直接拷贝到程序正文部分直接调用
所以-fPIC选项就是把库加载到任意位置内存,和可执行程序无关。