操作系统第4次实验报告:文件系统
Posted yyq726999waf
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了操作系统第4次实验报告:文件系统相关的知识,希望对你有一定的参考价值。
- 袁祎琦
- 201821121033
- 计算1812
1. 编写程序
在服务器上用Vim编写一个程序:实现Linux系统命令ls -lai
的功能,给出源代码。
ls -l:long,除文件名外,同时将文件或子目录的前线、使用者和大小等信息详细列出。 ls -a:all,显示指定目录下所有文件及其子目录,包含隐藏文件(.filename)。 ls -i:inode,输出文件的i节点的索引信息。
常用宏:
- S_ISDIR:是否是一个目录
- S_ISCHR:是否是一个字符设备
- S_ISBLK:是否是一个块设备
文件权限定义:
- S_IRUSR:用户读权限
- S_IWUSR:用户写权限
- S_IRGRP:用户组读权限
- S_IWGRP:用户组写权限
- S_IROTH:其他组都权限
- S_IWOTH:其他组写权限
1 /* 2 osls.c文件 3 */ 4 #include<stdio.h> 5 #include<string.h> 6 #include<sys/types.h> 7 #include<dirent.h> 8 #include<sys/stat.h> 9 #include<grp.h> 10 #include<pwd.h> 11 12 void do_ls(char []); 13 void dostat(char *); 14 void show_file_info(char *, struct stat *); 15 void mode_to_letters(int mode, char str[]); 16 char *uid_to_name(uid_t uid); 17 char *gid_to_name(gid_t gid); 18 19 //主函数 20 int main(int argc, char **argv){ 21 if (argc == 1){ 22 do_ls("."); 23 } 24 else{ 25 while (--argc){ 26 printf("%s: ", *++argv); 27 do_ls(*argv);//切换到指定目录后再显示该目录的内容 28 chdir("");//再回到当前工作目录上来 29 } 30 } 31 return 0; 32 } 33 //获取指定路径下的文件名 34 void do_ls(char dirname[]){ 35 DIR *dir_ptr; 36 struct dirent *direntp; 37 /* 38 opendir函数用来打开参数name指定的目录 39 并返回DIR *形态的目录流 40 */ 41 if ((dir_ptr = opendir(dirname)) == NULL){ 42 fprintf(stderr, "ls2: cannot open %s ", dirname); 43 dostat(dirname);//如果不是目录就当作文件来显示其属性 44 } 45 else{ 46 /* 47 readdir返回参数dir目录的下个目录进入点 48 */ 49 while((direntp = readdir(dir_ptr)) != NULL){ 50 dostat(direntp->d_name);//逐个显示目标文件信息 51 } 52 closedir(dir_ptr); 53 } 54 } 55 //文件显示 56 void dostat(char *filename){ 57 struct stat info; 58 struct dirent *direntp; 59 if (stat(filename, &info) == -1){//取文件信息失败 60 perror(filename); 61 } 62 else{//显示文件信息 63 show_file_info(filename, &info); 64 } 65 } 66 //显示指定文件详细信息 67 void show_file_info(char *filename, struct stat *info_p){ 68 char *uid_to_name(), *ctime(), *gid_to_name(); 69 void mode_to_letters(); 70 char modestr[11]; 71 struct dirent *direntp; 72 mode_to_letters(info_p->st_mode, modestr); 73 74 printf("%d", (int)info_p->st_ino); 75 printf("%s",modestr); 76 printf("%4d ",(int)info_p->st_nlink); 77 printf("%-8s ", uid_to_name(info_p->st_uid)); 78 printf("%-8s ", gid_to_name(info_p->st_gid)); 79 printf("%8ld ", (long)info_p->st_size); 80 printf("%.12s ", 4 + ctime(&info_p->st_mtime)); 81 printf("%s ", filename); 82 } 83 //显示文件读写权限函数 84 void mode_to_letters(int mode, char str[]){ 85 strcpy(str, "-----------");//default=无参数 86 87 if (S_ISDIR(mode)) str[0] = ‘d‘;//目录 88 if (S_ISCHR(mode)) str[0] = ‘c‘;//字符设备 89 if (S_ISBLK(mode)) str[0] = ‘b‘;//块设备 90 91 if (mode & S_IRUSR) str[1] = ‘r‘;//用户权限 92 if (mode & S_IWUSR) str[2] = ‘w‘; 93 if (mode & S_IXUSR) str[3] = ‘x‘; 94 95 if (mode & S_IRGRP) str[4] = ‘r‘;//组权限 96 if (mode & S_IWGRP) str[5] = ‘w‘; 97 if (mode & S_IXGRP) str[6] = ‘x‘; 98 99 if (mode & S_IROTH) str[7] = ‘r‘;//其他权限 100 if (mode & S_IWOTH) str[8] = ‘w‘; 101 if (mode & S_IXOTH) str[9] = ‘x‘; 102 } 103 char *uid_to_name(uid_t uid){ 104 struct passwd * getpwuid(), *pw_ptr; 105 static char numstr[10]; 106 //获取用户id 107 if ((pw_ptr = getpwuid(uid)) == NULL){ 108 sprintf(numstr, "%d", uid); 109 return numstr; 110 } 111 else{ 112 return pw_ptr->pw_name; 113 } 114 } 115 char *gid_to_name(gid_t gid){ 116 struct group *getgrgid(), *grp_ptr; 117 static char numstr[10]; 118 //获取组id 119 if ((grp_ptr = getgrgid(gid)) == NULL){ 120 sprintf(numstr, "%d", gid); 121 return numstr; 122 } 123 else{ 124 return grp_ptr->gr_name; 125 } 126 } 127 //ls -l:long,除文件名外,同时将文件或子目录的前线、使用者和大小等信息详细列出。 128 //ls -a:all,显示指定目录下所有文件及其子目录,包含隐藏文件(.filename)。 129 //ls -i:inode,输出文件的i节点的索引信息。
2. 分析运行结果
分解命令看不同:
1、
2、
3、
系统自带 ls -lai 命令:
自行编写实现:
运行 ./osls 例子分析:
923827 -rw-r--r-- 1 yuanyiqi jmu-cs-18 3586 Apr 30 19:16 osls.c
第一字段:文件inode号。
第二字段:r表示读(read),w表示写(write),x表示执行(execute),其表示中前三个表示文件文件属主的权限,中间三个表示组用户权限,最后三个表示其他用户权限。其中yuanyiqi是文件拥有者,jmu-cs-18是组用户。
第三字段:文件硬链接数或者子目录数,上面的例子的第二字段值为1,说明这个文件只有osls一个文件名,即只有一个指向该连接的硬链接。
第四字段:文件属主用户名。
第五字段:文件属主所在的组用户。
第六字段:文件大小。
第七、八、九字段:文件创建具体时间。
最后一个字段:文件名。
3. 通过该实验产生新的疑问及解答
1、ls-l后显示出的total是什么?怎么计算出来的?
答:total其实就是所有文件所占的块的大小总和,首先数据块(block),Linux的数据存储是以block为单位的,可以理解为一个固定的容器。默认数值是4096,就是4K,由于total的单位是K(1024)。
ls -l 后:
该功能是依赖命令 ls -s 实现的,如下图:
以下是实现计算total的主要代码部分:
1 long nTotalBlocks = 0; 2 DIR* dp = opendir(dirPathName); 3 struct dirent* dirp; 4 while ((dirp = readdir(dp)) != NULL) { 5 lstat(fullPath, &sbuf); 6 long nBlocks = sbuf.st_size / 4096; 7 if (sbuf.st_size % 4096 > 0) 8 nBlocks++; 9 if (S_ISLNK(sbuf.st_mode)) 10 nBlocks = 0; 11 nTotalBlocks += nBlocks; 12 } 13 closedir(dp); 14 cout << "total " << nTotalBlocks * 4 << endl;
以上是关于操作系统第4次实验报告:文件系统的主要内容,如果未能解决你的问题,请参考以下文章