百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术分析 > 正文

深圳大学操作系统实验四文件系统 深圳大学wind数据库

liebian365 2024-10-22 15:35 32 浏览 0 评论

实验目的

了解Linux 文件命令行操作命令;

了解Linux ext3文件系统上的软硬链接;


实验内容

可以使用Linux或其它Unix类操作系统;

学习该操作系统提供的文件系统的命令行接口;

学习文件的软硬链接的使用;


实验环境

硬件:桌面PC

软件:Linux 或其他操作系统

实验步骤及说明

学习使用Linux文件系统提供的的ls 、touch、rm、cp、mv、mkdir等命令(希望尽量涵盖各种满足日常编程所需操作),了解EXT2文件系统。

操作部分(参考):

  1. 构建以下目录子树:(20%)

你的私有目录

a

b

c

d

e

f

g

软链接

硬链接

  1. 创建一个4KB左右的文本文件,其内容为重复出现的“Hello Operating system”。读入该文件的目录项内容,并解读出其对应的inode节点号;然后读出对应的inode内容,找到文件的第一个扇区,读入第一个盘块并查看其内容;(30%)
  2. 学习Linux文件系统中关于文件硬链接和软链接的概念和相关操作命令,创建软硬链接各一个,用tree命令、ls -l和ls -i命令查看和对比它们的不同;(10%)
  3. 创建一个1GB的大文件,读入全部数据到内存中并记录所花时间,然后进行第二次读入并记录时间。(20%)

要求:用/proc/meminfo查看内存中页缓存使用的变化,并解释两次读入速度差异的原因。

实验报告要求:

  1. 按学校统一格式
  2. 需要给出具体命令和自行编写的程序的源代码
  3. 程序的设计需要给出设计思路或流程框图
  4. 实验操作的截图需要有必要的说明文字

选做:

利用df命令查看并解读文件系统的信息,学习mount/unmount命令如何将光驱或U盘挂载到系统中,并体验windows盘符和linux无盘符概念的差异。

查看c语言提供的fopen/fclose/fread/fwrite函数和操作系统直接对应的open/close/read/write两套接口的差异,弄清楚字符模式和二进制流模式是哪一层面的概念。

思考文件读写指针(游标概念)属于文件的逻辑抽象管理数据还是属于磁盘文件管理数据?文件指针是否需要保存在磁盘上,如果在磁盘上应该如何存放?如果在内存中又如何存放?

实验结果

学习使用Linux文件系统提供的的ls 、touch、rm、cp、mv、mkdir等命令(希望尽量涵盖各种满足日常编程所需操作),了解EXT2文件系统。

网上查阅资料得知,ls命令是用来显示目标列表的,输出信息可以彩色高亮显示以区分不同类型的文件(图1-1)

图 1?1 ls指令解释

Touch命令用于创建新的空文件,并且它还可用于更改现有文件和目录的时间戳(最近访问和修改的日期和时间),其语法是touch [option] file_name(s)(图1-2)。

图 1?2 touch创建空文件

Rm命令常用来删除目录里面的一个或多个文件的目录,也用于删除目录下文件与子目录,查阅资料发现其有以下参数(图1-3),图1-4是我们删除的实例。

图 1?3 rm命令参数

图 1?4 rm删除实例

Cp指令用于复制文件或目录,如果指定两个以上的文件或目录,且最后目的地是一个已经存在的目录,他会把前面的所有文件或目录复制到指定目录中,如果目录不存在则报错,且他具有许多参数(图1-5)。

图 1?5 cp指令参数

Mv指令是move的缩写,他可以用来移动文件或将文件改名,具体格式是

mv [选项] 源文件或目录 目标文件或目录,具体参数如下(图1-6)。

图 1?6 mv指令参数

Mkdir命令常用来创建目录,如果目录名前面没有加任何路径名,则在当前目录下创建由dirname指定的目录,如果给出了一个已经存在的路径,则将会在目录下创建一个指定的目录。命令格式为mkdir [OPTION]... DIRECTORY...,具体参数如下(图1-7)。

图 1?7 mkdir指令参数

