操作系统第4次实验报告:文件系统
- 姓名:林顺达
- 学号:201821121022
- 班级:计算1811
1. 编写程序
在服务器上用Vim编写一个程序:实现Linux系统命令ls -lai
的功能,给出源代码:
源代码:
#include<stdio.h> #include<string.h> #include<sys/types.h> #include<dirent.h> #include<sys/stat.h> #include<grp.h> #include<pwd.h> void do_ls(char []); void dostat(char *); void show_file_info(char *, struct stat *); void mode_to_letters(int mode, char str[]); char *uid_to_name(uid_t uid); char *gid_to_name(gid_t gid); int main(int argc, char **argv) { if (argc == 1) { do_ls("."); } else { while (--argc) { printf("%s:\n", *++argv); do_ls(*argv); } } return 0; } void do_ls(char dirname[]) { DIR *dir_ptr; struct dirent *direntp; if ((dir_ptr = opendir(dirname)) == NULL) { fprintf(stderr, "ls2: cannot open %s\n", dirname); } else { while((direntp = readdir(dir_ptr)) != NULL) { dostat(direntp->d_name); } closedir(dir_ptr); } } void dostat(char *filename) { struct stat info; if (stat(filename, &info) == -1) { perror(filename); } else { show_file_info(filename, &info); } } void show_file_info(char *filename, struct stat *info_p) { char *uid_to_name(), *ctime(), *gid_to_name(); void mode_to_letters(); char modestr[11]; mode_to_letters(info_p->st_mode, modestr); printf("%d ",(int)info_p->st_ino); printf("%s",modestr); printf("%4d ",(int)info_p->st_nlink); printf("%-8s ", uid_to_name(info_p->st_uid)); printf("%-8s ", gid_to_name(info_p->st_gid)); printf("%8ld ", (long)info_p->st_size); printf("%.12s ", 4 + ctime(&info_p->st_mtime)); printf("%s\n", filename); } void mode_to_letters(int mode, char str[]) { strcpy(str, "-----------"); if (S_ISDIR(mode)) str[0] = 'd'; if (S_ISCHR(mode)) str[0] = 'c'; if (S_ISBLK(mode)) str[0] = 'b'; if (mode & S_IRUSR) str[1] = 'r'; if (mode & S_IWUSR) str[2] = 'w'; if (mode & S_IXUSR) str[3] = 'x'; if (mode & S_IRGRP) str[4] = 'r'; if (mode & S_IWGRP) str[5] = 'w'; if (mode & S_IXGRP) str[6] = 'x'; if (mode & S_IROTH) str[7] = 'r'; if (mode & S_IWOTH) str[8] = 'w'; if (mode & S_IXOTH) str[9] = 'x'; } char *uid_to_name(uid_t uid) { struct passwd * getpwuid(), *pw_ptr; static char numstr[10]; if ((pw_ptr = getpwuid(uid)) == NULL) { sprintf(numstr, "%d", uid); return numstr; } else { return pw_ptr->pw_name; } } char *gid_to_name(gid_t gid) { struct group *getgrgid(), *grp_ptr; static char numstr[10]; if ((grp_ptr = getgrgid(gid)) == NULL) { sprintf(numstr, "%d", gid); return numstr; } else { return grp_ptr->gr_name; } }
分析:
ls -(参数)常用指令:
-a或--all 下所有文件和目录。 -A或--almost-all 显示所有文件和目录,但不显示现行目录和上层目录。 -b或--escape 显示脱离字符。 -B或--ignore-backups 忽略备份文件和目录。 -c 以更改时间排序,显示文件和目录。 -C 以又上至下,从左到右的直行方式显示文件和目录名称。 -d或--directory 显示目录名称而非其内容。 -D或--dired 用Emacs的模式产生文件和目录列表。 -f 此参数的效果和同时指定"aU"参数相同,并关闭"lst"参数的效果。 -F或--classify 在执行文件,目录,Socket,符号连接,管道名称后面,各自加上"*","/","=","@","|"号。 -g 次参数将忽略不予处理。 -G或--no-group 不显示群组名称。 -h或--human-readable 用"K","M","G"来显示文件和目录的大小。 -H或--si 此参数的效果和指定"-h"参数类似,但计算单位是1000Bytes而非1024Bytes。 -i或--inode 显示文件和目录的inode编号。 -I<范本样式>或--ignore=<范本样式> 不显示符合范本样式的文件或目录名称。 -k或--kilobytes 此参数的效果和指定"block-size=1024"参数相同。 -l 使用详细格式列表。 -L或--dereference 如遇到性质为符号连接的文件或目录,直接列出该连接所指向的原始文件或目录。 -m 用","号区隔每个文件和目录的名称。 -n或--numeric-uid-gid 以用户识别码和群组识别码替代其名称。 -N或--literal 直接列出文件和目录名称,包括控制字符。 -o 此参数的效果和指定"-l" 参数类似,但不列出群组名称或识别码。 -p或--file-type 此参数的效果和指定"-F"参数类似,但不会在执行文件名称后面加上"*"号。 -q或--hide-control-chars 用"?"号取代控制字符,列出文件和目录名称。 -Q或--quote-name 把文件和目录名称以""号标示起来。 -r或--reverse 反向排序。 -R或--recursive 递归处理,将指定目录下的所有文件及子目录一并处理。 -s或--size 显示文件和目录的大小,以区块为单位。 -S 用文件和目录的大小排序。 -t 用文件和目录的更改时间排序。 -T<跳格字符>或--tabsize=<跳格字数> 设置跳格字符所对应的空白字符数。 -u 以最后存取时间排序,显示文件和目录。 -U 列出文件和目录名称时不予排序。 -v 文件和目录的名称列表以版本进行排序。 -w<每列字符数>或--width=<每列字符数> 设置每列的最大字符数。 -x 以从左到右,由上至下的横列方式显示文件和目录名称。 -X 以文件和目录的最后一个扩展名排序。
此次实验为:ls -lai:
获取目录下文件名:
void do_ls(char dirname[]) { DIR* dir_ptr; struct dirent *direntp; if ((dir_ptr = opendir(dirname)) == NULL) { fprintf(stderr, "ls1: cannot open %s\n",dirname); } else { while((direntp = readdir(dir_ptr)) != NULL) { if( strcmp(direntp->d_name, ".") != 0 && strcmp(direntp->d_name, "..") != 0) printf("%s\n", direntp->d_name); } close(dir_ptr); } }
获取文件详细信息:
void show_stat_info(char *filename, struct stat *buf) { printf("inode\t\t:%d\n",(int)info_p->st_ino); //索引号 printf("mode\t\t:%o\n", buf->st_mode); //文件类型 printf("linkers\t\t:%d\n",(int)buf->st_nlink); //链接数 printf("user\t\t:%d\n", buf->st_uid); //用户id printf("group_id\t:%d\n", buf->st_gid); //组id printf("size\t\t:%d\n", (int)buf->st_size); //文件大小 printf("modtime\t\t:%d\n", (int)buf->st_mtime); //修改时间 printf("group_name\t:%s\n", filename); //文件名 }
通过上述结合处理显示即可得到与(ls -lai)一样的信息
2. 分析运行结果
使用ls -lai运行结果:
使用./ls.lai.out运行结果:
分析:
由于排版格式不同,导致在视觉上的效果不一致
使用ls -lai得到的结果是根据inode排序的
3. 通过该实验产生新的疑问及解答
疑问:如何使输出结果的顺序与指令ls -lai顺序一致
解答:可在获取完文件各项信息后通过排序算法相对于inode进行排序最后再输出