linux基础8:文件系统
- 1.物理存储->逻辑存储:
- 1.从磁盘到分区:
- 1.基本物理结构
- 2.物理存储结构
- 3.逻辑结构
- 4.操作系统的Io需求:
- 5.分区操作and分组操作:
- 2.文件系统结构:
- 1.基本结构:
- 2.分组区块:
- 3.目录
- 1. 目录是不是文件?
- 4.增删查改:
- 1.增:
- 2.删:
- 3.查:
- 4.改:
- 5.路径问题?
- 5.自定义一个分区并且挂载文件系统:
- 步骤1:创建目录
- 步骤2:挂载文件系统
- 卸载文件系统
- 2.软硬链接:
- 1.软链接:
- 1.操作:
- 2.应用:
- 2.硬链接:
- 1.操作:
- 1.程序
- 2.目录:
- 2.应用:计算
- 3.动静态库:
- 1.基本概念:
- 2.制作和使用静态库:
- 1.为什么需要一个库?
- 2.进行库文件的打包
- 3.使用静态库
- 3.制作和使用动态库:
- 1.产生位置无关码和生成共享库(动态库):
- 2.进行动态链接生成可执行:
- 3.头文件和库文件在一起进行封装打包:
- 4.头文件的访问库文件的访问:
- 5.不去使用-I 和 -L
- 4.解决执行可执行的问题:
- 1.为什么?
- 2.方法一:默认路径拷贝
- 3.方法二:环境变量
- 4.方法三:使用软连接
- 5.方法四:修改配置文件
- 4.动态库的加载:
- 1,系统角度
- 2.编址
- 1.绝对编址(平坦模式)
- 2.相对编址
- 3.理解动态库动态链接加载:
- 1.普通文件的加载:
- 2.存在动态文件的加载:
1.物理存储->逻辑存储:
1.从磁盘到分区:
1.基本物理结构
物理存储
1.磁道/柱面
2.扇区:是磁盘Io的基本单位,不一定是系统IO的基本单位。
补充:外部和内部的扇区宽度不同但是–>密度控制
3.一个磁头对应一个盘面,每一个磁道有唯一的编号。
2.物理存储结构
1.物理存储结构—>最小单位是扇区
2.通过磁头定位—>磁道/柱面 —确定柱面 cylinder
3.使用哪一个磁头—>确定磁道。head
4.定位扇区—>确定扇区。sector
5.CHS定位法
3.逻辑结构
1.物理结构转换为了一个线性结构(像我们的磁带)。
2.给一个数组下标如何确定实际的位置呢?
数组下标(线性地址) --> CHS
1.确定盘片:下标/单盘大小
2.temp = 下标%单盘大小。
3.确定磁道:temp/一个磁道的扇区个数
4.确定扇区:temp%一个磁道的扇区个数
5.最小的单位是扇区,物理到线性是磁盘自己完成的。
4.操作系统的Io需求:
1.操作系统认为一次读取一个扇区(512字节)太少了。
2.操作系统规定IO的基本单位是4字节。
5.分区操作and分组操作:
1.操作系统一下管理600GB的空间比较麻烦,现在已经是一种逻辑结构。
2.把600GB的空间分为4个150G的区域。
3.对于一个分区管理的操作可以cv到另一个分区那么本质是不是只需要去管理150GB的空间。
2.文件系统结构:
1.基本结构:
1.linux下的文件特性:文件 = 文件内容+文件属性(固定大小的)
2.struct inode{
类型,大小,权限,时间,inode编号(分区中唯一)
}
2.分组区块:
1.inode Table : 保存一个分组中的所有的文件的inode编号
2.inode bitmap : 用位置保存是第几个文件的inode,内容保存是否存在。
3.Date block : 文件的内容保存在每一个数据块中。
4.Block bitmap:位置代表第几个数据块,内容0,1代表有没有数据。
5.GDT:块组描述符,保存当前组的一些信息:使用了多少inode,使用了多少数据块。
补充:boot block:帮助我们找到磁盘中的操作系统并且启动操作系统的一个区域,磁盘第一个盘片上面。
6.super block :超级块(Super Block):存放文件系统本身的结构信息。记录的信息主要有:bolck 和 inode的总量,未使用的block和inode的数量,一个block和inode的大小,最近一次挂载的时间,最近一次写入数据的时间,最近一次检验磁盘的时间等其他文件系统的相关信息。Super Block的信息被破坏,可以说整个
文件系统结构就被破坏了==(super block 在一个分区的所有组中有可能只有百分之一存在super block 1.如果super block 过多降低效率,每次更新需要刷新super block 中的数据。2.super block 有几个防止有super block 坏了的情况出现本质是数据备份!!)==
3.目录
1. 目录是不是文件?
1,对一个文件做操作我们最先知道的就是文件名称。
2.目录是一个文件!目录 = 文件属性(所属组,权限 ,大小 ,时间) + 文件内容—>(目录中的文件名称 和 inode 编号的映射关系)。
3.目录中的映射关系就可以通过文件名称找到inode编号。
4.增删查改:
1.增:
1.在一个目录中创建一个新的文件。
2.在分组中把文件创建完成数据块中写入数据返回一个inode编号。
3.把inode编号和名称在当前目录中建立一个映射关系!完成了新增文件的操作。
2.删:
1,文件名称到inode编号,确定分组。
2.修改inode bitmap内容,返回把目录文件中的映射关系删除就可以了。
3.查:
1.文件名称到inode编号,确定分组。
2.inode编号找到date block信息。
4.改:
1.文件名称到inode编号,确定分组。
2.inode编号找到date block 对date block 内容做修改。
5.路径问题?
1.目录也是一个文件,文件内容需要找到上一个文件的内容。
2.需要递归式的找到根目录就可以完善文件查找的过程。
3.查找一个文件在内核中都要递归式的找到根目录,从根目录进行路径解析!
5.自定义一个分区并且挂载文件系统:
在Linux系统中,你可以使用mkdir命令来创建一个目录,并使用mount命令来挂载文件系统。下面是一些基本的步骤:
步骤1:创建目录
首先,你需要使用mkdir命令来创建一个新的目录。例如,如果你想在/mnt下创建一个名为mydir的目录,你可以使用以下命令:
bash
sudo mkdir /mnt/mydir
这将在/mnt下创建一个名为mydir的新目录。你需要有足够的权限来执行此操作,因此我使用了sudo来以超级用户身份运行命令。
步骤2:挂载文件系统
可以使用mount命令来挂载文件系统。假设你有一个名为/dev/sdb1的设备(这可能是一个硬盘分区、USB驱动器或其他类型的存储设备),并且你想将其挂载到刚才创建的/mnt/mydir目录下,你可以使用以下命令:
bash
sudo mount /dev/sdb1 /mnt/mydir
这会将/dev/sdb1设备挂载到/mnt/mydir目录。如果设备已经包含文件系统,那么现在你就可以通过访问/mnt/mydir来访问该文件系统了。
注意:在挂载文件系统之前,你可能需要确保设备是可用的,并且你知道它的设备路径。你可以使用lsblk或fdisk -l等命令来查看系统中可用的设备。此外,如果设备包含的文件系统需要特定的选项或类型才能正确挂载,你可能需要在mount命令中指定这些选项或类型。你可以查阅man mount来获取更多关于mount命令的信息。
卸载文件系统
当你不再需要访问挂载的文件系统时,你应该使用umount命令来卸载它。例如:
bash
sudo umount /mnt/mydir
这将卸载/mnt/mydir目录下的文件系统。请注意,在卸载文件系统之前,确保没有任何进程正在访问它,否则你可能会遇到问题。你可以使用lsof或fuser等命令来检查是否有进程正在访问某个目录或设备。
2.软硬链接:
1.软链接:
1.操作:
1.命令:ln -s 链接的目录或者文件或者程序 生成的链接文件
2.要求1:对一个可执行程序进行软链接
3.软链接文件:是一个新的生成的文件这个文件链接对应的文件,效果类似于windows下的快捷方式。
4.内容:相当于目标文件的一个路径。
2.应用:
可以快速执行目标文件:
举例:想要执行mybin
2.硬链接:
1.操作:
1.命令:ln 链接文件或者程序 生成的链接文件
2.要求1:对一个可执行程序进行硬链接
3.硬链接文件:是一个老文件的一个别名(inode没有变化),类似于C++中的引用。
4.硬链接数:文件用户名称前面就是硬连接个数
1.程序
2.目录:
1,不允许用户自己建立目录硬连接
2.在任意一个目录如果给根目录建立一个硬链接造成死循环问题。
3.操作系统:允许目录硬链接的存在?
4.创建一个目录:目录中的 . 和 … 相当于当前目录和上级命令的别名。
2.应用:计算
1.一个目录下有多少个目录可以通过当前目录的硬链接个数减2.
2.总结:删除文件:清除映射关系+硬链接数–到0
3.动静态库:
1.基本概念:
1.为什么需要库?
不同的系统通过不同的库去除差异性。
2.有那些库?
动态库||静态库 , 云服务器默认安装动态库。
3.查询程序依赖:
ldd mybin 显示程序依赖的库。
4.静态链接?
gcc -o mybin text.c -static —>当前环境下需要有静态库。
5.名称:
动态:libXXX.so
静态:libXXX.a
6.库的真实名称:
去除lib前缀和.so 或者 .a 后缀剩下的就是名字。
2.制作和使用静态库:
1.为什么需要一个库?
1.提高开发效率
2.进行库文件的打包
1.库文件中的.o文件中不可以有main函数。
2.生成.o文件 , gcc -c text.c text.o 默认生成同名.o文件。
3.打包命令:arr -rc libadd.a add.o…(各种.o文件)
3.使用静态库
1.自定义静态库,gcc是不认识的。
2.gcc main.c -o mybin -lname -L 库的位置
3.name:去掉lib的前缀和.a的后缀。
3.制作和使用动态库:
1.产生位置无关码和生成共享库(动态库):
1,使用fpic命令生成.o文件:
2.使用gcc -shared -o libmy.so *.o
3.makefile生成两个.o文件的优化。
2.进行动态链接生成可执行:
1.gcc main.c -L 链接库路径 -lname
2.在gcc中我们使用一个我们新建立的一个外部库gcc是找不到这个外部库的需要-L
3.-lname 是常规操作需要知道外部库的名称去使用。
3.头文件和库文件在一起进行封装打包:
4.头文件的访问库文件的访问:
1.gcc -o mybin main.c -I ./mylib/include/ -L ./mylib/lib -lname
2.-I 找头文件
3.-L找库文件
5.不去使用-I 和 -L
手动拷贝文件到gcc默认查找路径
1.gcc 对于.h文件默认查找当前路径和gcc默认的/user/include/
2.gcc 对于.so文件默认/lib64/
3.拷贝文件到这两个gcc的默认位置就可以不使用-I -L
4.解决执行可执行的问题:
1.为什么?
1.我们已经链接生成了可执行程序为什么执行可执行会not found
2.我们链接的是一个动态库!
3.动态库生成了可执行执行可执行需要实时可以调用到库.
4.编译操作的路径给gcc使用
5.执行程序时路径给操作系统进行使用.
2.方法一:默认路径拷贝
1.拷贝.h和.so文件到系统默认路径 /user/include 和 /lib/
3.方法二:环境变量
1.echo L D L I B R A R Y P A T H 环境变量指定的一个路径 2. e x p o r t L D L I B R A R Y P A T H = LD_LIBRARY_PATH环境变量指定的一个路径 2.export LD_LIBRARY_PATH= LDLIBRARYPATH环境变量指定的一个路径2.exportLDLIBRARYPATH= .so的一个绝对路径
3.将不在系统默认路径下的内容添加到环境变量中.
4.方法三:使用软连接
1.sudo ln -s .so的绝对路径 /lib/同名so
2.在默认搜索路径中去建立软连接。
5.方法四:修改配置文件
1./etc/ld.so.conf.d/ 目录新建文件
2.给文件中加入自定义库的路径
3.sudo ldconfig -->配置更新
4.动态库的加载:
1,系统角度
1.加载程序和库文件到内存中
2.对mm_struct结构体进行初始化。初始化依赖的是什么呢?
3.建立虚拟地址和物理地址之间的映射关系,页表中存在这样的映射关系。
4.动态库加载之后会映射到mm_struct中的共享区中。
补充:
1.又来一个进程,需要libmy.so,如果当前内存中已经加载了一份,不需要再加载另一份。
2.操作系统通过先描述再组织的方式管理加载到内存中的多钟动态库。
2.编址
我们的可执行程序在加载到内存之前有没有地址?
有地址的—>汇编代码每一个命令前面都会存在一个地址。
1.在可执行程序没有加载到内存的时候已经分配好了各各区域。
2.可执行在没有加载到内存中已经存在有代码+数据的地址。
3.虚拟地址就是从可执行中来的。
4.可执行进行反汇编:objdump -s mytest > test.s
1.绝对编址(平坦模式)
2.相对编址
—>mm_struct是依靠进程进行初始化的!
—>虚拟地址空间本身不仅仅是os需要去遵守编译器编译程序也要去遵守。
3.理解动态库动态链接加载:
1.普通文件的加载:
1.依靠ELF格式的表头数据对mm_struct进行一个初始化。
如何找到第一条命令开始执行程序呢?
2-1:拿cup中的一个pc指针指向ELF中保存的main的虚拟地址。
2-2:cup中存在一个指令寄存器保存下一个需要执行的指令的地址。
2-3:(cpu)虚拟地址->物理地址?
2-4:MMU(硬件) + 页表(软件) 进行虚拟到物理的转换!
2-5:在内存中找到下一条指令的虚拟地址给指令寄存器。
2-6:指令寄存器通过mmu找物理地址一步一步执行命令。
2.存在动态文件的加载:
1.正常执行我们的程序。
2.下一条命令:start+0x1001这样的命令。
3.找到动态库加载到内存中的一个位置,继续找下一条命令返回给指令寄存器。
4.可执行程序链接libmy.so的。
5.对于库的数据+方法的范围可以通过首地址+偏移量的方法进行访问。