关于ext4文件系统:目前大部分linux操作系统使用的是ext4文件系统,block是ext4的最小储存单位,使用blkid可以查看文件系统类型,每一个block只能存储一个文件的数据(图1-8)。

图 1?8 block等基础知识

EXT3文件系统会把整个分区划分成各个block group,每个块组由superblock,block group,block bitmap,inode bitmap和group descriptor以及inode table、data block组成(图1-9)。

Superblock用于记录文件系统的inode/block总量、使用量、剩余量、大小、以及文件系统的格式和相关信息。

Block bitmap记录所有使用和未使用的block号码,删除文件时,我们需要先从block bitmap中找到对应的block号码,更新标志为未使用,然后释放block。

Inode bitmap,记录使用和未使用的inode号码。

Group descriptor,描述每个区段的开始和结束的block号码,说明每个区段分别介于那些block号码之间。

Inode table,记录该组的所有inode的合集,可以通过inode编号以inode table起始位置做偏移找到inode位置。

图 1?9 EXT4文件系统分区功能

我们可以使用dumpe2fs打印ext4分区的详细信息,也可以通过dd了解文件在磁盘中的内容。

构建以下目录子树:(20%)

你的私有目录

a

b

c

d

e

f

g

软链接

硬链接

查阅资料得知,mkdir用于创建目录,默认情况下,ln用于产生硬链接,产生硬链接后目录项中的inode节点相同,即一个inode节点对应两个不通的文件名,两个文件名指向同一个文件;软连接称为符号链接,软连接的两个文件目录项的inode不通,但是他们inode的数据块指向的是目标文件的路径名,删除目标文件会使链接无效,软连接用ln指令的-s参数实现。

我们根据题意创建目录结构,首先先不考虑e和f文件,因为他们是链接的,不需要创建,所以暂时如下图2-1所示。

图 2?1 创建没有链接的文件目录结构

接着我们创建链接(图2-2)。

图 2?2 创建硬链接和软连接

创建一个4KB左右的文本文件,其内容为重复出现的“Hello Operating system”。读入该文件的目录项内容,并解读出其对应的inode节点号;然后读出对应的inode内容,找到文件的第一个扇区,读入第一个盘块并查看其内容;

根据题目要求,我们首先创建一个helloOS.txt的文件,然后在里面写上重复的Hello Operating system(图3-1)。

图 3?1 重复hello

为了解读其节点号,我们查阅资料得知,需要使用df指令,df指令主要来检查文件系统的磁盘空间占用情况,并且-i是来查看inode的节点信息的(图3-2)。

图 3?2 df参数

根据当前路径以及所查阅的资料, 我们查询helloOS.txt挂载在哪个文件系统下,我们发现是挂载在sda1文件系统下(图3-3)。

图 3?3 df -l查看信息

接着我们根据sda1查看该文件系统的类型,使用df -T的参数(图3-4),发现类型为EXT4。

图 3?4 查看文件系统类型

接着我们根据1.9,使用dumpe2fs查看sda1的文件系统的详细信息(图3-5),可以看到如下详细信息:

Inode大小为256字节

每组块存放8192个inode

每个block占用4096字节大小

系统中block总数为20971008个

系统里面inode总数为524880个

每组块里存放了inode的block数目为512块

图 3?5 dumpe2fs 查看信息

做个简单的计算,根据上述信息,每个block占用4096个字节,而每个inode占用256字节,4096/256=16,也就是每个块有16个inode,而每组块有512个block有inode,16*512=8192,与上图中inodes per group=8192相吻合。

根据stat指令简介(图3-6),我们可以使用其查看当前文件inode信息,主要是inode号,可以看到inode号为3804467(图3-7)。

图 3?6 stat指令

图 3?7 helloOS的详细信息

首先计算组号,因为每组有8192个inode,且inode是从1开始计数的,所以(3804467-1)/8192=464(组),根据刚刚dumpe2fs指令的结果,我们可以看到3144271-3415760刚好等于511(图3-8)。

图 3?8 464组号相关信息

然后我们根据上述信息计算:

inode表里面的索引值=inode编号%组内inode数目=(3804467-1)%8192=3378。也就是3804467号的inode第464组里面的偏移3378号的inode是目标inode,

