操作系统课程设计 indoec流程及代码分析Word文档格式.docx
- 文档编号:6718692
- 上传时间:2023-05-07
- 格式:DOCX
- 页数:22
- 大小:401.70KB
操作系统课程设计 indoec流程及代码分析Word文档格式.docx
《操作系统课程设计 indoec流程及代码分析Word文档格式.docx》由会员分享,可在线阅读,更多相关《操作系统课程设计 indoec流程及代码分析Word文档格式.docx(22页珍藏版)》请在冰点文库上搜索。
6.分析体会及自己所做亮点工作21
7.参考文献23
1.总体概述
实验名称:
Linux0.11文件系统源代码分析之I节点管理源代码分析;
源代码在源程序中的具体位置:
linux/fs/inode.c(电子书《Linux内核0。
11完全注释》赵炯编著的451页)。
实验要求:
对该源代码进行分析的主要任务是对重要的头文件进行分析、结合代码对实现所用的主要数据结构进行分析、结合代码对主要函数功能进行分析,并画出函数间调用关系结构图或程序流程图。
实验预期结果:
从形式上来看,程序主要是头文件、数据结构和函数构成,从思路上来看,程序是由数据结构和算法构成,但是现在Linux操作系统源代码,已经给了我们,而且别人也分析的特别的详细了。
作为初学者,没有什么经验,我想能把它看懂就不错了,所以最重要的是对程序的各个函数进行分析,画出流程图(主要是通过流程图来分析),在画流程图的过程中,仔细体会每行代码的作用和思路,从而最终看懂整个inode.c程序。
2.模块整体功能介绍及主要目标
2.1模块整体功能
inode.c程序主要涉及文件系统i节点信息的访问和管理。
每个文件的创建都会有一个i节点,它包括该文件的所有信息,本程序就是对创建好的文件的i节点进行管理。
该程序主要包括处理i节点的iget()、iput()、bmap(),以及其他一些辅助函数。
iput()函数的功能与iget()函数正好相反,主要把i节点引用计数值递减1,要是在某一时刻进程不需要持续使用一个i节点时就应该调用iput()函数来使i节点引用值减1,好让内核执行其他一些处理。
(详细过程见iput()函数的流程图(图14));
iget()函数的功能是从设备上取指定节点号的i节点,处理过程是扫描整个i节点表,来找相应的i节点,当找到后再等待解锁,这时i节点表可能会发生变化,就要再重新扫描i节点表,还要把i节点的引用计数值增1,还要判断是否是安装点,要是的话,就在超级块表中找,找到后,再写盘,再重新扫描整个i节点表。
最后返回找到的i节点指针。
(详细过程见iget()函数的流程图(图18))。
2.2主要目标
主要分析inode.c程序中的处理i节点的主要处理函数,包括iget()、iput()、bmap(),以及其他一些辅助函数。
结合代码对主要函数功能进行分析,并画出函数间调用关系结构图或程序流程图。
3.头文件的分析
3.1头文件kernel.h
panic(constchar*str);
//标准打印(显示)函数
printf();
//内核专用的打印信息函数,功能与printf()相同
printk();
//往tty上写指定长度的字符串。
3.2头文件sched.h
externvoidsleep_on(structtast_struct**p);
//不可中断的等待睡眠
externvoidinterruptible_sleep_on(structtast_struct**p);
//可中断的等待睡眠
externvoidwake_up(structtast_struct**p);
//明确唤醒睡眠的进程。
3.3头文件system.h
sti();
//开中断嵌入汇编宏函数
cli();
//关中断
3.4头文件fs.h
externstructm_inodeinode_table[NR_INODE];
//定义i节点表数组(32项)
externvoidtruncate(structm_inode*inode);
//刷新i节点信息。
externvoicsync_inodes(void);
//等待指定的i节点。
externvoidbrelse(structbuffer_head*buf);
//读取指定的数据块。
4.数据结构的分析
4.1structbuffer_head{…};
//缓冲块头数据结构,在程序中常用bh来表示buffer_head类型的缩写(极为重要)(结构见图1)
图1structbuffer_head结构体
4.2structd_inode{…};
//磁盘上的索引节点(i节点)数据结构。
4.3structm_inode{…};
//在内存中的i节点结构(结构见图2)
图2structm_inode结构体
4.4structsuper_block{…};
//内存中磁盘超级块结构(结构见图3)
图3structsuper_block结构体
4.5structd_super_block{…};
//磁盘上超级块结构
4.6structm_inodeinode_table[NR_INODE]={{0,},};
//内存中I节点表
5.函数的分析
5.1read_inode()函数分析
5.1.1函数头:
staticvoidread_inode(structm_inode*inode);
5.1.2主要功能:
读取指定I节点信息;
从设备上读取含有指定I节点信息的I节点盘块,然后复制到指定的I节点结构中。
为了确定I节点所在的设备逻辑块号(或缓冲块),必须首先读取相应设备上的超级块,以获取用于计算逻辑块号的每块I节点数信息INODES_PER_BLOCK.在计算出I节点所在的逻辑块号后,就把该逻辑块读入一缓冲块中。
然后把缓冲块中相应位置处的I节点内容复制到参数指定的位置处。
5.1.3流程图:
(见图4)
图4read_inode()函数流程图
write_inode()函数分析
5.2.1函数头:
staticvoidwrite_inode(structm_inode*inode);
5.2.2功能分析:
将i节点信息写入缓冲区中。
该函数把参数指定的i节点写入缓冲区相应的缓冲块中,待缓冲区刷新时会写入盘中。
5.2.3流程图:
(见图5)
图5write_inode()函数流程图
5.3sleep_on()函数分析
5.3.1函数头:
voidsleep_on(structtast_struct**p);
5.3.2功能分析:
把当前任务置为不可中断的等待状态,并让睡眠队列列头指针指向当前任务,只有明确地唤醒时才会返回。
该函数提供了进程与中断处理程序之间的同步机制。
函数参数p是等待任务队列列头指针。
指针是含有一个变量地址的变量。
这里参数p使用了指针的指针形式‘**p’,这是因为C函数参数只能传值,没有直接的方式让被调用函数改变调用该函数程序中变量的值。
但是指针‘*p’指向的目标(这里是任务结构)会改变,因此为了能修改调用该函数程序中原来就是指针变量的值,就需要传递指针‘*p’的指针,即‘**P’。
5.4wait_on_inode()函数分析
5.4.1函数头:
staticinlinevoidwait_on_inode(structm_inode*inode);
5.4.2函数的功能:
等待指定的i节点可用;
如果i节点已被锁定,则将当前任务置为不可中断的等待状态,并添加到该I节点的等待队列i_wait中,直到该i节点解锁并明确地唤醒本任务。
5.4.3程序流程图:
(见图6)
图6wait_on_inode()函数流程图
5.5lock_inode()函数分析
5.5.1函数头:
staticinlinevoidlock_inode(structm_inode*inode);
5.5.2函数的功能:
对指定的I节点上锁;
如果I节点已被锁定(即当inode->
i_lock=1),则将当前任务置为不可中断的等待状态,并添加到该I节点的等待队列i_wait中。
直到该I节点解锁(inode->
i_lock=0时)并明确地唤醒本任务。
然后对其上锁(inode->
i_lock=1)。
5.5.3流程图:
(见图7)
图7lock_inode()函数流程图
5.6unlock_inode()函数分析
5.6.1函数头:
staticinlinevoidunlock_inode(structm_inode*inode);
5.6.2函数的功能:
对指定的i节点解锁;
首先使i节点的锁定标志为0(复位),并明确地唤醒(wake_up(&
inode->
i_wait))等待在此i节点等待队列i_wait上的所有进程。
5.7invalidate_inodes()函数分析
5.7.1函数头:
voidinvalidate_inodes(intdev);
5.7.2函数的功能:
释放设备dev在内存i节点表中的所有i节点;
扫描内存中的i节点表数组,如果是指定设备使用的i节点就释放之。
5.7.3流程图:
(见图8)
图8invalidate_inodes()函数流程图
5.8sync_inodes(void)函数分析
5.8.1函数头:
voidsync_inodes(voic);
5.8.2函数的功能:
同步所有i节点;
把内存i节点表中所有i节点与设备上i节点作同步操作。
5.8.3流程图:
(见图9)
图9sync_inodes(void)函数流程图
5.9_bmap()函数分析
5.9.1函数头:
staticint_bmap(structm_inode*inode,intblock,intcreate);
5.9.2函数的功能:
文件数据块映射到盘块的处理操作;
参数:
inode-文件的i节点指针;
block-文件中的数据块号;
create-创建块标志。
该函数把指定的文件数据块block对应到设备上逻辑块上,并返回逻辑块号。
如果创建标志置位,则在设备上对应逻辑块不存在时就申请新磁盘块,返回文件数据块block对应在设备上的逻辑块号(盘块号)。
5.9.3流程图(由图10、11和12构成)
5.9.3.1主流程如下:
(见图10)
图10_bmap()函数主流程图
5.9.3.2对一次间接块进行处理的过程:
(见图11)
图11_bmap()函数中对一次间接块进行处理的流程图
5.9.3.3对二次间接块进行处理的过程:
(见图12)
Y
N
图12_bmap()函数中对二次间接块进行处理
5.10bmap()函数分析
5.10.1函数头:
intbmap(structm_inode*inode,intblock);
5.10.2函数的功能:
取文件数据块block在设备上对应的逻辑块号;
inode-文件的内存i节点指针;
若操作成功则返回对应的逻辑块号,否则返回0。
5.10.3调用结构图:
(见图13)
图13bmap()函数调用结构图
5.11iput()函数分析
5.11.1函数头:
voidiput(structm_inode*inode);
5.11.2功能分析:
放回(放置)一个i节点(回写入设备)。
该函数主要用于把i节点引用计数值递减1,并且若是管道i节点,则唤醒等待的进程。
若是块设备文件i节点则刷新设备。
并且若i节点的链接计数为0,则释放该i节点占用的所有磁盘逻辑块,并释放该i节点。
5.11.3流程图:
(见图14)
图14iput()函数流程图
5.12get_empty_inode()函数分析
5.12.1函数头:
structm_inode*get_empty_inode(void);
5.12.2功能分析:
从i节点表(inode_table)中获取一个空闲i节点项;
5.12.3流程图:
(见图15)
图15get_empty_inode()函数流程图
5.13get_pipe_inode()函数分析
5.13.1函数头:
structm_inode*get_pipe_inode(void);
5.13.2功能分析:
获取管道节点。
5.13.3流程图:
(见图16)
图16get_pipe_inode()函数流程图
5.14create_block()函数分析
5.14.1函数头:
intcreate_block(structm_inode*inode,intblock);
5.14.2功能分析:
如果对应的逻辑块不存在就创建一块;
返回设备上对应的已存在或新建的逻辑块号。
block-文件中的数据块号。
5.14.3调用结构图:
(见图17)
图17create_block()函数调用结构图
5.15iget()函数分析
5.15.1函数头:
structm_inode*iget(intdev,intnr);
5.15.2功能分析:
取得一个i节点。
5.15.3流程图:
(见图18)
图18iget()函数流程图
6.分析体会及自己所做亮点工作
经过自己几天的努力,Linux0.11文件系统源代码分析之I节点管理源代码分析inode.c,终于用自己的思路分析完了,理解透了。
Inode.c程序总共有339行代码,乍一看,自己都会心烦,很难看下去,报告也无从着手来写,虽然注解非常的详细,看代码最忌讳的就是没有耐心,所以在看代码之前就必需使自己静下心来,然后根据熊老师的要求,报告的说明,想好自己的分析计划。
先整体看一下程序,看它由哪些函数构成,第一遍看下来,就发现在inode.c程序中,定义了一些主要函数(如:
read_inode(),write_inode(),iget(),get_pipe_inode(),get_empty_inode(),iput(),bam(),_bamp(),sync_inode(),invalidate_inodes(),unlock_inode(),lock_inode(),wait_inode())(看第一遍时,只看一下这些函数头),它在本程序中定义了,那么看懂这些是必需的,不过同时我也发现,在这些函数中,也调用了其他的一些函数(如:
cli(),sti(),sleep_on(),wake_up(),printk(),panic(),bread()等等),而这些函数呢,在本程序中却没有定义,只是直接拿来调用它了,开始是用点糊涂,一下子间反应不过来是怎么回事,后来问了熊老师,他的讲解,让我顿间明白过来,也想起自己以前也编写过的像这种把所有的子程序,综合起来运行,那就是把一些需要共享的函数的函数头放到头文件中,当哪个子程序需要调用它们时,只需要加载相应的头文件即可。
最终这些函数在头文件(第11章)都能够找到。
(有注解,所以我能看的懂)。
类似的道理,一些在此程序中没有定义的数据结构,在头文件中也都有定义。
在最初不断地浏览整个程序的过程中,也遇到了一些问题,虽然有注解,但是注解中的有些词汇(名词),却不知道是什么意思,同时我注意到,inode.c程序只是文件系统源代码的一部分,而文件系统中的各个子程序也有交叉,所以我现在要明白,不能孤立地看这个程序,而是要是发现不懂的地方,可以到别的程序中找答案,例如:
超级块:
超级块中主要存放了有关整个文件系统的信息,其信息结构参见“总体功能描述”中的图9-3(电子书399页),并说明各部分的大小。
在linux0.11系统中,被加载的文件系统超级块保存在超级块表(数组)supper_block[]中。
整体思路想好后,接下来的任务就是单个的分析每个数据结构、函数,注意有些数据结构在本程序中没有定义,要到头文件中去寻找。
在分析函数的时候,有了前提知识,我是直接分析源代码的结构的,只有自己不懂的时候,才会去看注解,然后基本上都是用流程图或函数间调用结构图来描述的,再加了一些说明性的文字。
这样我就利用电子书上的注解分析,转换为自己的思路,这样的思维不那么呆板,而且也很有成就感。
通过分析程序画出其流程图,使我必需耐心看完并分析每条语句,分析一点,就记录一点在图上,最终把整个程序分析完。
冰冻之尺,非一日之寒,339行的程序分析下来,也花了我不少时间,从开始查资料到最后报告的完成,前后也有5天的时间。
分析此程序,使我了解了,处理i节点的函数iget()、iput()、bmap(),以及其他一些辅助函数的具体实现过程。
Iget()是指从设备上读取指定节点号nr的i节点,而iput()函数所完成的功能,正好与iget()函数相反,它主要用于把i节点引用计数值递减1,并且若是管道i节点,则唤醒等待的进程。
各个函数的具体详细描述过程见此报告的正文,在此不再赘余。
以上都是自己在分析inode.c程序中所得出的一点体会及一些学习方法和思考问题的方式。
我自己认为,可能有一天,我把这个程序的编写过程给忘了,但是这样思考问题的方法和做事的态度,却很实用,会伴随我一生,使我受益匪浅。
7.参考文献
[1]《Linux0.11内核完全注释》赵炯编著
[2]《Linux内核2.4版源代码分析大全》机械工业出版社李善平2002.1
[3]《Linux操作系统内核分析》陈利君编著人民邮电出版社
[4]
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 操作系统课程设计 indoec流程及代码分析 操作系统 课程设计 indoec 流程 代码 分析