Chinaunix首页 | 论坛 | 博客
  • 博客访问: 243112
  • 博文数量: 52
  • 博客积分: 285
  • 博客等级: 二等列兵
  • 技术积分: 585
  • 用 户 组: 普通用户
  • 注册时间: 2012-04-25 23:38
文章分类

全部博文(52)

文章存档

2013年(43)

2012年(9)

我的朋友

分类: LINUX

2013-06-08 13:02:20

早晨来到图书馆,本想把《you and your research》读完,这两天微雨,还算凉爽,竟不能静心。周围弥漫了各种浮躁的气息。my poor English makes the impetuous heart more impetuous.索性做些容易进入状态的事。把昨天的知识点做下回顾。
《linux 内核设计艺术》第三章 安装文件系统  
内核加载根文件系统以后,进程已经具备了“依托系统与外设以文件形式进行数据交互”的能力,但此时所指的外设仅限于根设备,即虚拟盘,进程还不能与硬盘以文件的形式进行数据交互,因为沿着根i节点。在虚拟盘上尚无法找到与硬盘上的文件有关的信息。所以,要让进程“依托系统”与硬盘也能以文件的形式进行数据交互,即安装一个关于硬盘的文件系统,使之与根文件系统建立关系。
安装文件系统分为三步:
1)将硬盘上的超级块读取出来,并载入到系统的超级块管理结构super_block[8]中.
2)将虚拟盘上指定的i节点读出,并将此i节点加载到系统的i节点管理结构inode_table[32]中
3)将硬盘上的超级块挂接到inode_table[32]中指定的i节点上,以此来安装文件系统
文件系统将为硬盘的文件操作提供最关键的数据和操作支持.
硬盘的文件系统安装成功后,用户程序如果需要操作硬盘上的文件,就可以从根i节点开始查找,直至找到mnt这个目录文件的i节点,之后以此为参照,找到硬盘的超级块,最后再通过硬盘的超级块,一步一步的找到硬盘上指定的文件
1.shell终端:mount /dev/hd1 /mnt 2.shell进程接到该命令后,会创建一个新进程,然后该新进程调用mount函数产生软中断,并最终映射到sys_mount这个系统调用函数中去执行。这个过程在此不再讨论
3.在硬盘的超级块结构中,有s_imount成员变量,这个点就是安装点。我们要实现的是得到这个安装点,和虚拟盘中mnt的挂接点,然后进行挂接.为了得到s_imount安装点,系统要先把它所在位置-硬盘中的超级块读进内存中,而如果想读出超级块,就要先得到这个硬盘的设备号
------------------------------------------------------------------------------------------------------------------
在分析sys_mount()函数前,想做下补充:
为何以文件的形式访问硬盘数据,直接以扇区的方式对硬盘进行访问不行吗?
《linux 内核设计艺术》 第四章 文件操作(打字过程中,小部分有改动,个人语序习惯^^)
不能说不行,但是存在许多问题。通常情况下,用户所要使用的数据都要大于一个扇区,这就需要多个扇区来存储。比较简单的方式是,将这些数据存储在一段物理连续的扇区.但在数据使用过程中,不断的被修改,删除和添加,硬盘中很快就会产生大量没有存储数据的碎片,而且理论和实际都表明,碎片会越来越多,最终整个硬盘几乎被碎片填满,比碎片尺寸大的数据将无法利用这些碎片。硬盘虽然有大量未用空间,却无法写入数据,造成浪费.
     操作系统的设计想出了“以碎制碎”策略。把硬盘的存储空间,人为分成许多规则的小块,把数据存储在这样的块中,这就是块设备的由来。通常,块大小是扇区大小的整数倍,不同的操作系统块的大小略有不同。linux 0.11,一个块大小是1KB(两个扇区)
     为了实现这个创意,操作系统的设计者提出了文件系统的设计方案。不仅如此,文件系统还解决了在存储数据时不会覆盖已经存在的数据的问题。这一点,意义重大。
     1.文件系统首先设计了一个数据结构,管理属于同一个文件的所有的块。对于linux 0.11来说,这个数据结构就是i节点.由于i节点的数量极其庞大,需要一个数据结构管理i节点的使用情况,这个数据结构就是i节点位图.
     2.另外,硬盘上的块数量也是极其庞大的,同样需要一个数据结构来标识块的使用情况,这个数据结构就是逻辑块位图
     3.以上这些数据结构的功能,大小,所处位置各不相同,需要一个总的数据结构来管理,这个数据结构就是超级块