因为一个block占4096字节,每个block只能有4096/16=16个inode,所以计算组内盘块号=组内索引/每个盘块有多少个inode=3378/16=211。

该inode在组内291盘块上,对应的偏移也是3378%16=2。

所以最终inode字节位置为(inode表起始盘块+inode组内盘块号)*盘块大小+盘块内偏移*inode大小=(15204384+211)*4096+2*256=62,278,021,632(byte)。

然后我们通过hexdump工具查看inode的内容(图3-9),结合图3-9我们知道在4字节偏移处为inode大小,查看得知为392,与源文件大小392字节相等,所以证明我们找到了inode(图3-10)。

图 3?9 ext4的inode结构体

图 3?10 hexdump查看inode

查阅资料得知,我们的inode中显示block地址在60字节偏移处(图3-11),此时我们查找60字节偏移处,因为是小端存储,所以块地址为0x00a138ce=10565838(图3-12)。

图 3?11 inode结构体中block偏移

图 3?12 查看块地址

我们尝试使用dd指令读取文件内容块地址为10565838的内容,首先我们先使用debugfs指令检查helloOS.txt文件的所在块号,也是10565838号!说明我们的计算正确,然后使用dd指令输出到out.txt文件中(图3-14),其中if=输入文件;of=输出文件;bs=步长;count=扫描的数目;skip=跳过的块数,并且查看结果(图3-15),发现正是我们文件的内容!

图 3?13 debugfs检查块号

图 3?14 dd输出对应快内容

图 3?15 输出结果

学习Linux文件系统中关于文件硬链接和软链接的概念和相关操作命令,创建软硬链接各一个,用tree命令、ls -l和ls -i命令查看和对比它们的不同;

我们在demo4文件夹中创建soft_and_hard.txt并且对其添加hardlink.txt的硬链接以及softlink.txt的软连接(图4-1),然后通过tree查看链接情况,发现softlink已经软连接到了soft_and_hard上面(图4-2)。

图 4?1 创建文件以及添加软硬连接

图 4?2 tree

然后通过ls -l查看目录下文件信息,发现hard_and_soft的硬链接计数和hardlink计数是相等的,都等于2,根据硬链接的定义,他们都是指向同一个文件的,但是softlink的连接计数为1,也就是被系统当做单独的文件,因为他的inode只记录了原文件的目录,与源文件不同内容的(图4-3),通过ls -i也能验证上述结论,就是hardlink与soft_and_hard有相同的inode号,也就是3804470,而softlink的不同,为3804471(图4-4)。

图 4?3 ls -l

图 4?4 ls -i

创建一个1GB的大文件,读入全部数据到内存中并记录所花时间,然后进行第二次读入并记录时间。(20%)

要求:用/proc/meminfo查看内存中页缓存使用的变化,并解释两次读入速度差异的原因。

我们首先使用dd命令创建一个bigFile.txt的大文件,输入为/dev/sda1 输出为该文件,大小为1G(图5-1)。

图 5?1 dd创建1G大文件

然后我们编写一个bigfile.c的代码文件,主要思路就是先创建一个1G缓冲区,然后文件流打开并读取,开始计时,读取完毕就结束计时,然后再按照相同操作操作一次(图5-2)。

图 5?2 bigfile.c

然后我们打开编译后的bigfile开始测试,首先不读取任何文件(图5-3),然后查看/proc/meminfo信息,可以发现cached有164268KB(图5-4),然后我们继续运行,第一次扫描用时6.53秒,然后查看meminfo发现cached增加到了173372KB(图5-5),然后运行第二次,发现用时比之前快了许多,仅有4.70秒(图5-6)。

图 5?3 不读取

图 5?4 meminfo查看cached

图 5?5 读取一次

图 5?6 查看meminfo

图 5?7 读取第二次

根据上述数据,我们可以得出:由于meminfo的cached页面明显增多,说明第一次读取文件的时候有许多数据进入了cached,然后第二次读取的时候直接读取cached比第一次读取的时候读取磁盘会快很多,虽然不是全部文件都进了cached,但也是优化了1秒多,快了许多。

