操作系统第四次实验报告:文件系统

姓名:傅伟杰

学号:201821121018

班级:计算1811

1. 编写程序

在服务器上用Vim编写一个程序:实现Linux系统命令ls -lai的功能,给出源代码。

源代码:

lab4.c
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<time.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<grp.h>
#include<pwd.h>
#include<dirent.h>

void myls(char []);
void do_stat(char *);
void print_myinfo(char *,struct stat *);
void mode_to_type(int mode,char buf[]);
char *uid_to_name(uid_t uid);
char *gid_to_name(gid_t gid);
void myls(char dir[])
{
        DIR  *pathdir = opendir(dir);//获取路径
        struct dirent *pd = NULL;
        if(pathdir == NULL)//路径为空
        {
                fprintf(stderr,"open dir is error!\n");
        }
        else//路径不为空
        {
                while((pd = readdir(pathdir)) != NULL)
                        /*一次读取目录中的下一个文件,直到读完*/
                {
                        do_stat(pd->d_name);
                }
                closedir(pathdir);
                /*关闭pathdir指向的目录流*/
        }
}

void do_stat(char *file)
{
        struct stat myinfo;
        if(stat(file,&myinfo) == -1)
        {
                perror(file);//出错情况,输出文件名
        }
        else
        {
                print_myinfo(file,&myinfo);
        }
}

void print_myinfo(char *file,struct stat* p_myinfo)
{
        char *uid_to_name(),*ctime(),*gid_to_name();
        void mode_to_type();
        char str[11];
        mode_to_type(p_myinfo->st_mode,str);
        printf("%d ",(int)p_myinfo->st_ino);
        printf("%s",str);
        printf("%4d ",(int)p_myinfo->st_nlink);
        printf("%-8s ",uid_to_name(p_myinfo->st_uid));
        printf("%-8s ",gid_to_name(p_myinfo->st_gid));
        printf("%8ld ",(long)p_myinfo->st_size);
        printf("%.12s ",4 + ctime(&p_myinfo->st_mtime));
        printf("%s\n",file);
}
void mode_to_type(int md,char mode[])
{
        strcpy(mode,"-----------");
        if(S_ISCHR(md)) mode[0] = 'c';
        if(S_ISDIR(md)) mode[0] = 'd';
        if(S_ISBLK(md)) mode[0] = 'b';

        if(md & S_IRUSR) mode[1] = 'r';
        if(md & S_IWUSR) mode[2] = 'w';
        if(md & S_IXUSR) mode[3] = 'x';
        if(md & S_IRGRP) mode[4] = 'r';
        if(md & S_IWGRP) mode[5] = 'w';
        if(md & S_IXGRP) mode[6] = 'x';
        if(md & S_IROTH) mode[7] = 'r';
        if(md & S_IWOTH) mode[8] = 'w';
        if(md & S_IXOTH) mode[9] = 'x';

}

char *uid_to_name(uid_t uid)
{
        struct passwd * getpwuid(),*pw_ptr;
        static char str[10];
        if((pw_ptr = getpwuid(uid)) == NULL)
        {
                sprintf(str,"%d",uid);
                return str;
        }
        else
        {
                return pw_ptr->pw_name;
        }
}
char *gid_to_name(gid_t gid)
{
        struct group  * getgrgid(),*grp_ptr;
        static char str[10];
        if((grp_ptr = getgrgid(gid)) == NULL)
        {
                sprintf(str,"%d",gid);
                return str;
        }
        else
        {
                return grp_ptr->gr_name;
        }
}
int main(int argc,char **argv)
{
        if(argc == 1)
        {
                myls(".");
        }
        else
        {
                while(--argc)
                {
                        printf("%s:\n",*++argv);
                        myls(*argv);
                }
        }
        return 0;
}

 

2. 分析运行结果

给出运行结果截图,对于每一列是如何获取的,结合源代码做解释

下面先给出系统ls -lai 的截图:

操作系统第四次实验报告:文件系统

 

 运行编写的c程序得到的数据的截图:

操作系统第四次实验报告:文件系统

 

 

 首先先进行ls指令的具体分析:

下面给出一些较为常见的参数,并解释参数的意义

-a 显示所有文件及目录 (ls内定将文件名或目录名称开头为"."的视为隐藏档,不会列出)

-l 除文件名称外,亦将文件型态、权限、拥有者、文件大小等资讯详细列出

