Linux下DIR,dirent,stat等結構體詳解

最近在看Linux下文件操作相關章節,遇到了這麼幾個結構體,被搞的暈乎乎的,今日有空,仔細研究了一下,受益匪淺。

首先說說DIR這一結構體,以下爲DIR結構體的定義:

 
  1. struct __dirstream   
  2.    {   
  3.     void *__fd;    
  4.     char *__data;    
  5.     int __entry_data;    
  6.     char *__ptr;    
  7.     int __entry_ptr;    
  8.     size_t __allocation;    
  9.     size_t __size;    
  10.     __libc_lock_define (, __lock)    
  11.    };   
  12.   
  13. typedef struct __dirstream DIR;  

 

DIR結構體類似於FILE,是一個內部結構,以下幾個函數用這個內部結構保存當前正在被讀取的目錄的有關信息(摘自《UNIX環境高級編程(第二版)》)。函數 DIR *opendir(const char *pathname),即打開文件目錄,返回的就是指向DIR結構體的指針,而該指針由以下幾個函數使用:

 

 
  1. struct dirent *readdir(DIR *dp);   
  2.   
  3. void rewinddir(DIR *dp);   
  4.   
  5. int closedir(DIR *dp);   
  6.   
  7. long telldir(DIR *dp);   
  8.   
  9. void seekdir(DIR *dp,long loc);  

 

關於DIR結構,我們知道這麼多就可以了,沒必要去再去研究他的結構成員。

接着是dirent結構體,首先我們要弄清楚目錄文件(directory file)的概念:這種文件包含了其他文件的名字以及指向與這些文件有關的信息的指針(摘自《UNIX環境高級編程(第二版)》)。從定義能夠看出,dirent不僅僅指向目錄,還指向目錄中的具體文件,readdir函數同樣也讀取目錄下的文件,這就是證據。以下爲dirent結構體的定義:

 

 
  1. struct dirent   
  2. {   
  3.   long d_ino; /* inode number 索引節點號 */  
  4.      
  5.     off_t d_off; /* offset to this dirent 在目錄文件中的偏移 */  
  6.      
  7.     unsigned short d_reclen; /* length of this d_name 文件名長 */  
  8.      
  9.     unsigned char d_type; /* the type of d_name 文件類型 */  
  10.      
  11.     char d_name [NAME_MAX+1]; /* file name (null-terminated) 文件名,最長255字符 */  
  12. }  

 

從上述定義也能夠看出來,dirent結構體存儲的關於文件的信息很少,所以dirent同樣也是起着一個索引的作用,如果想獲得類似ls -l那種效果的文件信息,必須要靠stat函數了。

通過readdir函數讀取到的文件名存儲在結構體dirent的d_name成員中,而函數

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

的作用就是獲取文件名爲d_name的文件的詳細信息,存儲在stat結構體中。以下爲stat結構體的定義:

 

 
  1. struct stat {   
  2.   
  3.         mode_t     st_mode;       //文件訪問權限   
  4.   
  5.         ino_t      st_ino;       //索引節點號   
  6.   
  7.         dev_t      st_dev;        //文件使用的設備號   
  8.   
  9.         dev_t      st_rdev;       //設備文件的設備號   
  10.   
  11.         nlink_t    st_nlink;      //文件的硬連接數   
  12.   
  13.         uid_t      st_uid;        //所有者用戶識別號   
  14.   
  15.         gid_t      st_gid;        //組識別號   
  16.   
  17.         off_t      st_size;       //以字節爲單位的文件容量   
  18.   
  19.         time_t     st_atime;      //最後一次訪問該文件的時間   
  20.   
  21.         time_t     st_mtime;      //最後一次修改該文件的時間   
  22.   
  23.         time_t     st_ctime;      //最後一次改變該文件狀態的時間   
  24.   
  25.         blksize_t st_blksize;    //包含該文件的磁盤塊的大小   
  26.   
  27.         blkcnt_t   st_blocks;     //該文件所佔的磁盤塊   
  28.   
  29.       };  

 

這個記錄的信息就很詳細了吧,呵呵。

最後,總結一下,想要獲取某目錄下(比如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有一個打印目錄下所有文件及目錄的程序,代碼如下:
[cpp] view plain copy
 



  1. #include <unistd.h>  
  2. #include <stdio.h>  
  3. #include <dirent.h>  
  4. #include <string.h>  
  5. #include <sys/stat.h>  
  6. #include <stdlib.h>  
  7.   
  8.   
  9. void printdir(char *dir, int depth)  
  10. {  
  11.     DIR *dp;  
  12.     struct dirent *entry;  
  13.     struct stat statbuf;  
  14.   
  15.     if ((dp = opendir(dir)) == NULL) {  
  16.         fprintf(stderr, “Can`t open directory %s\n”, dir);  
  17.         return ;  
  18.     }  
  19.       
  20.     chdir(dir);  
  21.     while ((entry = readdir(dp)) != NULL) {  
  22.         lstat(entry->d_name, &statbuf);  
  23.         if (S_ISDIR(statbuf.st_mode)) {  
  24.             if (strcmp(entry->d_name, ”.”) == 0 ||   
  25.                 strcmp(entry->d_name, “..”) == 0 )    
  26.                 continue;     
  27.             printf(“%*s%s/\n”, depth, ”“, entry->d_name);  
  28.             printdir(entry->d_name, depth+4);  
  29.         } else  
  30.             printf(“%*s%s\n”, depth, ”“, entry->d_name);  
  31.     }  
  32.     chdir(“..”);  
  33.     closedir(dp);     
  34. }  
  35.   
  36.   
  37. int main(int argc, char *argv[])  
  38. {  
  39.     char *topdir = ”.”;  
  40.     if (argc >= 2)  
  41.         topdir = argv[1];  
  42.   
  43.     printf(“Directory scan of %s\n”, topdir);  
  44.     printdir(topdir, 0);  
  45.     printf(“done.\n”);  
  46.     exit(0);  
  47. }  


在這個程序中我們使用的DIR結構也只是聲明瞭該結構的指針,那麼DIR結構應該也是同FILE結構一樣,在打開一個目錄的時候,由內核幫我們分配該結構體的內存。
dirent結構也是如此。但stat結構卻是要我們自己聲明結構體的。


轉載自:https://www.cnblogs.com/fnlingnzb-learner/p/6472404.html

發佈了71 篇原創文章 · 獲贊 279 · 訪問量 24萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章