利用df命令查看并解读文件系统的信息,学习mount/unmount命令如何将光驱或U盘挂载到系统中,并体验windows盘符和linux无盘符概念的差异。

我们在linux系统中直接使用df命令,可以看到第一列为文件系统的名字,第二列指block块的数目总量,第三列是已被使用的block量,第四列是可用块数目,USE%是使用占比,Mounted on是指挂载在哪个目录下,以/dev/sda1为例,他是挂载在”/”目录下的(图6-1)。

图 6?1 df命令

根据df参数介绍(图6-2),我们使用df -HT来查看文件系统信息,可以看到相较于df指令,他把size变成了我们常用的KB/MB/GB来划分,并且给出了文件系统的类型和挂载目录(图6-2)。

图 6?2 df参数介绍

图 6?3 df -HT

接着我们关闭虚拟机,在虚拟机中挂载一个iso文件,图中挂载了一个centos的iso文件(图6-4)。

图 6?4 挂载iso文件

接着我们开机,可以看到光盘显示在桌面上了(图6-5)。

图 6?5 iso文件读入

查看df -h指令,我们可以看到iso文件挂载在了/dev/sr0(图6-6)。

图 6?6 iso文件挂载目录

然后由于使用mount指令,我们查阅资料后明白mount的参数使用(图6-7),然后根据这个挂载到/home/liujunnan-2017303010/demo4/cdiso中(图6-8),然后进入cdiso目录查看,发现挂载成功(图6-9)。

图 6?7 mount参数

图 6?8 挂载到cdiso目录中

图 6?9 cdiso目录下文件查看

我们尝试使用umount命令卸载./cdiso,然后进入iso目录查看(图6-10),发现不挂载进不去(图6-10)。

图 6?10 卸载后无法进入iso目录

Linux与windows相比挂载移动存储设备十分不同,windows系统里面对于移动存储设备或者虚拟存储器,系统会自动分配一个盘符作为根目录,我们直接根据盘符访问就可访问文件(图6-11),但是在linux里面需要挂载,因为linux认为阴间设备也是文件,他们有各自文件系统,必须统一文件系统才能访问,这个统一的过程叫做挂载。

图 6?11 windows挂载

查看c语言提供的fopen/fclose/fread/fwrite函数和操作系统直接对应的open/close/read/write两套接口的差异,弄清楚字符模式和二进制流模式是哪一层面的概念。

查阅资料得知:open/close/read/write是低级IO, 是系统调用函数,而fopen/fclose/fread/fwrite是高级IO,是标准库中的函数,后者是由前者实现的。

open() 打开一个文件并返回它的句柄如果失败,将返回一个小于0的值,原型是int open(const char *path, int access [, unsigned mode]); 参数path是要打开的文件名,access是打开的模式,mode是可选项。表示文件的属性,主要用于UNIX系统中,在DOS/WINDOWS这个参数没有意义。

close() 关闭一个句柄,原型是int close(int handle);如果成功返回0

read() 块读文件,原型是int read(int handle, void *buf, unsigned len);参数buf保存读出的数据,len是读取的字节。函数返回实际读出的字节。

write() 块写文件,原型是int write(int handle, void *buf, unsigned len);参数的含义同read(),返回实际写入的字节。

1.fopen的原型是:FILE *fopen(const char *filename,const char *mode),fopen实现三个功能

为使用而打开一个流

把一个文件和此流相连接

给此流返回一个FILR指针

参数filename指向要打开的文件名,mode表示打开状态的字符串

fclose()的功能就是关闭用fopen()打开的文件,其原型是:int fclose(FILE *fp);如果成功,返回0,失败返回EOF。

fread的功能是从流中读指定个数的字符,原型是size_t fread(void *ptr, size_t size, size_t n, FILE *stream);参数ptr是保存读取的数据,void*的指针可用任何类型的指针来替换,如char*、int *等等来替换;size是每块的字节数;n是读取的块数,如果成功,返回实际读取的块数(不是字节数),本函数一般用于二进制模式打开的文件中。

fwrite与fread对应,向流中写指定的数据,原型是size_t fwrite(const void *ptr, size_t size, size_t n, FILE *stream);参数ptr是要写入的数据指针,void*的指针可用任何类型的指针来替换,如char*、int *等等来替换;size是每块的字节数;n是要写的块数,如果成功,返回实际写入的块数(不是字节数),本函数一般用于二进制模式打开的文件中。