-r 将文件以相反次序显示(原定依英文字母次序)-t 将文件依建立时间之先后次序列出

-A 同 -a ,但不列出 "." (目前目录) 及 ".." (父目录)

-F 在列出的文件名称后加一符号;例如可执行档则加 "*", 目录则加 "/"

-R 若目录下有文件,则以下之文件亦皆依序列出

-i –inode 印出每个文件的 inode 号

在linux中通过ls指令输出的文件名的颜色是有着一定的意义的

默认颜色为普通文件

绿色为可执行文件  

红色为tar包文件

蓝色为目录文件

水红色为图像文件

青色为链接文件

黄色为设备文件

具体颜色可参考下图:

操作系统第四次实验报告:文件系统

我们这一次实验需要实现的时 ls -lai:

首先要做的是获取目录下面的文件名称:

具体实现

函数myls
void myls(char dir[])
{
        DIR  *pathdir = opendir(dir);//获取路径
        struct dirent *pd = NULL;
        if(pathdir == NULL)//路径为空
        {
                fprintf(stderr,"open dir is error!\n");
        }
        else//路径不为空
        {
                while((pd = readdir(pathdir)) != NULL)
                        /*一次读取目录中的下一个文件,直到读完*/
                {
                        do_stat(pd->d_name);
                }
                closedir(pathdir);
                /*关闭pathdir指向的目录流*/
        }
}

然后获取文件:

接着解释一下获取某个目录下的某个文件的详细信息的操作

1.首先,通过opendir()函数打开目录,然后返回指向目录的DIR结构体

2.然后,调用readir()函数读取目录下面的索引文件,并返回指向该目录下的所有文件的dirent结构体d

3.最后遍历d,调用stat进行详细信息的获取

具体实现

函数print_myinfo
void print_myinfo(char *file,struct stat* p_myinfo)
{
        char *uid_to_name(),*ctime(),*gid_to_name();
        void mode_to_type();
        char str[11];
        mode_to_type(p_myinfo->st_mode,str);
        printf("%d ",(int)p_myinfo->st_ino);
        printf("%s",str);
        printf("%4d ",(int)p_myinfo->st_nlink);
        printf("%-8s ",uid_to_name(p_myinfo->st_uid));
        printf("%-8s ",gid_to_name(p_myinfo->st_gid));
        printf("%8ld ",(long)p_myinfo->st_size);
        printf("%.12s ",4 + ctime(&p_myinfo->st_mtime));
        printf("%s\n",file);
}

关于stat和dirent的解释

stat结构体的具体内容如下
    dev_t         st_dev;       //文件的设备编号
    ino_t          st_ino;       //节点**
    mode_t      st_mode;      //文件的类型和存取的权限**
    nlink_t        st_nlink;     //连到该文件的硬连接数目,刚建立的文件值为1
    uid_t          st_uid;       //用户ID**
    gid_t          st_gid;       //组ID**
    dev_t         st_rdev;      //(设备类型)若此文件为设备文件,则为其设备编号
    off_t          st_size;      //文件字节数(文件大小)**
    unsigned long st_blksize;   //块大小(文件系统的I/O 缓冲区大小)
    unsigned long st_blocks;    //块数
    time_t        st_atime;     //最后一次访问时间**
    time_t        st_mtime;     //最后一次修改时间**
    time_t        st_ctime;     //最后一次改变时间(指属性)**
**代表本次编写中有使用到的

dirent结构体集具体如下:

long d_ino;  //索引号节点号

off_t d_off;  //目录中的偏移量

unsigned short d_reclen;  //文件长度

char d_name [NAME_MAX+1];  //文件名称

 

3. 通过该实验产生新的疑问及解答

Question:我编写的程序中相比于系统的ls还是较为简陋的,主要的点在于输出文件的颜色含义并没有对应好,如何对不同的文件类型采取正确的分类?

 

Answer:具体内容参考了下列网站(见参考资料第二条),了解了关于linux ansi控制码的一些相关信息,发现能够成功解决,只需要在输出的时候判断文件类型,并选择对应的ansi码进行颜色控制即可.

 

参考资料:

https://www.runoob.com/linux/linux-comm-ls.html

https://blog.csdn.net/daoer_sofu/article/details/102456935

https://www.cnblogs.com/xiaoshiwang/p/10764243.html

上一篇:Python操作Redis(六)


下一篇:CentOS 7设置网络开机自动连接