Linux下DIR,dirent,stat等结构体详解

Linux下文件读取目录、文件路径:

首先说说DIR这一结构体

DIR结构体的定义:

    struct __dirstream   
       {   
        void *__fd;    
        char *__data;    
        int __entry_data;    
        char *__ptr;    
        int __entry_ptr;    
        size_t __allocation;    
        size_t __size;    
        __libc_lock_define (, __lock)    
       };   
      
    typedef struct __dirstream DIR;  

DIR结构体类似于FILE,是一个内部结构,以下几个函数用这个内部结构保存当前正在被读取的目录的有关信息(摘自《UNIX环境高级编程(第二版)》)。函数DIR *opendir(const char *pathname),即打开文件目录,返回的就是指向DIR结构体的指针,而该指针由以下几个函数使用:

    struct dirent *readdir(DIR *dp);   
      
    void rewinddir(DIR *dp);   
      
    int closedir(DIR *dp);   
      
    long telldir(DIR *dp);   
      
    void seekdir(DIR *dp,long loc);  

关于DIR结构,我们知道这么多就可以了,没必要去再去研究他的结构成员。

接着是dirent结构体,首先我们要弄清楚目录文件(directory file)的概念:这种文件包含了其他文件的名字以及指向与这些文件有关的信息的指针(摘自《UNIX环境高级编程(第二版)》)。从定义能够看出,dirent不仅仅指向目录,还指向目录中的具体文件,readdir函数同样也读取目录下的文件,这就是证据。

dirent结构体的定义:

    struct dirent   
    {   
      long d_ino; /* inode number 索引节点号 */  
         
        off_t d_off; /* offset to this dirent 在目录文件中的偏移 */  
         
        unsigned short d_reclen; /* length of this d_name 文件名长 */  
         
        unsigned char d_type; /* the type of d_name 文件类型 */  
         
        char d_name [NAME_MAX+1]; /* file name (null-terminated) 文件名,最长255字符 */  
    }  

从上述定义也能够看出来,dirent结构体存储的关于文件的信息很少,所以dirent同样也是起着一个索引的作用,如果想获得类似ls -l那种效果的文件信息,必须要靠stat函数了。

通过readdir函数读取到的文件名存储在结构体dirent的d_name成员中,而函数

int stat(const char *file_name, struct stat *buf);

的作用就是获取文件名为d_name的文件的详细信息,存储在stat结构体中。

stat结构体的定义:

    struct stat {   
      
            mode_t     st_mode;       //文件访问权限   
      
            ino_t      st_ino;       //索引节点号   
      
            dev_t      st_dev;        //文件使用的设备号   
      
            dev_t      st_rdev;       //设备文件的设备号   
      
            nlink_t    st_nlink;      //文件的硬连接数   
      
            uid_t      st_uid;        //所有者用户识别号   
      
            gid_t      st_gid;        //组识别号   
      
            off_t      st_size;       //以字节为单位的文件容量   
      
            time_t     st_atime;      //最后一次访问该文件的时间   
      
            time_t     st_mtime;      //最后一次修改该文件的时间   
      
            time_t     st_ctime;      //最后一次改变该文件状态的时间   
      
            blksize_t st_blksize;    //包含该文件的磁盘块的大小   
      
            blkcnt_t   st_blocks;     //该文件所占的磁盘块   
      
          };  

最后,总结一下,想要获取某目录下(比如a目下)b文件的详细信息,我们应该怎样做?

首先,我们使用opendir函数打开目录a,返回指向目录a的DIR结构体c。

接着,我们调用readdir( c)函数读取目录a下所有文件(包括目录),返回指向目录a下所有文件的dirent结构体d。

然后,我们遍历d,调用stat(d->name,stat *e)来获取每个文件的详细信息,存储在stat结构体e中。

总体就是这样一种逐步细化的过程,在这一过程中,三种结构体扮演着不同的角色。