对于open与fopen区别:

open是系统调用,返回的是文件句柄,文件的句柄是文件在文件描述副表里的索引,fopen是ANSIC标准中的C语言库函数,返回的是一个指向文件结构的指针)(图7-1)。

fopen用户态下就有了缓存,它使用了FILE这个结构保存缓冲数据。在进行read和write的时候减少了用户态和内核态的切换。而open没有缓存,每次读操作都直接从文件系统中获取数据。在进行read和write的时候每次都需要进行内核态和用户态的切换。

一般用fopen打开普通文件,用open打开设备文件。

图 7?1 fopen

我们看看write / read 和 fwrite / fread 的接口(图7-2),read与write作为系统调用,只需要指定读取和写的字节数count即可,但是fwrite与fread需要提供size也就是单个元素的大小,这意味着write/read是二进制流模式,直接读取字节,字符流是fwrite/fread用户层面的,按照对象大小灵活访问数据。

图 7?2 接口

一个文件可以以文本模式或二进制模式打开,这两种的区别是:在文本模式中回车被当成一个字符'\n',而二进制模式认为它是两个字符0x0D, 0x0A;如果在文件中读到0x1B,文本模式会认为这是文件结束符,也就是二进制模型不会对文件进行处理,而文本方式会按一定的方式对数据作相应的转换。

根据上述分析,我们可以推测出,二进制流是系统的层面,不分析单个元素的单位大小,而字符流是用户层面的,用户根据操作系统的二进制数据解析出字符流,解析的时候发生在用户空间。

思考文件读写指针(游标概念)属于文件的逻辑抽象管理数据还是属于磁盘文件管理数据?文件指针是否需要保存在磁盘上,如果在磁盘上应该如何存放?如果在内存中又如何存放?

通过分析fopen我们可以知道,该函数返回一个FILE*类型的指针变量,也就是文件指针。

从概念上来看,文件指针属于逻辑抽象管理数据。

但是从应用上看,linux文件指针存在于PCB中,也就是内存,而不是磁盘中,每次打开新文件都会获得从头开始的文件指针。

如果文件指针保存在磁盘上,则他应该在inode、FAT表或者是block中某个特定的位置,因为文件指针是互斥变量,那么每个block都有指针的话,就不能实现并行。

如果文件指针在内存中,那么必须存放在PCB中,这也意味着多个进程可以以不同进度访问同一个文件,使得系统更加健壮,也让系统支持并行。

四、实验体会:(根据自己情况填写)

通过本次实验,我受益匪浅:

  1. 通过对linux文件系统的实验,我明白了ln用于链接文件的作用,并且明白了touch指令用于创建新文件,rm用于删除,cp用于拷贝,mv用于移动重命名,mkdir用于新建目录
  2. 明白了EXT2文件系统的基本结构,大部分linux系统都是用的EXT2文件系统,明白了inode的计算方法,明白了使用df查看磁盘空间以及文件系统类型,debugfs查看文件所属盘块,hexdumpfs查看二进制文件内容,dd查看对应盘块内容。
  3. 明白了cache对于读写文件的加速效果,以及cache存在的必要性。
  4. 明白了可以使用ls -I 和ls -l 查看链接情况,并且每个文件的inode根据软硬连接的不同情况不同。
  5. 明白了mount和umount的作用,以及挂载对于linux 的必要性和与windows系统的挂载区别。
  6. 明白了linux读写文件的两种不同形式,分别是二进制流形式和字符形式。



相关推荐

“版本末期”了?下周平衡补丁!国服最强5套牌!上分首选

明天,酒馆战棋就将迎来大更新,也聊了很多天战棋相关的内容了,趁此机会,给兄弟们穿插一篇构筑模式的卡组推荐!老规矩,我们先来看10职业胜率。目前10职业胜率排名与一周前基本类似,没有太多的变化。平衡补丁...

VS2017 C++ 程序报错“error C2065:“M_PI”: 未声明的标识符"

