操作系统课程设计超级块处理.doc_第1页
操作系统课程设计超级块处理.doc_第2页
操作系统课程设计超级块处理.doc_第3页
操作系统课程设计超级块处理.doc_第4页
操作系统课程设计超级块处理.doc_第5页
已阅读5页,还剩19页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

华东交通大学课程设计报告第1章 课程设计目的1. 通过Linux操作系统源码分析,深刻理解系统的底层知识(如系统的引导和硬件提供的中断机制等,多任务机制,系统保护机制等等);2. 加深学生对操作系统所涉及的概念、算法、数据结构的理解;体验操作系统所涉及的抽象思维的具体实现;激励学生在操作系统设计方面的创新精神;培养正规系统程序设计的思想; 3. 从了解操作系统的整体结构,体会整体设计在软件设计中的份量和作用,以及一些宏观设计的方法和技巧(Linux的内核为上层应用提供一个与具体硬件不相关的平台;同时在内核内部,它又把代码分为与体系结构和硬件相关的部分以及可移植的部分;Linux虽然不是微内核的,但他把大部分的设备驱动处理成相对独立的内核模块,这样减小了内核运行的开销,增强了内核代码的模块独立性)。4.在源码的分析过程中,体会代码的清晰性,兼容性,可移植性的重要作用。例如,可以通过定义大量的宏,来增强代码的清晰度和可读性,而又不增加编译后的代码长度和代码的运行效率;可移植性使得大家在以后编码过程中,兼顾到后续的代码维护和升级。第2章超级块整体功能介绍及主要目标 linux硬盘组织方式为:引导区、超级块(superblock),索引结点(inode),数据块(datablock),目录块(diredtory block)。其中超级块中包含了关于该硬盘或分区上的文件系统的整体信息,如文件系统的大小等;超级块后面的数据结构是索引结点,它包含了针对某一个具体文件的几乎全部信息,如文件的存取权限、所有者、大小、建立时间以及对应的目录块和数据块等;数据块是真正存储文件内容的位置。但是索引结点中不包括文件的名字,文件名是放在目录块里的。目录块里包含有文件的名字以及此文件的索引结点编号。超级块文件描述了对文件系统中超级块操作的函数,这些函数属于文件系统低层函数,供上层的文件名和目录操作函数使用。主要有get_super()、put_super()和read_super()。另外还有2 个有关文件系统加载/卸载系统调用sys_umount()和sys_mount(),以及根文件系统加载函数mount_root()。其它一些辅助函数与buffer.c中的辅助函数的作用类似。get_super()函数用于在指定设备的条件下,在内存超级块数组中搜索对应的超级块,并返回相应超级块的指针。因此,在调用该函数时,该相应的文件系统必须已经被加载(mount),或者起码该超级块已经占用了超级块数组中的一项,否则返回NULL。put_super()用于释放指定设备的超级块。它把该超级块对应的文件系统的i 节点位图和逻辑块位图所占用的缓冲块都释放掉。在调用umount()卸载一个文件系统或者更换磁盘时将会调用该函数。read_super()用于把指定设备的文件系统的超级块读入到缓冲区中,并登记到超级块数组中,同时也把文件系统的i 节点位图和逻辑块位图读入内存超级块结构的相应数组中。最后并返回该超级块结构的指针。sys_umount()系统调用用于卸载一个指定设备文件名的文件系统,而sys_mount()则用于往一个目录名上加载一个文件系统。程序中最后一个函数mount_root()是用于安装系统的根文件系统,并将在系统初始化时被调用。其具体操作流程图9.16 所示。图9.16 mount_root()函数的功能该函数除了用于安装系统的根文件系统以外,还对内核使用文件系统起到初始化的作用。它对内存中超级块数组进行了初始化,还对文件描述符数组表file_table进行了初始化,并对根文件系统中的空闲盘块数和空闲i 节点数进行了统计并显示出来。mount_root()函数是在系统执行初始化程序main.c 中,在进程0 创建了第一个子进程(进程1)后被调用的,而且系统仅在这里调用它一次。具体的调用位置是在初始化函数init()的setup()函数中。第3章 数据结构及头文件分析超级块中主要存放了有关整个文件系统的信息,其信息结构参见下列图:头文件分析如下:#include / 内核配置头文件。定义键盘语言和硬盘类型(HD_TYPE)可选项。#include / 调度程序头文件,定义了任务结构task_struct、初始任务0 的数据,/ 还有一些有关描述符参数设置和获取的嵌入式汇编函数宏语句。#include / 内核头文件。含有一些内核常用函数的原形定义。#include / 系统头文件。定义了设置或修改描述符/中断门等的嵌入式汇编宏。#include / 错误号头文件。包含系统中各种出错号。(Linus 从minix 中引进的)。#include / 文件状态头文件。含有文件或文件系统状态结构stat和常量。int sync_dev(int dev); / 对指定设备执行高速缓冲与设备上数据的同步操作。(fs/buffer.c,59)void wait_for_keypress(void); / 等待击键。(kernel/chr_drv/tty_io.c, 140)/* set_bit uses setb, as gas doesnt recognize setc */* set_bit()使用了setb 指令,因为汇编编译器gas 不能识别指令setc */ 测试指定位偏移处比特位的值(0 或1),并返回该比特位值。(应该取名为test_bit()更妥帖)/ 嵌入式汇编宏。参数bitnr 是比特位偏移值,addr 是测试比特位操作的起始地址。/ %0 - ax(_res),%1 - 0,%2 - bitnr,%3 - addr#define set_bit(bitnr,addr) ( register int _res _asm_(ax); _asm_(bt %2,%3;setb %al:=a (_res):a (0),r (bitnr),m (*(addr); _res; )struct super_block super_blockNR_SUPER; / 超级块结构数组。/* this is initialized in init/main.c */* ROOT_DEV 已在init/main.c 中被初始化 */int ROOT_DEV = 0;第4章超级块代码分析4.1锁定指定的超级块 static void lock_super(struct super_block * sb) cli(); / 关中断。while (sb-s_lock) / 如果该超级块已经上锁,则睡眠等待。sleep_on(&(sb-s_wait);sb-s_lock = 1; / 给该超级块加锁(置锁定标志)。sti(); / 开中断。分析流程图如下:4.2对指定超级块解锁 static void free_super(struct super_block * sb) cli(); / 关中断。/sb-s_lock = 0; / 复位锁定标志。wake_up(&(sb-s_wait); / 唤醒等待该超级块的进程。sti(); / 开中断。分析流程图如下:4.3睡眠等待超级块解锁 static void wait_on_super(struct super_block * sb) cli(); / 关中断。 while (sb-s_lock) / 如果超级块已经上锁,则睡眠等待。 sleep_on(&(sb-s_wait); sti(); / 开中断。 分析流程图如下:4.4 系统取指定设备的超级块struct super_block * get_super(int dev)struct super_block * s;/如果没有指定设备,则返回空指针。if (!dev)return NULL;/s 指向超级块数组开始处。搜索整个超级块数组,寻找指定设备的超级块。s = 0+super_block;while (s s_dev = dev) wait_on_super(s);if (s-s_dev = dev)return s;s = 0+super_block;/ 如果当前搜索项不是,则检查下一项。如果没有找到指定的超级块,则返回/空指针。 elses+;return NULL;分析流程图如下:4.5 释放指定设备的超级块/ 释放设备所使用的超级块数组项(置s_dev=0),并释放该设备i 节点位图/和逻辑块位图所占用的高速缓冲块。如果超级块对应的文件系统是根文件系 /统,或者其i 节点上已经安装有其它的文件/ 系统,则不能释放该超级块。void put_super(int dev)struct super_block * sb;struct m_inode * inode;int i;/ 如果指定设备是根文件系统设备,则显示警告信息“根系统盘改变了,准备生死决战吧”,并返回。if (dev = ROOT_DEV) printk(root diskette changed: prepare for armageddonnr);return;/ 如果找不到指定设备的超级块,则返回。if (!(sb = get_super(dev)return;/ 如果该超级块指明本文件系统i 节点上安装有其它的文件系统,则显示警告信息,返回。if (sb-s_imount) printk(Mounted disk changed - tssk, tssknr);return;/ 找到指定设备的超级块后,首先锁定该超级块,然后置该超级块对应的设/备号字段为0,也即即将放弃该超级块。lock_super(sb);1 sb-s_dev = 0;然后释放该设备i 节点位图和逻辑块位图在缓冲区中所占用的缓冲块。brelse(sb-s_imapi);brelse(sb-s_zmapi);/ 最后对该超级块解锁,并返回。free_super(sb);return;分析流程图如下:4.6 从设备上读取超级块到缓冲区中/ 如果该设备的超级块已经在高速缓冲中并且有效,则直接返回该超级块的指针。static struct super_block * read_super(int dev)struct super_block * s;struct buffer_head * bh;int i,block;/ 如果没有指明设备,则返回空指针。if (!dev)return NULL;/ 首先检查该设备是否可更换过盘片(也即是否是软盘设备),如果更换过盘,则高速缓冲区有关该/ 设备的所有缓冲块均失效,需要进行失效处理(释放原来加载的文件系统)。check_disk_change(dev);/ 如果该设备的超级块已经在高速缓冲中,则直接返回该超级块的指针。if (s = get_super(dev)return s;/ 否则,首先在超级块数组中找出一个空项(也即其s_dev=0 的项)。如果数组已经占满则返回空指针。for (s = 0+super_block ; s+) if (s = NR_SUPER+super_block)return NULL;if (!s-s_dev)break;/ 找到超级块空项后,就将该超级块用于指定设备,对该超级块的内存项进行部分初始化。s-s_dev = dev;s-s_isup = NULL;s-s_imount = NULL;s-s_time = 0;s-s_rd_only = 0;s-s_dirt = 0;/ 然后锁定该超级块,并从设备上读取超级块信息到bh 指向的缓冲区中。如果读超级块操作失败,/ 则释放上面选定的超级块数组中的项,并解锁该项,返回空指针退出。lock_super(s);if (!(bh = bread(dev,1) s-s_dev=0;free_super(s);return NULL;/ 将设备上读取的超级块信息复制到超级块数组相应项结构中。并释放存放读取信息的高速缓冲块。*(struct d_super_block *) s) =*(struct d_super_block *) bh-b_data);brelse(bh);/ 如果读取的超级块的文件系统魔数字段内容不对,说明设备上不是正确的文件系统,因此同上面/ 一样,释放上面选定的超级块数组中的项,并解锁该项,返回空指针退出。/ 对于该版linux 内核,只支持minix 文件系统版本1.0,其魔数是0x137f。if (s-s_magic != SUPER_MAGIC) s-s_dev = 0;free_super(s);return NULL;/ 下面开始读取设备上i 节点位图和逻辑块位图数据。首先初始化内存超级块结构中位图空间。for (i=0;is_imapi = NULL;for (i=0;is_zmapi = NULL;/ 然后从设备上读取i 节点位图和逻辑块位图信息,并存放在超级块对应字段中。block=2;for (i=0 ; i s_imap_blocks ; i+)if (s-s_imapi=bread(dev,block)block+;elsebreak;for (i=0 ; i s_zmap_blocks ; i+)if (s-s_zmapi=bread(dev,block)block+;elsebreak;/ 如果读出的位图逻辑块数不等于位图应该占有的逻辑块数,说明文件系统位图信息有问题,超级块/ 初始化失败。因此只能释放前面申请的所有资源,返回空指针并退出。if (block != 2+s-s_imap_blocks+s-s_zmap_blocks) / 释放i 节点位图和逻辑块位图占用的高速缓冲区。for(i=0;is_imapi);for(i=0;is_zmapi);/释放上面选定的超级块数组中的项,并解锁该超级块项,返回空指针退出。s-s_dev=0;free_super(s);return NULL;/ 否则一切成功。对于申请空闲i 节点的函数来讲,如果设备上所有的i 节点已经全被使用,则查找/ 函数会返回0 值。因此0 号i 节点是不能用的,所以这里将位图中的最低位设置为1,以防止文件/ 系统分配0 号i 节点。同样的道理,也将逻辑块位图的最低位设置为1。s-s_imap0-b_data0 |= 1;s-s_zmap0-b_data0 |= 1;/ 解锁该超级块,并返回超级块指针。free_super(s);return s;分析流程图如下:4.7 卸载文件系统的系统调用函数/ 参数dev_name 是设备文件名。int sys_umount(char * dev_name)struct m_inode * inode;struct super_block * sb;int dev;/ 首先根据设备文件名找到对应的i 节点,并取其中的设备号。if (!(inode=namei(dev_name)return -ENOENT;dev = inode-i_zone0;/ 如果不是块设备文件,则释放刚申请的i 节点dev_i,返回出错码。if (!S_ISBLK(inode-i_mode) iput(inode);return -ENOTBLK;/ 释放设备文件名的i 节点。iput(inode); if (dev=ROOT_DEV) / 如果设备是根文件系统,则不能被卸载,返回出错号。return -EBUSY;/ 如果取设备的超级块失败,或者该设备文件系统没有安装过,则返回出错码。if (!(sb=get_super(dev) | !(sb-s_imount)return -ENOENT;/ 如果超级块所指明的被安装到的i 节点没有置位其安装标志,则显示警告信息。if (!sb-s_imount-i_mount)printk(Mounted inode has i_mount=0n);/ 查找i 节点表,看是否有进程在使用该设备上的文件,如果有则返回忙出错码。for (inode=inode_table+0 ; inodei_dev=dev & inode-i_count)return -EBUSY; / 复位被安装到的i 节点的安装标志,释放该i 节点。sb-s_imount-i_mount=0;iput(sb-s_imount);/ 置超级块中被安装i 节点字段为空,并释放设备文件系统的根i 节点,置超级块中被安装系统根i 节点指针为空。sb-s_imount = NULL;iput(sb-s_isup);sb-s_isup = NULL;/ 释放该设备的超级块以及位图占用的缓冲块,并对该设备执行高速缓冲与设备上数据的同步操作。put_super(dev);sync_dev(dev);return 0;分析流程图如下:4.8 安装文件系统调用函数/ 参数dev_name 是设备文件名,dir_name 是安装到的目录名,rw_flag 被安装文件的读写标志。/ 将被加载的地方必须是一个目录名,并且对应的i 节点没有被其它程序占用。int sys_mount(char * dev_name, char * dir_name, int rw_flag)struct m_inode * dev_i, * dir_i;struct super_block * sb;int dev;/ 首先根据设备文件名找到对应的i 节点,并取其中的设备号。/ 对于块特殊设备文件,设备号在i 节点的i_zone0中。if (!(dev_i=namei(dev_name)return -ENOENT;dev = dev_i-i_zone0;/ 如果不是块设备文件,则释放刚取得的i 节点dev_i,返回出错码。if (!S_ISBLK(dev_i-i_mode) iput(dev_i);/ 释放该设备文件的i 节点dev_i。iput(dev_i);/ 根据给定的目录文件名找到对应的i 节点dir_i。if (!(dir_i=namei(dir_name)return -ENOENT;/ 如果该i 节点的引用计数不为1(仅在这里引用),或者该i 节点的节点号是根文件系统的节点/ 号1,则释放该i 节点,返回出错码。if (dir_i-i_count != 1 | dir_i-i_num = ROOT_INO) iput(dir_i);return -EBUSY;/ 如果该节点不是一个目录文件节点,则也释放该i 节点,返回出错码。if (!S_ISDIR(dir_i-i_mode) iput(dir_i);return -EPERM;/ 读取将安装文件系统的超级块,如果失败则也释放该i 节点,返回出错码。if (!(sb=read_super(dev) iput(dir_i);return -EBUSY;/ 如果将要被安装的文件系统已经安装在其它地方,则释放该i 节点,返回出错码。if (sb-s_imount) iput(dir_i);return -EBUSY;/ 如果将要安装到的i 节点已经安装了文件系统(安装标志已经置位),则释放该i 节点,返回出错码。if (dir_i-i_mount) iput(dir_i);return -EPERM;/ 被安装文件系统超级块的“被安装到i 节点”字段指向安装到的目录名的i 节点。sb-s_imount=dir_i;/ 设置安装位置i 节点的安装标志和节点已修改标志。/* 注意!这里没有iput(dir_i) */dir_i-i_mount=1; /* 这将在umount 内操作 */dir_i-i_dirt=1; /* NOTE! we dont iput(dir_i) */return 0; /* we do that in umount */分析流程图如下:4.9 安装根文件系统/ 该函数是在系统开机初始化设置时(sys_setup()调用的。( kernel/blk_drv/hd.c, 157 )void mount_root(void)int i,free;struct super_block * p;struct m_inode * mi;/ 如果磁盘i 节点结构不是32 个字节,则出错,死机。该判断是用于防止修改源代码时的不一致性。if (32 != sizeof (struct d_inode)panic(bad i-node size);/ 初始化文件表数组(共64 项,也即系统同时只能打开64 个文件),将所有文件结构中的引用计数/ 设置为0。?为什么放在这里初始化?for(i=0;iNR_FILE;i+)file_tablei.f_count=0;/ 如果根文件系统所在设备是软盘的话,就提示“插入根文件系统盘,并按回车键”,并等待按键。if (MAJOR(ROOT_DEV) = 2) printk(Insert root floppy and press ENTER);wait_for_keypress();/ 初始化超级块数组(共8 项)。for(p = &super_block0 ; p s_dev = 0;p-s_lock = 0;p-s_wait = NULL;/ 如果读根设备上超级块失败,则显示信息,并死机。if (!(p=read_super(ROOT_DEV)panic(Unable to mount root);/从设备上读取文件系统的根i 节点(1),如果失败则显示出错信息,死机。if (!(mi=iget(ROOT_DEV,ROOT_INO)panic(Unable to read root i-node);/ 该i 节点引用次数递增3 次。因为下面266-268 行上也引用了该i 节点。mi-i_count += 3 ; /* NOTE! it is logically used 4 times, not 1 */* 注意!从逻辑上讲,它已被引用了4 次,而不是1 次 */ 置该超级块的被安装文件系统i 节点和被安装到的i 节点为该i 节点。p-s_isup = p-s_imount = mi;/ 设置当前进程的当前工作目录和根目录i 节点。此时当前进程是1 号进程。current-pwd = mi;current-root = mi;/ 统计该设备上空闲块数。首先令i 等于超级块中表明的设备逻辑块总数。free=0;i=p-s_nzones;/ 然后根据逻辑块位图中相应

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论