---------------------------------------------------------------------华丽丽的分割线---------------------------------------------------------------------------------------------------------------------------------------------
补充:
首先,关于上文提到的“ DIR结构体类似于FILE,是一个内部结构”此句中的内部结构不是很明白,后来看到一遍博文有介绍FILE结构,具体如下:

“ struct file结构体定义在include/linux/fs.h中定义。文件结构体代表一个打开的文件,系统中的每个打开的文件在内核空间都有一个关联的 struct file。它由内核在打开文件时创建,并传递给在文件上进行操作的任何函数。在文件的所有实例都关闭后,内核释放这个数据结构。在内核创建和驱动源码中,struct file的指针通常被命名为file或filp。”
此处说FILE结构是在内核打开文件时创建的。参考以前的关于FILE操作的代码可以发现,我们在使用FILE结构时是直接声明一个FILE结构的指针,例如:
FILE *fp
然后使用fopen函数返回一个FILE结构指针给fp。我们并没有声明一个结构体,而只是声明该结构体的指针。
所以本人猜测,具体的结构体的内存分配已经由内核帮我们完成了。
DIR结构的使用方法和FILE类似,在《Linux程序设计第四版》的P104有一个

打印目录下所有文件及目录的程序

代码如下:

    #include <unistd.h>
    #include <stdio.h>
    #include <dirent.h>
    #include <string.h>
    #include <sys/stat.h>
    #include <stdlib.h>
     
     
    void printdir(char *dir, int depth)
    {
    	DIR *dp;
    	struct dirent *entry;
    	struct stat statbuf;
     
    	if ((dp = opendir(dir)) == NULL) {
    		fprintf(stderr, "Can`t open directory %s\n", dir);
    		return ;
    	}
    	
    	chdir(dir);
    	while ((entry = readdir(dp)) != NULL) {
    		lstat(entry->d_name, &statbuf);
    		if (S_ISDIR(statbuf.st_mode)) {
    			if (strcmp(entry->d_name, ".") == 0 || 
    				strcmp(entry->d_name, "..") == 0 )  
    				continue;	
    			printf("%*s%s/\n", depth, "", entry->d_name);
    			printdir(entry->d_name, depth+4);
    		} else
    			printf("%*s%s\n", depth, "", entry->d_name);
    	}
    	chdir("..");
    	closedir(dp);	
    }
     
     
    int main(int argc, char *argv[])
    {
    	char *topdir = ".";
    	if (argc >= 2)
    		topdir = argv[1];
     
    	printf("Directory scan of %s\n", topdir);
    	printdir(topdir, 0);
    	printf("done.\n");
    	exit(0);
    }

在这个程序中我们使用的DIR结构也只是声明了该结构的指针,那么DIR结构应该也是同FILE结构一样,在打开一个目录的时候,由内核帮我们分配该结构体的内存。
dirent结构也是如此。但stat结构却是要我们自己声明结构体的。

以上转自:https://blog.csdn.net/zhuyi2654715/article/details/7605051

d_type表示档案类型:

enum
{
    DT_UNKNOWN = 0,         //未知类型
# define DT_UNKNOWN DT_UNKNOWN
    DT_FIFO = 1,            //管道
# define DT_FIFO DT_FIFO
    DT_CHR = 2,             //字符设备
# define DT_CHR DT_CHR
    DT_DIR = 4,             //目录
# define DT_DIR DT_DIR
    DT_BLK = 6,             //块设备
# define DT_BLK DT_BLK
    DT_REG = 8,             //常规文件
# define DT_REG DT_REG
    DT_LNK = 10,            //符号链接
# define DT_LNK DT_LNK
    DT_SOCK = 12,           //套接字
# define DT_SOCK DT_SOCK
    DT_WHT = 14             //链接
# define DT_WHT DT_WHT
};

以上转自:https://www.cnblogs.com/jikexianfeng/p/7084911.html

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值