1、文件系统ls实现与内核编码文件系统ls实现与内核编码一. 设计目的操作系统是控制和管理计算机硬件和软件资源的虚拟机,其中的文件系统是对软件和设备进行管理的系统,文件系统是操作系统中非常重要的一个模块,它的实现占用了操作系统源码的最大编码量,其好坏也直接影响着用户对操作系统的感受程度。通过对操作系统课程设计的实践,进一步加深对文件系统的认识和理解,并在此基础上培养学生的工程应用能力。实验分别从用户态和内核态两个层实践文件系统的部分功能。二. 设计内容1.使用Linux编程实现用户态下带参数的ls命令功能ls命令支持以下功能:支持 -l 参数;输出结果按字典排序;列出“.”文件,支持-a参数,在没
2、有-a时候不显示隐藏文件;显示记录总数;支持对给定的目录进行操作,如 ls /tmp;正确显示文件特殊属性suid、sgid和sticky;支持-u参数,它会显示出文件的最后访问时间;当关掉一个文件的读权限,就不能打开这个文件来读。如果从一个终端登录,打开一个文件,保持文件的打开状态,然后从另外的终端登录,去掉文件的读权限,看会出现什么情况。编写一个程序,先用open()打开一个文件,用read()读一些内容,调用sleep()等待20s以后,再读一些内容,从另外的终端,再等待的20s内去掉文件的读权限,这样会有什么结果?2.编写内核模块显示目录或文件的信息。调试Linux操作系统原理与应用第
3、8章文件系统P215 的例子给内核模块传入参数path,其中path为绝对路径当path为目录时,显示目录对应的dentrey结构中的相关信息(可打印的信息);当path为文件时,显示文件对应的indoe结构中的相关信息(可打印的信息);当路径错误时,有错误提示信息。三概要设计1功能模块图;实现ls命令功能 实现 ls运行命令修改文件权限chmod文件特殊权限eg:chmod7363 2.cls /指定目录ls -uls -als -l ls文件名按字典排序 在一终端运行1.c ,读出文件中的内容,在另一终端修改文件权限,再显示结果,然后在修改文件权限,再显示结果。 Ls -laLs -luL
4、s -uaLs -luaLs 指定文件/指定目录 -l Ls 指定文件/指定目录 -uLs 指定文件/指定目录 -aLs 指定文件/指定目录 -laLs 指定文件/指定目录 -luLs 指定文件/指定目录 -uaLs 指定文件/指定目录 -lua编写内核模块编写内核模块,打印super_block结构中一些域的值。(课本上的例子) 运行 加锁遍历系统中的 超级块打印文件系统所在的主设备号和次设备号打印文件系统名遍历打印每个超级块中的所有索引节点号 解锁索引节点数量给内核模块传入参数path,其中path为绝对路径 运行 path=文件 错误路径 path=目录显示错误信息显示文件信息 显示目录
5、信息2各个模块详细的功能描述。实现ls命令功能ls -l:每个文件单独占一行,显示文件的详细属性信息ls -a:显示包括隐藏文件在内的所有文件ls -u:显示出文件的最后访问时间ls:显示的文件名按字典顺序排序ls /指定目录:显示当前目录下的内容ls -lu:每个文件单独占一行,显示文件的详细属性信息,并且显示出文件的最后访问时间ls -la:显示包括隐藏文件在内的所有文件的详细属性信息ls -lua:显示包括隐藏文件在内的所有文件的详细属性信息,并且显示出文件的最后访问时间chmod 权限 文件名:修改文件的权限,并且显示出此文件是否受suid,sgid和sticky的控制chmod 权限
6、(3位) 在一终端运行程序,读取文件信息,在另一终端修改文件权限,看结果。编写内核模块编写内核模块,打印super_block结构中一些域的值。(课本上的例子)遍历系统中的超级块:list_head结构类型的字段名称为s_list。list_entry宏通过指向list_head节点的地址来得到外部超级块的首地址。获取系统中个超级块的地址,获得某个子进程的地址,打印文件系统所在的主设备号和次设备号和文件系统名。遍历打印每个超级块中的所有索引节点号,打印索引结点。给内核模块传入参数path,其中path为绝对路径path=路径时,显示如下信息:目录项标志哈希表短目录名目录项长度目录项名目录项计数
7、器的引用path=文件时,显示如下信息:文件索引节点的数量文件类型和权限用户ID用户组ID 指定文件系统的读写访问标志 文件大小索引节点的状态硬链接数引用记数文件的块数版本号以位为单位的块大小错误信息显示:Open file failed四详细设计1功能函数的调用关系图ls命令错误处理函数,打印出错误所在行的行数和错误信息void my_error(const char *error_string, int line);获取文件属性void show_file_attribute(struct stat buf,char *file_name,int flag_u)输出文件的文件名,若命令中没
8、有-l选项,则输出文件时要保证上下对齐void show_file_columns(char *file_name)根据命令行参数(存放在flag中)和完整路径名(存放在pathname中)显示目标文件void show_file(int flag,char *pathname)为显示某个目录下的文件做准备,path:要显示的目录void show_file_dir(int flag_param,char *path)main函数 show_fileshow_file_dir show_file_attribute show_file_columns my_error 编写内核模块编写内核模块
9、,打印super_block结构中一些域的值。(课本上的例子) my_init module_init(my_init) my_exit module_exit(my_exit)给内核模块传入参数path,其中path为绝对路径 module_init(param_init) param_init kernel_file_open(p_pchar) kernel_dir_info()kernel_file_info(); param_init module_exit(param_exit)2各功能函数的数据流程图ls命令获取文件属性void show_file_attribute(struct
10、 stat buf,char *file_name,int flag_u) 获取并打印文件类型) 获取文件所有者的权限获取文件所有者同组的用户对该文件的操作权限获取并打印其他用户对文件的操作权限库函数getpwuid访问用户信息getgrgid访问组列表 获取时间输出文件的文件名,若命令中没有-l选项,则输出文件时要保证上下对齐void show_file_columns(char *file_name)本行不足以打印一个文件名则换行每两个相邻文件之间空2格根据命令行参数(存放在flag中)和完整路径名(存放在pathname中)显示目标文件void show_file(int flag,ch
11、ar *pathname)从路径中解析出文件名ls -ulals -ulls -uals -als -uls -l ls为显示某个目录下的文件做准备,path:要显示的目录void show_file_dir(int flag_param,char *path)获取该目录下文件总数和最长的文件名对整个目录进行遍历获取该目录下所有的文件名文件名按最后访问时间进行排序文件名按字母顺序存储于filenames编写内核模块编写内核模块,打印super_block结构中一些域的值。(课本上的例子)打印super_blocks域 加锁遍历系统中的超级块获取系统中个超级块的地址 打印文件系统所在的主设备号和
12、次设备号和文件系统名遍历打印每个超级块中的所有索引节点号打印索引结点 解锁 索引节点数量给内核模块传入参数path,其中path为绝对路径文件信息通过file获取dentry再获取inode的相关信息输出文件索引节点的信息 文件索引节点的数量文件类型和权限用户ID用户组ID 指定文件系统的读写访问标志 文件大小索引节点的状态硬链接数引用记数文件的块数版本号以位为单位的块大小目录信息通过file获取dentry相关信息输出目录项信息目录项标志哈希表短目录名目录项长度目录项名目录项计数器的引用3重点设计及编码ls命令重点设计:为显示某个目录下的文件做准备,path:要显示的目录编码:void sh
13、ow_file_dir(int flag_param,char *path) DIR *dir;/ 对目录进行操作 struct dirent *ptr;/对目录的数据项进行操作 int count=0; char filenames256PATH_MAX+1,tempPATH_MAX+1; char tempfilePATH_MAX+1; struct stat buf; int atimePATH_MAX+1,temp1; /获取该目录下文件总数和最长的文件名 dir=opendir(path); if(dir=NULL) my_error(opendir,_LINE_); while(p
14、tr=readdir(dir)!=NULL)/对整个目录进行遍历 if(filename_maxlend_name) filename_maxlen=strlen(ptr-d_name); count+; closedir(dir); if(count256) my_error(这个目录下的文件太多了,_LINE_); int i,j,length=strlen(path); /获取该目录下所有的文件名 dir=opendir(path); for(i=0;id_name); if(lstat(tempfile,&buf) = -1) my_error(lstat, _LINE_); atim
15、ei = buf.st_atime; strncpy(filenamesi,path,length);/保存文件路径 filenamesilength=0; strcat(filenamesi,ptr-d_name);/d_name:当前目录下所有文件/子目录 filenamesilength+strlen(ptr-d_name)=0; /文件名按最后访问时间进行排序 if(flag_param = PARAM_U|(flag_param = PARAM_U+PARAM_A) for(i = 0;i count-1;i+) for(j = i+1;j count;j+) if(atimei a
16、timej) temp1 = atimei; atimei = atimej; atimej = temp1; strcpy(tempfile,filenamesi); strcpy(filenamesi,filenamesj); strcpy(filenamesj,tempfile); else /文件名按字母顺序存储于filenames for(i = 0; i count-1; i+) for(j = 0; j 0 ) strcpy(temp,filenamesj+1); tempstrlen(filenamesj+1) = 0; strcpy(filenamesj+1,filename
17、sj); filenamesj+1strlen(filenamesj) = 0; strcpy(filenamesj, temp); filenamesjstrlen(temp) = 0; for(i = 0; i s_dev),MINOR(sb-s_dev); /打印文件系统名 printk(file_type name:%s,sb-s_type-name); /遍历打印每个超级块中的所有索引节点号 list_for_each(linode,&sb-s_inodes) pinode=list_entry(linode,struct inode,i_sb_list); count+; prin
18、tk(%lut,pinode-i_ino);/打印索引结点 给内核模块传入参数path,其中path为绝对路径重点设计:打开文件编码:static int kernel_file_open(char *path) /O_DIRECTORY 如果参数所指的文件并非为一目录,则打开文件失败 / 以目录的形式打开 file=filp_open(path,O_DIRECTORY,0); if(IS_ERR(file) file=filp_open(path,O_RDWR|O_CREAT,0777); if(IS_ERR(file) printk(Open file %s failed.n,path);
19、/ 路径错误 return 0; /文件 printk(open file success!n); printk(Path of file: %s,path); kernel_file_info(); printk(ending!n); filp_close(file,NULL); return 1; else /目录 printk(nThis is a diretory!n); printk(Path of directory: %s,path); kernel_dir_info(); printk(ending!n); filp_close(file,NULL); return 0; 5测
20、试数据及运行结果1正常测试数据和运行结果ls命令lsls -l 并显示总记录数ls -als -uls -ulls -uals -lals -lauls /tmpls -l 文件名.c 修改文件的属性并看suid,sgid,sticky是否起作用了。?修改文件权限读取3.txt中的内容修改3.txt的权限再读取3.txt修改3.txt权限再读取3.txt编写内核模块编写内核模块,打印super_block结构中一些域的值。(课本上的例子)插入:insmod卸载:rmmod显示:dmesg运行结果:显示主设备号,次设备号,文件类型名和索引节点数量。给内核模块传入参数path,其中path为绝对路
21、径调试path=文件path=目录当目录中没有文件时,会自动创建指定文件路径错误时,报错2异常测试数据及运行结果ls命令编写内核模块编写内核模块,打印super_block结构中一些域的值。(课本上的例子)给内核模块传入参数path,其中path为绝对路径六调试情况,设计技巧及体会1改进方案在使用Linux编程实现用户态下带参数的ls命令功能的过程中,我实现了基本要求和部分高级要求,使得ls的部分命令可以实现,但是我的代码没有实现ls -R递归地列出目录中所有的文件包含子目录中的文件和输出结果分栏排序,每栏的宽度由这一栏最长的文件名决定,显示的栏数还受终端显示器的的宽度影响,每一列尽可能的等宽
22、。这样让显示结果看上去不是那么的整齐。为了使显示结果看起来整齐并且代码功能强大,在代码中添加递归,遍历等和调用系统中的一些宏来实现-R和控制终端大小。在内核传参的实验过程中,我的代码实现了路径为目录和文件的传参并且在传入路径错误时会报错,但是不能实现当指定目录中没有某个文件时,不能自动创建这个文件,通过修改代码,我的代码实现了这个功能。 2体会通过本次课程设计,让我对ls有了进一步的了解和认识,通过编写ls代码,实现用户态下带参数的ls命令功能,让我对ls下参数有了更深的了解。通过内核模块传参的代码,让我对linux下内核模块中dentry目录项和file文件结构体有了进一步的了解和认识。经过
23、这为期两周的linux课程设计,让我对linux有了更深,更进一步的了解和掌握,让我对ls命令中的参数和内核模块中一些宏和结构体有了一定的了解和掌握,这为我以后的学习打下了坚实的基础。本次的linux课程设计增长了我的见识,让我的知识面更宽更广。七参考文献1 DANIEL P.BOVET&MARCO CESATI. 深入理解LINUX内核M. 陈莉君,张琼声,张宏伟,译.第三版. 北京:中国电力出版社,2007:825-831.2Documentation/x86/boot.txt 3 鸟哥. 鸟哥的Linux私房菜M. 王世江,改编. 第三版. 北京:人民邮电出版社,2011:293-399,596-608.4 Richard Blum. 汇编语言程序设计M. 马朝晖 译. 北京:机械工业出版社,2006.5http:/elinux.org/images/d/d2/Tools-and-technique-for-reducing-bootup-time.pdf八附录:源代码(电子版)
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1