文件的物理结构和逻辑结构

以C语言创建顺序文件为例

typedef struct{
   int number;//学号
   char name[30];//姓名
   char major[30];//专业
}Student_info;

//以“写”方式打开文件
FILE *fp = fopen("students.info","w");
if(fp == NULL){
   printf("打开文件失败!");
   exit(0);
}
Student_info student[N];//用数组保存N个学生信息
for(int i = 0;i<n;i++){  //生成n个学生信息
   student[i].number = i;
   student[i].name = '?';
   student[i].major[0] = '?';
}

//将N个学生的信息写入文件
fwrite(student,sizeof(Student_info),N,fp);
fclose(fp);

调用了fwrite()函数之后,其实刚才我们定义的这n个学生的信息,这N个Struct结构体就会被保存到磁盘里 ,在我们自己看来每一个学生是占64B,因为这个int型的变量,它是占4个字节,然后下面这两个char型数组分别又占30B,所以,每一个学生信息,每一个Struct结构体它总共是64B,当然更简单的方法,其实,我们只需要用C语言提供的sizeof()就可以得出每一个学生记录他的大小是多少,所以,基于我们自己的视角,如果,我们想要在文件里面读出第5个学生的信息,第5个学生所对应的记录,那么我们只需要用这样的一段代码就可以实现。


总之,在我们用户看来每一个学生的记录,它似乎就是连续存放的,并且每个学生的它所占的空间大小是相同的,所以,当我们想要从文件里面读出某一个学生对应的记录的时候,其实我们就可以方便的算出那一条记录所对应的逻辑地址,总之,我们只需要给操作系统提供我们想要访问的逻辑地址,那么接下来的事情,操作系统会替我们完成。事实上,在背后,从操作系统的视角来看,他同样的是把我们这一整个文件的数据,把他切分成了一个一个的小块,每一块的大小就是和磁盘块保持一致,比如说都是1KB,操作系统,当然可以采用连续分配的方式来存储这些逻辑块,也可以采用连接分配,也可以采用索引分配,但是它到底采用了哪种分配方式,我们其实是不得而知的,也必要关心,反正我们作为用户只需要作为提供我们想要访问的记录它所存放的逻辑地址,然后剩下的这个逻辑地址转换逻辑块号,逻辑块号再转换成物理块号,这些事情都是操作系统在背后帮我们完成的


好了,刚才我们给出的这个例子中,这个例子的文件是采用了顺序存储的方式,也就是这些逻辑上相邻的记录是一个连一个,都是相邻的存放的,其实当我们在存储这些记录的时候,我们当然也可以使用链式存储的方式来实现。比如说,当我们在定义这个学生信息的时候,我们可以再增加这样一个字段next,这个字段是指向了下一个学生记录的存放位置,那和之前类似,我们也可以定义一个比如说长度为10000的这个Student_info数组,也就是说,如果,最多我们总共可以存10000个学生的信息,那0号学生的信息,比如说,它是存在数组下标为0的这个位置,那么我们可以在这个学生对应的这个结构体中记录下一个学生,也就是一号学生他的存放位置,那他存在数组下标为3的地方,所以0号学生对应的结构体中,这个next变量我们可以把他设置为3,这样的话,其实就相当于我们建立了一个指向下一个记录的指针,那这不就是所谓的链式存储吗。我们所以学生的数据是存放在这样的一大片连续空间中,但是各个逻辑上相邻的学生数据,我们又是通过这种链接指针的方式把他们连在一起的,所以,这就是所谓顺序文件的链式存储,这其实是以我们用户自己来设计的,那如果我们采用上面这种顺序存储的方式来存放各个学生记录的话,那我们可以很方便算出第i个学生他的记录存放的地址,然后用这个逻辑地址就可以直接命中我们想要找的那条记录,而如果我们采用的是下面这种链式存储的方式,那我们想要找到第i个学生的记录,那我们只有先读入第一个学生的记录,然后一个一个往后找,其实,这就和数据结构里面的顺序表和链表都是一样的。总之,当我们在创建一个文件的时候,我们可以这就来决定到底是用顺序存储的方式来存放这些记录,还是用链式存储的方式来存放这些记录,但是无论如何,在我们自己看来,这些记录,他肯定都是占用了一整片的连续空间,这是从我们的视角来看到的东西


