stat函数,实现一个简易的ls命令(my_ls),将指定文件的属性信息打印出来(文件属性)【linux】(o)

stat函数,实现一个简易的ls命令(my_ls),将指定文件的属性信息打印出来(文件属性)

Stat函数

Stat、lstat、fstat这三个函数实现的功能相同,只是略微有区别,我们只要先把stat函数搞清楚了,lstat、fstat非常容易理解。

ls命令其实就是调用了这三个函数中的lstat来实现的,我们可以调用lstat函数来自己实现一个ls命令。

我们在这里说明这三个函数,并不是真的去实现一个ls命令,而是通过这三个函数的学习,深刻的理解文件各种属性,进而理解了“文件”。

stat函数

函数原型

#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
int stat(const char *path, struct stat *buf);

我们可以通过 man 2 stat进行查看
在这里插入图片描述

函数功能

功能就是获取文件的属性信息。每个文件的属性信息,都是存在块设备上、该文件自己的inode节点空间中的。调用stat函数时,文件系统通过stat给的path,到块设备上索引到该文件的inode节点空间,然后将里面的文件属性信息,读到应用程序的缓存中,如此就得到了文件的属性信息。

文件属性数据中转的过程:

块设备上的inode结点 ------> 驱动程序的缓存 --------> stat函数提供的内核缓存-------->应用缓存

返回值

调用成功,返回0,失败返回-1,errno被设置。

参数说明

int stat(const char *path, struct stat buf);
(1)const char path:文件路径名

(2)struct stat *buf:应用缓存,用于存放读到的文件属性信息

缓存的类型为struct stat,通过man 2 stat,可以查看到struct stat结构体类型。

struct stat {
	dev_t     st_dev;      	 /* 块设备号(ID)块设备驱动程序的编号 */
	ino_t     st_ino;        /* inode结点号,文件属性信息所存inode节点的编号 */ 
	mode_t    st_mode;    	 /* 文件类型和文件权限*/  ls
	nlink_t   st_nlink;      /* 链接数 */             ls
	uid_t     st_uid;        /* 文件所属用户ID*/      ls
	gid_t     st_gid;        /* 文件所属组ID */       ls
	dev_t     st_rdev;       /* 字符设备ID */         
	off_t     st_size;       /* 文件大小 */
	blksize_t st_blksize;    /* 系统每次按块Io操作时,块的大小(一般是512或1024) */
	blkcnt_t  st_blocks;  	 /* 块的索引号 */
	/* windows下,文件的时间,同样也分为这三种 */
	time_t    st_atime;   	/* 最后一次访问时间,read*/  ls
	time_t    st_mtime; 	 	/* 最后一次修改时间,write */
	time_t    st_ctime;   	/* 最后一次属性修改的时间,如权限被修改,文件所有者(属主)被修改 */
	};

其中标记有ls的,表示这些属性,是我们ls查看时,会显示的内容。

我们可以在通过帮助手册进行查看:
在这里插入图片描述

实现一个自己的ls命令(my_ls),将指定文件的属性信息打印出来。

#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>

void print_error(char *str)
{
         perror(str);
         exit(-1);
}
int main(void)
{
        int ret = 0;
        struct stat sta = {0};
        //int stat(const char *pathname, struct stat *statbuf);
        //获取文件属性
        ret = stat("./new.txt",&sta);
        if(-1 == ret)   print_error("stat fail");
        ////打印文件属性
        printf("%d %lu %d %d %ld %ld %s\n",sta.st_mode,sta.st_nlink,sta.st_uid,sta.st_gid,sta.st_size,sta.st_atime,"new.txt");
        return 0;
}     

执行结果为:

在这里插入图片描述

打印出来的都是数字
在这里插入图片描述
和我们ls -l new.txt所显示的显示的不一样:

Linux都是以数字形式来管理属性信息的,我们需要自己把它翻译为更好理解英文字母。

接下来我们把程序改的更像ls命令:
(1)名字改为 my_ls
(2)ls可以跟参数,让我的程序也可以跟参数

我们在编译的时候重命名最终可执行文件为 my_ls ,我们知道main函数是有参数的,所以我们在运行main函数的时候就可以传递参数。
我们对于代码进行修改:

#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>

void print_error(char *str)
{
         perror(str);
         exit(-1);
}
int main(int argc,char **argv)
{
        int ret = 0;
        struct stat sta = {0};
        //int stat(const char *pathname, struct stat *statbuf);
        //获取文件属性
        if(argc != 2)
        {
                printf("my_ls fileName\n\n");
                exit(-1);
        }
        printf("argv[0] = %s,argc[1] = %s\n",argv[0],argv[1]);
        ret = stat(argv[1],&sta); 
        if(-1 == ret)   print_error("stat fail");
        ////打印文件属性
        printf("%d %lu %d %d %ld %ld %s\n",sta.st_mode,sta.st_nlink,sta.st_uid,sta.st_gid,sta.st_size,sta.st_atime,argv[1]);
        return 0;
}   
    

这个时候我们需要跟接一个文件名,我们在执行的时候加上文件名为参数
第一个参数是表示的是程序路径名 第二个参数表示所要显示的文件路径名
执行结果为:

在这里插入图片描述

如果我们没有给参数 就会直接打印文件名错误,所以我们通过给可执行程序跟上文件名参数来打印文件属性。我们程序的功能就是执行并输入所要显示的文件文件之后,显示详细文件属性信息。

发布了84 篇原创文章 · 获赞 71 · 访问量 9100

猜你喜欢

转载自blog.csdn.net/qq_43648751/article/details/104199405