操作系统第三次实验报告

更新时间:2023-05-10 07:11:01 阅读量: 实用文档 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

操作系统实验报告

实验名称: 实现ls命令实验

计算机科学与技术学院

目录

一、实验目的和要求 .......................................................................... 2 二、实验内容 ...................................................................................... 2 三、实验步骤 ...................................................................................... 2 四、实验结果与分析 .......................................................................... 3

1.输出当前目录下文件 ............................................................ 3 2.输出指定目录下文件 ............................................................ 3 五、程序源代码 .................................................................................. 5 六、实验体会 ...................................................................................... 7

一、实验目的和要求

在linux系统下用C语言编写一个程序实现 linux 系统下 ls 命令的功能。

二、实验内容

问题:编写一个程序实现 linux 系统下 ls 命令的功能。

首先通过Linux系统的文件目录流打开函数DIR *opendir(const char *name); 来先打开文件目录,然后通过系统调用函数struct dirent *readdir(DIR *dirp); 读取文件目录下的文件信息。其中文件结构体dirent的结构如下:

struct dirent {

ino_t d_ino; /* inode number */

off_t d_off; /* offset to the next dirent */

unsigned short d_reclen; /* length of this record */

unsigned char d_type; /* type of file; not supported by all file system types */ char d_name[256]; /* filename */ };

三、实验步骤

根据实验要求,实现指令ls的基本功能,即实现列出当前目录下的文件名,还有就是实现列出指定目录下的所有文件的文件名信息。 在编写好代码之后编译代码然后输入指令测试实验结果是否符合要求。

四、实验结果与分析

1、输入指令:./myls

输入默认的指令,输出当前目录下的文件名称,并用不同颜色区分文件夹和文件的区别。实验结果如下图图1所示:

图1 输出当前目录下所有的文件名

2、输入指令:./myls ./Documents

给定一个制定的路径,输出所给定路径下所有文件的文件名。结果如下图图2所示:

图2 输出指定目录下的所有文件名

五、程序源代码

/************************* *FileName:myls.c *Author:

*Date:2014/1/5

***************************/ #include <stdio.h>

#include <stdlib.h> #include <dirent.h> #include <errno.h> #include <string.h> #include <sys/ioctl.h> #include <unistd.h> #include <termios.h> #include <sys/stat.h> #define SPACE 4

/*自定义的字符串结构体 */ typedef struct{ char *str;/*实际内容*/ unsigned length;/*字符串长度*/ }String;

/*文件信息结构体*/ typedef struct{ unsigned length;/*集合中文件名的数量*/ unsigned i,j;/*i是行数,j是列数*/ String *filenames; unsigned maxlen;/*文件名集合中最大的文件名长度*/ char **formats;/*格式化输出序列*/ }FormatInfo;

/*获取无符号整型数十进制数的长度*/ unsigned unsigned_length(unsigned n){ unsigned length = 0; do{ ++length; n /= 10; }while(n) return length; }