那从操作系统的视角来看,刚才我们实现的这种链式存储的顺序文件,其实操作系统在背后也会把他拆分成1KB,1KB这样的一个一个的块,然后这些物理块操作系统在背后有可能会产生用连续分配的方式把他们存放在磁盘中,当然,也可以采用链接分配的方式,把他们存放在磁盘当中。注意,我们在讲逻辑结构的时候,讲到顺序文件可以采用链式存储的方式,在讲物理结构的时候,我们又讲到了链接分配的方式,这两个东西看起来很像,其实文件的逻辑结构里面,我们聊到所谓的链式存储指的是,我们在文件的内部,这一些记录的先后顺序,我们是用链接指针把他们连起来的,这是由我们文件主自己来设计的;那在文件的物理结构里面提到的所谓的链接分配,其实,这个链接是操作系统做的事情,操作系统会把我们给出的这一整个很大的文件把他拆分成一个一个的逻辑块,然后在磁盘里面存放这些逻辑块的时候,操作系统会用链接的方式来记录这些逻辑块他们之间的先后顺序。总之,在讲文件逻辑结构的时候,我们谈到的链式存储,其实这些信息是我们用户需要关心的,操作系统他并不管,而文件的物理结构结构里面我们提到的链接分配,这些链接信息是操作系统需要关心的,我们用户并不需要管。


在学习文件的逻辑结构的时候,我们提到过索引文件这种索引结构,那如果,我们要自己实现索引文件这种逻辑结构的话,可以怎么做呢,我们可以先定义这样一个结构体,这样的一个结构体就是对应了一个索引项,每一个索引项记录了学生的学号还有这个学生记录它所存放的逻辑地址,就是记录了这样一个映射关系,那我们之前介绍的额那段代码,其实已经告诉大家怎么把Struct结构体存到文件里面了,那用类似的办法,我们当然可以把这些一个一个的IndexTable这种Struct结构体存到我们的文件里面,每一个IndexTable对应一个索引项,然后接下来的这一片空间,我们可以定义一个长长的Studentinfo这样一个数组,然后这个数组中存入各个学生的信息,然后我们的各个索引项会建立起学号还有各个学生信息的这种映射关系,这个例子其实就是一个索引文件,这种逻辑结构同样也是由我们,由文件的创建者自己来决定的,比如说,我们可以规定在我们这个文件前边的1MB我们存放的都是索引项的信息,然后后边的这些部分,我们存放的是这些一条一条的记录相关的信息,所以,当我们想要根据学生的学号找到这个学生所对应的记录的的时候,我们就可以先把这前边的1MB的这些数据先给读进来,然后,查询我们的这些索引项,找到目标学生它的索引项,然后再根据这个索引项的信息确定目标学生它的记录到底存放在哪一个逻辑地址中,然后接下来再来读取这个学生的信息就可以了。


总之,对于索引文件的这种文件结构,其实在我们用户看来,我们的这整个文件,他依然是连续存放的,依然是占有了一整片的连续空间,然而在背后操作系统其实同样的会把我们的这一整个文件,把他拆分成1KB,1KB这样一个一个小块,然后操作系统会把这些小块存放在磁盘里面,当然,可以采用连续分配,链接分配,也可以采用索引分配的方式,也就是说,操作系统会维护一个索引表,那这个索引表是记录了各个逻辑块号到物理块号之间的映射关系。注意:我们在逻辑结构里面讲到的所谓的索引文件,这个索引文件的索引表其实是由文件主,由用户自己来建立的,这个索引表记录的是各个关键字到记录存放的逻辑地址之间的一个映射关系,而我们在文件的物理结构里面提到的文件的索引分配,这也有一个索引表,这个索引表其实是由操作系统建立的,它是实现了逻辑块号到物理块号之间的映射关系,所以,索引文件这种逻辑结构和索引分配这种物理结构完全是两个维度的东西。

总结


例如:以上就是今天要讲的内容,本文以C语言创建顺序文件为例,剖析了文件的物理结构和逻辑结构

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值