背景知识:没有被进程打开的文件存放在磁盘
单个文件角度:文件位置,文件大小等属性。
系统角度:文件数量,文件对应的属性,还可以存储多少文件等
1. 磁盘的物理结构
磁盘有磁盘盘片、磁头、伺服系统、音圈马达。
盘片上有多个同心圆,称为磁道。
将盘片分成很多扇形,在每一个扇形内的磁道称为扇区。每一个扇区是磁盘存储数据的基本单位,为512字节。
物理上把数据写入制定扇区,需要先找到扇区。
CHS寻址:1.在哪一个面上(对应的就是哪一个磁头)。2.在哪一个磁道上。3.在哪一个扇区上
1. 2 磁盘的抽象结构
将磁盘盘面当成卷起来的磁带,磁带抽出来就成了线性结构。扇区可以抽象理解成数组,访问一个扇区只需要知道数组下标。
1.3 磁盘分区
将磁盘抽象理解成线性数组之后,数据存储到磁盘起始就是存储到数组。找扇区就是找数组下标,对磁盘的管理就是对数组的管理。一个磁盘的大小非常大,所以需要分区管理(C、D盘之类的)。每一个区域都有若干块组,文件=内容+属性。Linux在磁盘上存储文件时,将内容和属性分开存储。
虽然磁盘的基本单元是512字节,但操作系统和磁盘进行IO的基本单位是4KB,也是一个Block group(块设备)的大小。原因:1.太小会进行多次IO,降低效率。2、与磁盘进行解耦合。
2. 块组
Super Block | 文件系统的属性信息 |
Date blocks | 多个(4KB )块设备的集合,包括的都是特定文件的内容 |
inode Table | inode是一个大小为128字节的空间,保存的都是文件对应的属性。该块组内,所有文件的inode空间的集合,需要唯一标识性,每一个inode块,都有一个inode编号。一般一个文件,一个inode,一个inode编号。 |
Block Bitmap | 有多于blocks个数的比特位,比特位和特定的blocks是对应的,比特位位1代表该blocks被占用,否则表示可用 |
inode Bitmap | 同block bitmap 不过代表的是inode |
GDT | 块组描述符。这个块组的大小,block inode已用多少,还有多少 |
2.1 inode
struct inode
{
//文件大小
//文件的inode编号
//其他属性
int blocks[15];
};
注意:在Linux中,inode属性里面,没有文件的文件名!
那如果文件特别大,一个blocks才4kb存不下怎么办?其实不是所有的date block只能存文件数据,也可以存储其他块的块号。
2.1.1 查看inode
ls -li
2.1.2 inode与文件名
要想找到一个文件,需要通过他的inode编号找到分区特定的blick group,在inode table表查到对应的inode结构体,从而找到属性和内容。
那如何得知inode编号呢?-->依托于目录结构。一个目录下可以有多个文件,但这些文件没有重复的文件名。目录也是文件,那目录的data blocks保存什么?答案是目录data blocks里面保存的是文件名。文件名和inode编号的映射关系互为Key值。
这也是为什么在目录创建文件需要w权限
3. 软硬链接
3.1 软连接
又称符号链接
ln -s testLink.txt soft.link
ll
soft.link -> testLink.txt
soft.link 是新建的 ,指向 testLink.txt的软连接。
3.2 硬链接
ln testLink1.txt hard.link
ll
hard.link
hard.link 是新建的,指向textLink1.txt的硬链接。
3.3 软硬链接的区别:
硬链接没有独立的inode,相当于取别名。创建硬链接就是在指定得到目录下建立了文件名和指定inode的映射关系。当我们删除文件时,并不是把inode删掉,而是把这个文件的引用计数--,当引用计数减为0时,这个文件才真正删除。
软连接相当于快捷方式。
引用计数
默认情况下,创建一个目录,其引用计数(硬链接)为2。原因是:目录名和自己目录内部有一个.文件,二者的对应的inode是一样的。 在创建的目录路径下创建d1、d2、d3目录,该目录的硬链接数为2+3=5,原因是:d1、d2、d3目录中各有一个..文件,其代表着上级文件。
注意:
1.软链接可以跨文件系统,硬链接不可以。
2.硬链接不管有多少个,都指向的是同一个I节点,会把结点连接数(引用计数)增加,只要结点的连接数不是0,文件就一直存在不管你删除的是源文件还是链接的文件。所以inode和文件名并非与是一一对应的
只要有一个存在文件就存在。 当你修改源文件或者连接文件任何一个的时候,其他的文件都会做同步修改。
软链接不直接使用i节点号作为文件指针, 而是使用文件路径名作为指针。所以删除链接文件对源文件无影响,但是删除源文件,链接文件就会找不到要指向的文件。软链接有自己的inode, 并在磁盘上有一小片空间存放路径名。
3.软连接可以对一个不存在的文件名进行连接 。
4.软连接可以对目录进行连接。硬链接不可以对目录进行连接。
4. 静态库
静态库 .a 结尾 动态库 .so 结尾
4.1 常规写法
只把 .o文件给别人能用吗?
我们用mymath.c myprint.c 形成两个.o文件,复制到usrlib文件夹下,用main.c形成.o文件后,依然可以形成可执行程序。
4.2 静态库
经过上述论证,发现.o文件给其他人,编译时将自己写的main.c也形成.o文件,这三个.o文件就可以形成可执行程序。但是每次编译都需要带上.o文件,麻烦而且容易漏写,所以我们需要打包成一个文件。
4.2.1 生成静态库
bash: ar -rc libhello.a mymath.o myprint.o
ar是gnu归档工具,rc表示(replace and create)
其中hello是我这个库的名字。
4.2.2 查看静态库中的目录列表
bash: ar -tv libhello.a
4.2.3 发布 Makefile
libhello.a: mymath.o myprint.o
ar -rc libhello.a mymath.o myprint.o
mymath.o:mymath.c
gcc -c mymath.c -o mymath.o
myprint.o:myprint.c
gcc -c myprint.c -o myprint.o
.PHONY:hello
hello:
mkdir -p hello/lib
mkdir -p hello/include
cp -rf *.h hello/include
cp -rf *.a hello/lib
.PHONY:clean
clean:
rm -f *.o libhello.a
4.2.4 库的使用之安装
- 将生成的静态库拷入到需要被使用的目录下
cp -rf hello ../usrlib
- 将hello库下包含的头文件全部拷入 /usr/include/ 路径下
sudo cp hello/include/* /usr/include/ -rf
- 将hello库下的静态库拷入 /lib64 路径下
sudo cp hello/lib/libhello.a /lib64
- 编译时 需要带上我们的库名称
gcc main.c -lhello
4.2.5 库的使用之硬使用
gcc main.c -I ./hello/include/ -L ./hello/lib/ -lhello
-I 表示头文件在这里找
-L 表示库文件在这里找
-lhello 在特定他路径下使用hello库
5. 动态库
5.1 生成动态库
形成一个与位置无关的二进制文件
gcc -fPIC -c mymath.c -o mymath.o
gcc -fPIC -c myprint.c -o myprint.o
生成动态库
gcc -shared myprint.o mymath.o -o libhello.so
Makefile
5.2 使用动态库
- 动静态库同时存在时,gcc默认采用的是动态库。
- 如果同时存在的情况下非要使用静态链接,编译时需要加 -static
5.2.1 添加至环境变量
查看库搜索路径 (没有设置过就是空)
echo $LD_LIBRARY_PATH
添加至环境变量
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:路径
退出Xshell后设置的环境变量就没了,因为设置的是内存级的环境变量
5.2.2 新增配置文件
在 /etc/ld.so.conf.d/ 路径下创建一个文件,然后将路径放到该文件中,然后更新
sudo touch /etc/ld.so.conf.d/hellolib.conf
sudo vim /etc/ld.so.conf.d/hellolib.conf
sudo ldconfig
5.2.3 建立软链接
sudo ln -s 路径/libhello.so /lib64/libhello.so