so:
     1."超级块->逻辑块位图->数据块",这条路线可以查找到硬盘上的空闲数据块;
     2.“超级块->i节点位图->i节点表中的i节点->数据块”,这条路线可以访问到文件中指定的数据块.
------------------------------------------------------------------------------------------------------------------------
from:《linux 内核完全注释》
//// 安装文件系统调用函数
// 参数dev_name 是设备文件名,dir_name 是安装到的目录名,rw_flag 被安装文件的读写标志
// 将被加载的地方必须是一个目录名,并且对应的i 节点没有被其它程序占用
200 int sys_mount(char * dev_name, char * dir_name, int rw_flag)
201 {
202     struct m_inode * dev_i, * dir_i;
203     struct super_block * sb;
204     int dev;
205
// 首先根据设备文件名找到对应的i 节点,并取其中的设备号
// 对于块特殊设备文件,设备号在i 节点的i_zone[0]中
206     if (!(dev_i=namei(dev_name))
207         return -ENOENT;
208     dev = dev_i->i_zone[0];
// 如果不是块设备文件,则释放刚取得的i 节点dev_i,返回出错码。
209     if (!S_ISBLK(dev_i->i_mode)) {
210          iput(dev_i);
211          return -EPERM;
212     }
// 释放该设备文件的i 节点dev_i。 213     iput(dev_i);
// 根据给定的目录文件名找到对应的i 节点dir_i。
214     if (!(dir_i=namei(dir_name)))
215          return -ENOENT;
// 如果该i 节点的引用计数不为1(仅在这里引用),或者该i 节点的节点号是根文件系统的节点
9.7 super.c 程序
- 305 -
// 号1,则释放该i 节点,返回出错码。
216     if (dir_i->i_count != 1 || dir_i->i_num == ROOT_INO) {
217          iput(dir_i);
218          return -EBUSY;
219     }
// 如果该节点不是一个目录文件节点,则也释放该i 节点,返回出错码。
220     if (!S_ISDIR(dir_i->i_mode)) {
221         iput(dir_i);
222         return -EPERM;
223     }
// 读取将安装文件系统的超级块,如果失败则也释放该i 节点,返回出错码。
224     if (!(sb=read_super(dev))) {
225         iput(dir_i);
226         return -EBUSY;
227     }
// 如果将要被安装的文件系统已经安装在其它地方,则释放该i 节点,返回出错码。
228     if (sb->s_imount) {
229         iput(dir_i);
230         return -EBUSY;
231    }
// 如果将要安装到的i 节点已经安装了文件系统(安装标志已经置位),则释放该i 节点,返回出错码。
232     if (dir_i->i_mount) {
233        iput(dir_i);
234        return -EPERM;
235     }
// 被安装文件系统超级块的“被安装到i 节点”字段指向安装到的目录名的i 节点。 236    sb->s_imount=dir_i;
// 设置安装位置i 节点的安装标志和节点已修改标志。/* 注意!这里没有iput(dir_i) */
237    dir_i->i_mount=1; /* 这将在umount 内操作 */
238    dir_i->i_dirt=1; /* NOTE! we don't iput(dir_i) */
239    return 0; /* we do that in umount */
240 }
241
ps:
呵,关于文件系统的知识点,是在调试linux 0.11过程中开始关注的。well,just for fun.
阅读(1867) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~