《操作系统课程设计文件系统ls实现与内核编码.doc》由会员分享,可在线阅读,更多相关《操作系统课程设计文件系统ls实现与内核编码.doc(25页珍藏版)》请在三一办公上搜索。
1、 西 安 邮 电 大 学 (计算机学院)操作系统课程设计报告题 目:文件系统ls实现与内核编码 专业名称: 班 级: 学生姓名: 学号(8位): 指导教师: 设计起止时间: 2014年5月19日2014年5月30日一. 设计目的操作系统是控制和管理计算机硬件和软件资源的虚拟机,其中的文件系统是对软件和设备进行管理的系统,文件系统是操作系统中非常重要的一个模块,它的实现占用了操作系统源码的最大编码量,其好坏也直接影响着用户对操作系统的感受程度。通过对操作系统课程设计的实践,进一步加深对文件系统的认识和理解,并在此基础上培养学生的工程应用能力。实验分别从用户态和内核态两个层实践文件系统的部分功能。
2、二. 设计内容1. 在Linux下编程实现带参数的shell命令 ls。实现的功能如下:l 支持 -l 参数;l 输出结果按字典排序;l 列出“.”文件,支持-a参数,在没有-a时候不显示隐藏文件;l 显示记录总数。l 支持对给定的目录进行操作,如 ls /tmp;l 输出结果分栏排序,每栏的宽度由这一栏最长的文件名决定,显示的栏数还受终端显示器的宽度影响,每一列尽可能的等宽;l 正确显示文件特殊属性suid、sgid和sticky,参见联机帮助确保程序能处理各种情况;l 支持标准的ls支持选项-R,它的功能是递归地列出目录中所有的文件包含子目录中的文件;l 支持标准的ls支持选项-u,它会显
3、示出文件的最后访问时间,如果用了-u而不用-l,会有什么结果?2. 修改文件读权限。当关掉一个文件的读权限,就不能打开这个文件来读。如果从一个终端登录,打开一个文件,保持文件的打开状态,然后从另外的终端登录,去掉文件的读权限,这时有什么事情会发生?编写一个程序,先用open()打开一个文件,用read()读一些内容,调用sleep()等待20s以后,再读一些内容,从另外的终端,再等待的20s内去掉文件的读权限,这样会有什么结果?3. 调试Linux操作系统原理与应用第8章文件系统P215 的例子4. 编写内核模块显示目录或文件的信息。给内核模块传入参数path,其中path为绝对路径:l 当p
4、ath为目录时,显示目录对应的dentrey结构中的相关信息(可打印的信息);l 当path为文件时,显示文件对应的indoe结构中的相关信息(可打印的信息);l 当路径错误时,有错误提示信息。三概要设计1功能模块图;处理命令行参数获取命令行参数获取屏幕宽度运行命令处理路径非法情况处理无路径情况处理路径为目录的情况处理路径为文件的情况(1)、实现ls(2) 、修改文件权限关闭文件读取文件内容睡眠20秒打开错误,退出程序否读取文件内容是判断文件是否存在运行命令解锁遍历各超级块的索引结点号遍历系统中的超级块加锁(3) 、调试例子移除内核文件信息输出目录信息输出打开文件或目录非法路径提示分析绝对路径
5、插入内核(4) 、内核传参2各个模块详细的功能描述。(1)、实现lsu 运行命令:在终端下运行程序。u 获取屏幕宽度:调用系统函数ioctl(),获取当前终端的宽度。u 获取命令行参数:遍历命令行获取命令参数a、u、l、R及其组合,并存入params 数组中。u 处理命令行参数:根据上一步得到的param 分析当前运行时的参数类型并记录在paramFlag中。u 处理无路径情况:显示当前目录的所有信息,并根据上一步得到的paramFlag参数组合分类的显示。u 处理路径为目录的情况:显示该目录的所有信息,并根据上一步得到的paramFlag参数组合分类的显示。u 处理路径为文件的情况:显示该文
6、件的所有信息,并根据上一步得到的paramFlag参数组合分类的显示。u 处理路径非法情况:显示错误提示并退出程序。(2) 、修改文件权限u 打开文件:文件不存在则报错,文件存在则进行操作。当修改权限之后,再次打开文件并进行操作。u 读取文件内容:成功打开文件则读取文件中存在的数据。在睡眠前后都进行读取文件内容。u 睡眠:在第一次读取文件内容之后睡眠20秒,方便进行修改权限操作。(3) 、调试例子u 加、解锁:在对超级块操作前,加锁防止系统其他进程对超级块进行修改;在操作完成后解锁。u 获取超级块信息:遍历超级块,获取超级块的基本信息并输出。u 打印各超级块的索引结点号:遍历各超级块中的索引结
7、点并输出相关信息。(4)、内核传参u 文件操作:对由命令传入的绝对路径对应的目录或文件进行打开操作。u 获取dentry结构体的信息:若绝对路径指向的是目录,则打印其dentry结构体中的相关信息。u 获取inode结构体的信息:若绝对路径指向的是文件,则打印其dentry结构体中的相关信息。四详细设计1功能函数的调用关系图(1)、实现lsHasDirs()ShowFileInfo()ShowFileName()DisposeParam()CompareU()Compare()DirRead()main()其中:void DirRead( int, char * ):读取目录下文件和子目录的内
8、容信息。int Compare( const void *, const void * ):按字典顺序排序。int CompareU( const void *, const void * ):在有-u而没有-l的情况下,按最近时间由近到远的顺序排序。void DisposeParam( int, char * ):根据参数的种类,分类对该目录或文件进行不同的显示操作。int hasDirs( char * ):判断当前获取的子目录路径是否之前被找到。void ShowFileName( char * ):显示文件名。void ShowFilesInfo( struct stat, char
9、*, int ):显示文件的详细信息。close()sleep()read()open()(2) 、修改文件权限其中:open():调用文件操作函数,打开文件返回文件描述符。read():调用文件操作函数,读取文件中的内容。sleep():调用线程操作函数,是程序睡眠20秒,等待修改权限。close():调用文件操作函数,关闭文件。(3)、调试例子spin_unlock()list_entry()list_for_eachspin_lock()其中:spin_lock():加锁操作,在对超级块操作前,加锁防止系统其他进程对超级块进行修改。list_for_each:链表宏定义,用来遍历链表,链
10、表中存放个超级块的地址。list_entry():获取超级块的地址。spin_unlock():解锁操作。(4) 、内核传参path_exit()ShowDirInfo()ShowFileInfo()OpenFile()path_init()其中:static _init int path_init( void ):插入内核时系统调用该函数对其初始化。static int OpenFile( char * ):自定义函数,根据插入内核时传入的参数,打开相应的路径获取信息。static int ShowFileInfo( void ):说明路径指向的是文件,并输出文件inode结构体中的信息。s
11、tatic int ShowDirInfo( void ):说明路径指向的是目录,并输出目录dentry结构体中的信息。static _exit void path_exit( void ):移除内核时系统调用该函数输出相应信息。ShowFileInfo()(是)传参:文件状态stat、文件名、有参数u标志有参数-lShowFileName()(否)传入参数:文件名参数有-R,传入参数:当前找到的子目录的完整路径HasDir()(否)显示目录下的文件名,传参:命令行参数、文件路径(是)传参:命令行参数、子目录完整路径有-R有-u无-lCompare()(否)CompareU()(是)Dispo
12、seParam()(文件)传参:命令参数、路径DirRead()(无路径、目录)传参:命令参数、路径判断路径main()2各功能函数的数据流程图(1)、实现lsclose()sleep()read()open()传参:文件描述符、存储读取文件内容的buf、读取文件长度程序睡眠20秒睡眠结束,继续读文件内容,传参:文件描述符、存储读取文件内容的buf、读取文件长度关闭文件再次打开文件,查看权限(2) 、修改文件权限(3) 、调试例子spin_unlock()list_entry()list_for_eachspin_lock()插入内核需要参数:SB_LOCK_ADDRESS 传参:链表结点,超
13、级块地址链表头 传参:链表头、超级块类型、存储所有超级块信息的链表遍历各超级块的索引号节点并获取索引结点的信息(4)、内核传参路径非法,显示错误信息path_exit()ShowDirInfo()ShowFileInfo()OpenFile()path_init()传参:绝对路径文件目录路径3重点设计及编码(1)、实现lsu 在只有-u的情况下按照最后访问时间由近到远排序,调用的是系统排序方法qsort( filePaths, count, sizeof( filePaths 0 ), CompareU );其中CompareU()是自定义的排序函数。int CompareU( const v
14、oid *first, const void *last )struct stat buf1, buf2;stat( ( char * )first, &buf1);stat( ( char * )last, &buf2);return ( ( int )buf2.st_atime - ( int )buf1.st_atime );u 实现-R的功能。在void DisposeParam( int paramFlag, char *filePath )函数中查找当前目录下存在的子目录。if ( ( paramFlag = 8 ) & S_ISDIR( buf.st_mode ) & strcm
15、p( fileName, . ) & strcmp( fileName, . ) & hasDirs( filePath ) = 0 )/ 判断为目录时过滤.和.并且若该目录没有被找出strcpy( dirPath dirCount , filePath );hasDir = 1;/ 标志,在当前目录下找到子目录dirCount+;/ 更新子目录数然后再void DirRead( int paramFlag, char *path )函数中递归调用自身来显示子目录的相关内容。if ( paramFlag = PARAM_R & hasDir = 1 )/ 将子目录的hasDir标志位置0,表示
16、子目录下还未找到其子目录hasDir = 0;for ( dirShow; dirShow dirCount; )/ -l输出总用量置0,-a分栏宽度置MAXCHAR,递归调用自身total = 0;restLen = line;printf( n%s:n, dirPath dirShow );DirRead( paramFlag, dirPath dirShow+ );(2)、内核传参u 判断路径指向的文件类型:file = filp_open( path, O_DIRECTORY, 0 );if ( IS_ERR( file ) )/ 不成功则以文件形式打开file = filp_open
17、( path, O_RDONLY, 0444 );if ( IS_ERR( file ) )/ 路径错误printk( The Paht %s failed!n, path );return 0;/ 该路径指向一个文件printk( This is file!n );ShowFileInfo();filp_close( file, NULL );return 0;else/ 该路径指向一个目录printk( This is diretory!n );ShowDirInfo();filp_close( file, NULL );return 0;五测试数据及运行结果1正常测试数据和运行结果(1)
18、、实现lsu 无参有路径的情况:u 无参数的情况、只有-a的情况、只有-u的情况:有上述的情况可以看出:如果用了-u而不用-l,输出的文件名会按最后访问时间由近到远的顺序而不是按字典顺序排序。u 对比-l和-lu的输出不同情况:不同之处在于输出的时间,-l输出最近修改时间,-lu输出最近访问时间。并且在-l的情况下会输出三个特殊属性SGID、SUID、Sticky位。u -R的情况:递归显示子目录信息u -aulR组合情况:(2) 、修改文件权限调用sleep()等待20s以后,再读一些内容,从另外的终端,再等待的20s内去掉文件的读权限,但是程序还是能从文件中读取出内容。当再一次打开文件时由
19、于无权限,文件打开错误。(3) 、调试例子u 查看程序中涉及的两个全局变量:cat /proc/kallsyms | grep super_blocks结果:ffffffff81c4f3c0 D super_blockscat /proc/kallsyms | grep super_blocks结果:ffffffff81f027a0 B sb_lock u 运行结果:(部分内容)(4) 、内核传参u 当路径指向文件时,显示文件inode信息:当路径指向目录时,显示目录dentry信息:2异常测试数据及运行结果(1)、实现ls(2)、修改文件权限(3)、内核传参六调试情况,设计技巧及体会1改进方
20、案本次实验完成的很不错。在实现ls的功能中,完成了所有的要求,可以改进的地方有:将分栏情况模拟成系统显示的效果(以列为主,以各列的文件名最大值为栏宽),而不是简单的以行为主,以所有的文件名中最大值为栏宽;使用-R参数时,应使用链表结构而不是数组结构,这样不会因为递归太深,子目录太多而造成的越界现象。在实现内核传递参数的功能中,完成了所有的功能,可以的改进的地方就是尽可能的输出有用的信息。2体会通过本次实验,我实现了ls这个shell命令,为之后设计操作系统打下基础;通过控制文件的访问权限我理解了文件操作的工作原理;编写内核代码让我掌握了通过命令传入参数的方法。通过上网查找资料、查看课本等途径,
21、让我的自学能力更进一步,对Linux和操作系统的知识理解得更加的深入。七参考文献1Linux操作系统原理与应用M. 陈莉君,康华编著. 第二版. 北京:清华大学出版社,2012.2 美Molay.B 著. Unix/Linux编程实践教程M. 杨宗源,黄海涛译. 北京:清华大学出版社,2004.3 鸟哥. 鸟哥的Linux私房菜M. 王世江,改编. 第三版. 北京:人民邮电出版社,2011.八附录:1.ls#include #include #include #include #include #include #include #include #include #include #defi
22、nePARAM_NONE0/ 无参数#definePARAM_A1/ -a: 显示所有文件#definePARAM_L2/ -l:一行显示一个文件的详细信息#define PARAM_U4/ -u:显示文件最后一次访问时间#define PARAM_R8/ -R:递归显示文件与子目录及其内容#define PATHCOUNT10/ 递归显示目录功能中子目录的数量int restLen = 0;/ -l打印详细信息时一行剩余长度int maxFileLen = 0;/ 存放某目录下最长的文件名的长度int total = 0;/ -l显示的总用量int hasDir = 0;/ -R中标志位,在
23、当前目录下是否找到子目录int dirCount = 0;/ -R中目前递归找到的子目录的数量int dirShow = 0;/ -R已显示相关信息的子目录的数量int line = 0;/ 屏幕的宽度char dirPath PATHCOUNT PATH_MAX + 1 = 0 ;/ -R中存储子目录路径void DirRead( int, char * );int Compare( const void *, const void * );int CompareU( const void *, const void * );void DisposeParam( int, char * );
24、int HasDirs( char * );void ShowFileName( char * );void ShowFilesInfo( struct stat, char *, int );int main( int argc, char * argv )int i, j, k;int paramCount, paramFlag;char path PATH_MAX + 1 ;/ 保存命令行中路径char params 20 ;/ 存储参数struct stat st;struct winsize size;j = 0;paramCount = 0;/ 带参数的命令行数量paramFlag
25、 = PARAM_NONE;/ 参数标志位,初始无餐/ 获取屏幕宽度ioctl(STDOUT_FILENO, TIOCGWINSZ, &size);line = size.ws_col;restLen = line;/ 读取命令行中的参数for ( i = 1; i argc; i+ ) if ( argv i 0 = - ) for ( k = 1; k strlen( argv i ); k+, j+ )params j = argv i k ;paramCount+;params j = 0;/ 判断当前命令的参数,更新参数标记位for (i = 0; i j; i+) switch(
26、params i )case a:paramFlag |= PARAM_A;break;case l:paramFlag |= PARAM_L;break;case u:paramFlag |= PARAM_U;break;case R:paramFlag |= PARAM_R;break;default:printf( 有未知的参数存在!n );return 0;/ 没有路径,显示当前目录if ( ( paramCount + 1 ) = argc ) strcpy( path, ./0 );DirRead( paramFlag, path );return 0;/ 有路经,判断路径非法、是
27、目录、是文件i = 1 + paramCount;do strcpy( path, argvi );if ( stat( path, &st ) = -1 )/ 路径非法printf( 目标文件或目录%s不存在!n, path );return 0;/ 路径为目录if ( S_ISDIR( st.st_mode ) ) DirRead( paramFlag, path );else/ 路径为文件DisposeParam( paramFlag, path );i+; while (i pw_name );/ 打印所有者的用户名printf( %6s, grp-gr_name );/ 打印组名pr
28、intf( %7ld , (long)buf.st_size ); / 打印文件的大小 if ( hasU = 0 )strcpy( buf_time, ctime( &buf.st_mtime ) );/ 最后一次修改时间elsestrcpy( buf_time, ctime( &buf.st_atime ) );/ 最后一次访问时间buf_time strlen( buf_time ) - 1 = 0;/ 去掉换行符printf( %s, buf_time );/ 打印文件的时间信息printf( %sn, fileName );/ 打印文件名字total += (int)buf.st_b
29、locks;/ 计算当前目录所有文件的总用量/ 没有-l,只打印文件名并分栏对齐void ShowFileName( char *fileName )int i, len;/ 本行剩余长度不足已显示下一个文件名,换行if ( restLen maxFileLen ) printf( n );restLen = line;/ 打印文件名并分栏len = maxFileLen - strlen( fileName );/ 当前显示栏的剩余长度printf( %s , fileName );/ 打印文件名if ( (int)* fileName 0 )/ 文件名若为中文len += 2;for (
30、i = 0; i len; i+ )/ 当前栏剩余处打印空格printf( );restLen -= ( maxFileLen );/ 更新当前行的剩余长度/ -R下判断是否已知参数路径为一个目录路径int HasDirs( char *filePath )int i;for ( i = 0; i dirCount; i+)if ( strcmp( filePath, dirPath i ) = 0 )return 1;return 0;/ 分析参数并分别执行不同的操作void DisposeParam( int paramFlag, char *filePath )struct stat b
31、uf;int i, j, hasU;char fileName NAME_MAX + 1 ;/ 存储文件名hasU = 0;/ 从完整路径中解析文件名for ( i = 0, j = 0; i = 8 ) & S_ISDIR( buf.st_mode ) & strcmp( fileName, . ) & strcmp( fileName, . ) & HasDirs( filePath ) = 0 )/ 判断为目录时过滤.和.并且若该目录没有被找出strcpy( dirPath dirCount , filePath );hasDir = 1;/ 标志,在当前目录下找到子目录dirCount
32、+;/ 更新子目录数/ 对参数分类操作if ( paramFlag = 0 | paramFlag = 4 | paramFlag = 8 | paramFlag = 12)/ paramFlag为下列情况:PARAM_NONE,PARAM_U,PARAM_R,PARAM_U + PARAM_Rif ( fileName 0 != . ) ShowFileName( fileName );else if ( paramFlag = 1 | paramFlag = 5 | paramFlag = 9 | paramFlag = 13)/ paramFlag为下列情况:PARAM_A,PARAM_
33、A + PARAM_U,PARAM_A + PARAM_R,PARAM_A + PARAM_U + PARAM_RShowFileName( fileName );else if ( paramFlag = 2 | paramFlag = 10 )/ paramFlag为下列情况:PARAM_L,PARAM_L + PARAM_Rif ( fileName 0 != . ) ShowFilesInfo( buf, fileName, hasU );else if ( paramFlag = 3 | paramFlag = 11 )/ paramFlag为下列情况:PARAM_A + PARAM_L,PARAM_A + PARAM_L + PARAM_RShowFilesInfo( buf, fileName, hasU );else if ( paramFlag = 6 | paramFlag = 14 )/ paramFlag为下列情况:PARAM_L + PARAM_U,PARAM_L + PARAM_U + PARAM_RhasU = 1;if ( fileName 0 != . )ShowFilesInfo( buf, fileName, hasU );else if ( paramFlag = 7 | paramFlag = 1