宁夏找人做网站多少钱,seo代码优化包括哪些,自适应网站设计尺寸,wordpress怎么链接地址hello#xff0c;大家好#xff0c;这里是bang___bang_#xff0c;今天来谈谈的文件系统知识#xff0c;包含有缓冲区、inode、软硬链接、动静态库。本篇旨在分享记录知识#xff0c;如有需要#xff0c;希望能有所帮助。 目录
1️⃣缓冲区
#x1f359;缓冲区的意义 … hello大家好这里是bang___bang_今天来谈谈的文件系统知识包含有缓冲区、inode、软硬链接、动静态库。本篇旨在分享记录知识如有需要希望能有所帮助。 目录
1️⃣缓冲区
缓冲区的意义
常见缓冲区刷新策略
缓冲区位置猜想
现象猜测
现象解释
用户级缓冲区位置
2️⃣理解文件系统
磁盘的存储结构
磁盘物理结构
磁盘抽象结构
文件系统
inode vs 文件名
3️⃣软硬链接
软链接
硬链接
4️⃣动态库和静态库
静态库
生成静态库
使用静态库
动态库
生成动态库
使用动态库
同时存在使用静态库还是动态库
特点总结
静态库特点
动态库特点 1️⃣缓冲区
问题什么是缓冲区
答就是一段内存空间
缓冲区的意义
我们知道了一段内存空间就是缓冲区那么为什么要有缓冲区呢
生活例子映射 你在西安你有个好朋友在上海下个月好朋友要过生日了你想送他一本你自己手绘的图画你可以选择自己骑车亲手送给你的朋友也可以选择下楼到顺丰选择寄送包裹然后回家。
毫无疑问你自己骑车亲手送需要花费大量的时间而你选择去顺丰寄包裹却很快但是寄包裹也不是立马就会发送包裹可能要等仓库堆满一批货物再一起发送。图画是数据顺丰是缓冲区
自己骑车亲手送就相当于写透模式WT
而去顺丰寄包裹再可以直接回家就相当于写回模式WB
写透模式直接将数据写到外部设备。
写回模式先将数据写到缓冲区当缓冲区的数据达到一定量时再集中写到外部设备。
通过这个例子很显然能感受到缓冲区存在的意义了
缓冲区存的意义提高整机效率。主要是为了提高用户的响应速度
常见缓冲区刷新策略
缓冲策略一般特殊
一般情况 ✦立即刷新 ✦行刷新行缓冲 ✦满刷新全缓冲
特殊情况 ✦用户强制刷新(fflush) ✦进程退出
一般而言行缓冲的设备文件——显示器 全缓冲的设备文件——磁盘文件 所有的设备永远都倾向于全缓冲
——缓冲区满了才刷新—更少次的IO操作—更少次的外设的访问提高效率 和外部设备IO的时候数据量的大小不是主要矛盾和外设预备IO的过程是最耗费时间的
缓冲区位置猜想
现象猜测
下面有一段代码我们分别输出到显示屏输出重定向到文件。
int main() {//C语言提供的printf(hello printf\n);fprintf(stdout, hello fprintf\n);const char* s hello fputs\n;fputs(s, stdout);//OS提供的const char* ss hello write\n;write(1, ss, strlen(ss));fork();return 0;
} 现象图 我们可以看到同一份代码输出的结果却不一样C的IO接口打印了2次系统接口只打印1次和向显示器打印一样也就是说子进程中有父进程C的IO接口对应的打印数据但没有系统接口的。也就是说如果有缓冲区那么绝对是C标准库来提供的。 现象解释 ★如果向显示器打印刷新策略是行刷新那么进程执行到fork()函数时会将C标准库里缓冲区的数据全部进行刷新出去fork无意义 对于进程来说当我们调用C文件接口fputs时实际是将进程数据写入到C标准库中的缓冲区里然后再统一调用系统接口write函数写入到对应的目标文件中。 ★如果我们进行输出重定向时将原本写入到stdout文件中的数据写入到了磁盘文件中缓冲模式就由行刷新变成了全缓冲。(\n便没有意义了当进程执行到代码fork()时此时进程写入C标准库中的缓冲区数据还未刷新。当进程执行fork函数便又生成了子进程。 fork后父子进程退出刷新数据到磁盘文件中但是刷新实际上也是一次写入因为进程的独立性发生写时拷贝打印2份 ★缓冲区里的数据也是父进程的数据提前强制刷新后没有数据了子进程也就没拷贝了 用户级缓冲区位置
问题为什么fflush只传了stdout却能找到缓冲区
答C语言中打开文件FILE* fopenstruct FILE 结构体 内部封装了fd,还包含了该文件fd对应的语言层的缓冲区结构 2️⃣理解文件系统
我们使用ls -l指令读取文件信息实际上是对磁盘中的文件进行读取。 磁盘——永久性存储介质(还有SSD,U盘flash卡光盘磁带
磁盘是一个外设还是我们计算机中唯一的一个机械设备也就是说速度很慢相对于CPU
磁盘的存储结构
磁盘物理结构
磁盘盘片磁头伺服系统音圈马达等等 向磁盘写入本质就是改变磁盘上的正负性。 磁盘的盘面被划分为一个个磁道而磁道又被划分为一个个扇区。
扇区磁道划分区域是磁盘存储数据的基本单位512byte
如何将数据写入指定的一个扇区有以下步骤CHS寻址 ——1.在哪一个面上对应的就是哪一个磁头 ——2.在哪一个磁道柱面上 ——3.在哪一个扇区上
如果我们有了CHS寻址方式就可以找到任意一个扇区。
磁盘抽象结构
小时候我们都有过磁带这种东西他是缠在一起成圈的但是我们也可以将他全拉出来成线状。磁盘我们也可以抽象成拉长后变为线状结构。
结构圆形结构CHS-线性结构LBA
LBA是非常单纯的一种寻址模式﹔从0开始编号来定位扇区第一扇区LBA0第二扇区LBA1依此类推。所以将来我们想要访问磁盘的某个扇区只需要将通过LBA寻址后转换为CHS物理寻址。 最终对磁盘的管理就变成了对一个个小分区的管理。
文件系统 磁盘文件系统图 上图为磁盘文件系统图内核内存映像肯定有所不同 磁盘是典型的块设备 硬盘分区被 划分为一个个的 block 。一个 block 的大小是由格式化的时候确定的并且不可以更改。 虽然磁盘的基本单位是扇区512字节但是OS文件系统和磁盘进行IO的基本单位是4KB8*512byte4KB-block大小。 ★Super Block-文件系统的属性信息 ★Data bolcks-多个4KB大小的集合保存的都是特定文件的内容 ★inode Tableinode是一个大小为128字节的空间保存的是对应文件的属性该块组内所有文件的inode空间的集合需要标识唯一性每一个inode块都要有一个inode编号 ★Block Bitmap:假设有10000blocks10000比特位比特位合特定的block是一一对应的其中比特位为1代表该block被占用否则表示可用 ★inode Bitmap:假设有10000个inode节点就有10000个比特位比特位和特定的inode是一一对应的。其中bitmap中比特位为1代表该inode被占用否则表示可用 ★GDT:块组描述符这个块组多大已经使用了多少了有多少个inode已经占用了多少个还剩多少一共有多少个block使用了多少....
我们将块组分割成上面的内容并且写入相关的管理数据-每一个块组都这么干-整个分区就被写入了文件系统信息格式化
inode vs 文件名
一个目录下可以保存很多文件但是这些文件都不会重名。目录是文件目录有自己的inode和Data block 文件名在目录的Data block 中它保存着与inode编号的映射关系文件名与inode互为key值都是唯一的。
为什么目录需要w权限 因为在目录下创建文件时这个目录有自己的数据块我们创建文件的文件名就在目录的Data block 中所以我们要将文件名和inode编号写入保存此时必须需要w权限。 为什么目录中具有r权限 当我们需要显示文件名时我们只能从目录的内容中获取文件名及相关属性就必须访问目录的文件内容就必须需要r权限从目录的Data block中获取文件名。 创建文件系统做了什么 特定分组找到没有使用的inode分配inode编号如果文件有内容向文件内容当中申请Data Block设置Block Bitmap,建立inode和Bitmap的映射inode和Bitmap、Data Block的对应关系并写到inode结点中inode文件名对应的映射关系写到特定的目录的DataBlock中。 删除文件系统做了什么 删除文件肯定是在这个目录下删除找到这个目录的Data Block 删文件用户提供文件名在Data Block中索引查询由文件名进行映射的inode编号找到将inodeBitmap对应的比特位由1置为0将Block Bitmap中的比特位由1置为0,在目录的Data Blocks中将文件名与inode编号解除映射关系。 查看文件系统做了什么 根据文件名找到inode,然后查内容查属性。 3️⃣软硬链接
本质区别有没有独立的inode
软链接
软链接有独立的inode软链接是一个独立的文件
应用相当于windows下的快捷方式
特性可以理解成为软链接的文件内容是指向的文件对应的路径
ln -s 文件 软链接文件名
建立一个软链接 软链接如同Windows下的快捷方式 硬链接
硬链接没有独立的inode硬链接不是一个独立的文件有被链接文件的inode
创建硬链接就是在指定的目录下建立了 文件名 和 指定inode的映射关系。
ln 文件 硬链接文件名
建立一个硬链接 硬链接没有独立的inode!也就是说硬链接不是一个独立的文件!
硬链接数引用计数 硬链接后inode与文件名映射关系增加1组所以为2从这里可以看出一个思想
当我们删除一个文件的时候并不是把这个文件inode删除而是将这个文件的inode引用计数--。当引用计数为0的时候这个文件才正在删除RAII思想
默认创建文件引用计数是1创建目录引用计数是2 inode与文件名对应一组映射关系。
但目录为什么是2呢 因为目录里面还有隐藏文件.文件也就是说inode对应2个文件名自己目录名自己目录内部的文件名所以引用计数为2。
4️⃣动态库和静态库
静态库 ✦静态库.a程序在编译链接的时候把库的代码链接到可执行文件中。程序运行的时候将不再需要静态库。
生成静态库
打包.o文件ar -rc xxx.a xxx.o xxx.o
解析 ar是gnu归档工具 ar——archieve r——replace c ——create 把.o文件打包到.a静态库
将myprint.o、mymath.o打包到libtest.a
myprint.h代码
#pragma once#includestdio.h
#includetime.hextern void Print(const char* str);
myprint.c代码
#includemyprint.hvoid Print(const char* str)
{printf(%s[%d]\n,str,(int)time(NULL));
}
mymath.h代码
#pragma once#includestdio.hextern int addToTarget(int form,int to);
mymath.c代码
#includemymath.hint addToTarget(int form,int to)
{int sum0;for(int iform;ito;i){sumi;}return sum;
}Makefile
libtest.a:mymath.o myprint.oar -rc libtest.a mymath.o myprint.o
mymath.o:gcc -c mymath.c -o mymath.o -stdc99
myprint.o:gcc -c myprint.c -o myprint.o -stdc99.PHONY:clean
clean:rm -rf *.o *.a 静态库生成图 使用静态库
gcc main.c -I 指定头文件搜索路径 -L 指定库文件搜索路径 -l使用哪个库
使用上面生成的libtest.a静态库
修改Makefile文件将头文件放到include目录中静态库放到lib目录中。
libtest.a:mymath.o myprint.oar -rc libtest.a mymath.o myprint.o
mymath.o:gcc -c mymath.c -o mymath.o -stdc99
myprint.o:gcc -c myprint.c -o myprint.o -stdc99.PHONY:output
output:mkdir -p libmkdir -p includecp -rf *.h includecp -rf *.a lib.PHONY:clean
clean:rm -rf *.o *.a lib include使用静态库生成可执行文件 动态库
✦动态库.so程序在运行的时候才去链接动态库的代码多个程序共享使用库的代码。
生成动态库
生成动态库的必须加 -fPIC 生成二进制文件
-shared告诉gcc生成动态库
gcc -fPIC -c xxxx.c -o xxxx.o //生成动态库必须加-fPIC
gcc -shared xxxx.o -o libxxxx.so //-shared告诉gcc生成动态库
生成libtest.so动态库
编写Makefile文件
libtest.so:mymath_d.o myprint_d.ogcc -shared mymath_d.o myprint_d.o -o libtest.so
mymath_d.o:mymath.cgcc -fPIC -c mymath.c -o mymath_d.o -stdc99
myprint_d.o:myprint.cgcc -fPIC -c myprint.c -o myprint_d.o -stdc99.PHONY:output
output:mkdir -p libmkdir -p includecp -rf *.h includecp -rf *.so lib.PHONY:clean
clean:rm -rf *.o *.so lib include生成动态库 使用动态库
动态库的使用和静态库是一样的。
gcc main.c -I 指定头文件搜索路径 -L 指定库文件搜索路径 -l使用哪个库
main.c使用动态库libtest.so
查看程序链接的库动态库ldd
ldd 可执行程序 //查看程序链接的库 同时存在使用静态库还是动态库
问题假设现在既有静态库又有动态库那么程序默认链接的是哪种库
修改Makefile文件
.PHONY:all
all:libtest.so libtest.alibtest.so:mymath_d.o myprint_d.ogcc -shared mymath_d.o myprint_d.o -o libtest.so
mymath_d.o:mymath.cgcc -fPIC -c mymath.c -o mymath_d.o -stdc99
myprint_d.o:myprint.cgcc -fPIC -c myprint.c -o myprint_d.o -stdc99libtest.a:mymath.o myprint.oar -rc libtest.a mymath.o myprint.o
mymath.o:gcc -c mymath.c -o mymath.o -stdc99
myprint.o:gcc -c myprint.c -o myprint.o -stdc99.PHONY:clean
clean:rm -rf *.o *.a *.so 现象 验证发现同时存在静态库和动态库默认使用的是动态库。
那么如何在这种情况使用静态库呢 -static 指定静态链接
-static的意义摒弃默认优先使用动态库的原则而是直接使用静态库。 使用ldd查看链接的动态库报错显示不是动态可执行文件也就是说使用的是静态库
特点总结
静态库特点 优点 ①静态库被打包到应用程序中加载速度快 ②发布程序无需提供静态库移植方便 缺点 ①相同的库文件数据可能在内存中被加载多份消耗系统资源浪费内存 ②库文件更新需要重新编译项目文件生成新的可执行程序浪费时间 动态库特点 优点 ①可实现不同进程间的资源共享 ②动态库升级简单只需要替换库文件无需重新编译应用程序 ③可以控制何时加载动态库不调用库函数动态库不会被加载 缺点 ①加载速度比静态库慢 ②发布程序需要提供依赖的动态库 文末结语开篇解释缓冲区以及意义并验证了用户级缓冲区的刷新策略接下来谈文件系统首先介绍磁盘的存储结构包括物理结构和抽象结构介绍inode和文件名之间的关系软硬链接的使用最后讲解动静态库详细说明如何制作并使用动静态库并探究了动静态库同时存在时默认使用动态库以及想使用静态库的解决方案最终总结动静态的特点。本篇旨在分享记录知识如有需要希望能有所帮助感谢观看