/*预读根目录,将格式化输出的信息保存在info中*/ void Preread(char *root, FormatInfo *info) { DIR *dir; unsigned i,j,count = 0; struct dirent *ptr; String filename; unsigned *g = NULL;/*g是根据目录下的目录项名的长度进行分组的辅助变量*/ unsigned width = 0; unsigned group = 0; unsigned max = 0; unsigned row = 1; unsigned pos = 0;

struct winsize t_size; ioctl(STDIN_FILENO, TIOCGWINSZ, &t_size);/*获取终端的行数和列数*/ if(info == NULL){ printf("Error! \"info\" can not be NULL!\n"); return; } dir = opendir(root); if(dir == NULL){ perror("Fail to open dir.\n"); exit(1); } while(readdir(dir)) ++count;/*统计文件和目录的个数*/ rewinddir(dir);/*回卷读取目录的指针*/ info->filenames = (String *)malloc(sizeof(String) * count); g = (unsigned *)malloc(sizeof(unsigned) * count); i = 0;

/*获取文件或目录名和计算其长度*/ while((ptr = readdir(dir)) != NULL){ filename.str = ptr->d_name;/*文件或目录名*/ filename.length = strlen(ptr->d_name); info->filenames[i++] = filename; }

/*对目录项根据目录名或文件名用选择排序法从小到大进行排序*/ for(i=0;i<count;++i){ for(j=i;j<count;++j){ if(strcmp(info->filenames[i].str, info->filenames[j].str) > 0){ filename = info->filenames[i]; info->filenames[i] = info->filenames[j]; info->filenames[j] = filename; } } } /*用试探的方法测试最后列表的组数*/ group = count;/*先假定分为count个列表*/ row = 1;/*每列的行数为1*/ do{ for(j=0,width=0;j<group;++j){ for(i=0,max=0;i<row;++i){ /*找出每一列中文件或目录名最长的那一个*/ pos = j*row + i; if(pos >= count) break; if(info->filenames[pos].length > max){ max = info->filenames[pos].length;

g[j] = max;/*把每个列表的最大宽度存放到g数组里*/ } } width += (max + SPACE);/*将各组最长的文件或目录名的长度相加,把列表之间的间隔也算上*/ } /*假如其总宽度大于终端的宽度(列数),则把分组列表的数量减少,继续试探。*/ if(width >= t_size.ws_col){ --group; row = (count%group)?(count/group+1):(count/group); }else{ break;/*否则,估算列表的数量结束*/ } }while(1); info->formats = (char **)malloc(sizeof(char *) * group); info->maxlen = 0; for(i=0;i<group;++i){ if(g[i] > info->maxlen) info->maxlen = g[i];/*这里找出最大文件或目录名的长度*/ g[i] += SPACE;/*把列表之间的间隔算上*/ j = unsigned_length(g[i]) + 4; info->formats[i] = (char *)malloc(sizeof(char) * j); sprintf(info->formats[i],"%%-%us",g[i]);/*这里就是组织格式化输出字符串的关键部分*/ info->formats[i][j] = '\0'; } putchar('\n'); info->length = count; info->i = row;/*列表行数*/ info->j = group;/*列表数量*/ free(g); closedir(dir); }

void Myls(char *root){ FormatInfo fi; int i,j,pos,len; char *filepath = NULL; struct stat buf; Preread(root,&fi);/*预读目录*/ len = strlen(root); filepath = (char *)malloc(sizeof(char) * (strlen(root)+fi.maxlen+1)); filepath[0] = '\0'; strcat(filepath,root); if(filepath[len-1] != '/'){

filepath[len++] = '/'; } for(i=0,pos=0;i<fi.i;++i){ for(j=0;j<fi.j;++j){ pos = j*fi.i + i; if(pos < fi.length){ filepath[len] = '\0'; strcat(filepath, fi.filenames[pos].str); stat(filepath, &buf); if(S_ISDIR(buf.st_mode)){ printf("\033[01;36m");//Set color_dark-green }else{ printf("\033[0m");//Set default_color } printf(fi.formats[j],fi.filenames[pos]); }else if(i<fi.i){ break; }else{ putchar('\n'); return; } } putchar('\n'); } printf("\033[0m");//Restore default_color free(filepath); }

int main(int argc, char *argv[]){ if(argc < 1){ printf("参数错误!/n"); exit(1); }else if(argc == 1){ Myls("."); }else{ Myls(argv[1]); } return 0; }

六、实验体会

这次实验明显感觉到比前两次实验要简单一些,因为这些内容都是C语言学过的一些基本运用,知识要套用Linux系统中文件目录相关的一些系统调用和文件结构而已,然后进行一些简单的文件读取,以及文件信息的整理排序输出就可以实现ls指令的基本功能——列出文件目录中文件的文件名等信息。

此外我还在基本功能的上面做了一点小改进,如给输出目录中的文件夹用亮绿色输出,普通文件就用默认颜色输出,而且为了使文件名输出时排列整齐,我用了一个排序提取所有待输出文件中最长的一个文件名的长度,然后根据当前终端的显示行数,来确定每行列出的文件个数,使输出的文件能整齐打印到终端上显示。

本文来源:https://www.bwwdw.com/article/4uxe.html

Top