首先,程序中头文件的选择,要选择头文件,在文件中是没有对M_PI的定义的。选择:项目——>”XXX属性"——>配置属性——>C/C++——>预处理器——>预处理器定义,...

东营交警实名曝光一批酒驾人员名单 88人受处罚

齐鲁网·闪电新闻5月24日讯酒后驾驶是对自己和他人生命安全极不负责的行为,为守护大家的平安出行路,东营交警一直将酒驾作为重点打击对象。5月23日,东营交警公布最新一批饮酒、醉酒名单。对以下驾驶人醉酒...

Qt界面——搭配QCustomPlot(qt platform)

这是我第一个使用QCustomPlot控件的上位机,通过串口精确的5ms发送一次数据,再将读取的数据绘制到图表中。界面方面,尝试卡片式设计,外加QSS简单的配了个色。QCustomPlot官网:Qt...

大话西游2分享赢取种族坐骑手办!PK趣闻录由你书写

老友相聚,仗剑江湖!《大话西游2》2021全民PK季4月激燃打响,各PK玩法鏖战齐开,零门槛参与热情高涨。PK季期间,不仅各种玩法奖励丰厚,参与PK趣闻录活动,投稿自己在PK季遇到的趣事,还有机会带走...

测试谷歌VS Code AI 编程插件 Gemini Code Assist

用ClaudeSonnet3.7的天气测试编码,让谷歌VSCodeAI编程插件GeminiCodeAssist自动编程。生成的文件在浏览器中的效果如下:(附源代码)VSCode...

顾爷想知道第4.5期 国服便利性到底需优化啥?

前段时间DNF国服推出了名为“阿拉德B计划”的系列改版计划,截至目前我们已经看到了两项实装。不过关于便利性上,国服似乎还有很多路要走。自从顾爷回归DNF以来,几乎每天都在跟我抱怨关于DNF里面各种各样...

掌握Visual Studio项目配置【基础篇】

1.前言VisualStudio是Windows上最常用的C++集成开发环境之一,简称VS。VS功能十分强大,对应的,其配置系统较为复杂。不管是对于初学者还是有一定开发经验的开发者来说,捋清楚VS...

还嫌LED驱动设计套路深?那就来看看这篇文章吧

随着LED在各个领域的不同应用需求,LED驱动电路也在不断进步和发展。本文从LED的特性入手,推导出适合LED的电源驱动类型,再进一步介绍各类LED驱动设计。设计必读:LED四个关键特性特性一:非线...

Visual Studio Community 2022(VS2022)安装图文方法

直接上步骤:1,首先可以下载安装一个VisualStudio安装器,叫做VisualStudioinstaller。这个安装文件很小,很快就安装完成了。2,打开VisualStudioins...

Qt添加MSVC构建套件的方法(qt添加c++11)

前言有些时候,在Windows下因为某些需求需要使用MSVC编译器对程序进行编译,假设我们安装Qt的时候又只是安装了MingW构建套件,那么此时我们该如何给现有的Qt添加一个MSVC构建套件呢?本文以...

Qt为什么站稳c++GUI的top1(qt c)

为什么现在QT越来越成为c++界面编程的第一选择,从事QT编程多年,在这之前做C++界面都是基于MFC。当时为什么会从MFC转到QT?主要原因是MFC开发界面想做得好看一些十分困难,引用第三方基于MF...

qt开发IDE应该选择VS还是qt creator

如果一个公司选择了qt来开发自己的产品,在面临IDE的选择时会出现vs或者qtcreator,选择qt的IDE需要结合产品需求、部署平台、项目定位、程序猿本身和公司战略,因为大的软件产品需要明确IDE...

Qt 5.14.2超详细安装教程,不会来打我

Qt简介Qt(官方发音[kju:t],音同cute)是一个跨平台的C++开库,主要用来开发图形用户界面(GraphicalUserInterface,GUI)程序。Qt是纯C++开...

Cygwin配置与使用(四)——VI字体和颜色的配置

简介:VI的操作模式,基本上VI可以分为三种状态,分别是命令模式(commandmode)、插入模式(Insertmode)和底行模式(lastlinemode),各模式的功能区分如下:1)...

取消回复欢迎 发表评论: