在學習linux的過程中,經常看到這樣一句話,一切皆文件,但一直對這句話不太理解,比如目錄怎麼會是文件呢?還有到處都會提到i節點,是個什麼東東呢?最近仔細看了下關於這方面的介紹,稍微對linux的文件存儲有了進一步的瞭解。
目錄其實也是一種文件,只不過這種文件比較特殊,它裏面存儲的是一張對應表,即文件名和i節點的對應關係表,而i節點纔是記錄此文件詳細信息的結構,如文件大小,屬性,權限,存在硬盤的那個塊等。我們在一個目錄創建文件就是在這張表裏添加對應關係而已,使用某個文件時也是根據i節點確定在硬盤的實際存儲位置的。使用“ls -iaR"命令嘗試看一下文件的i節點信息。
瞭解了這些信息後,讓我們來想想pwd命令是怎麼實現的。內核爲每個目錄都設置了一個指向自己的i節點入口,即".",還有一個指向其父目錄i節點的入口,即”..",我們首先獲取當前目錄的i節點編號,但是並不能知道當前目錄的名稱,我們切換到其的父目錄,在裏面尋找當前i節點編號對應的文件名即可。這樣我們就很容易聯想到使用遞歸來實現,但是終止條件是什麼呢?在Unix文件系統的根目錄中,“."和“..”指向同一個i節點,我們可以以此判斷是否發到達了根目錄,下面附上自己實現的pwd命令。
/*****************************************pwd*******************************************************
#include<stdio.h>
#include<sys/stat.h>
#include<sys/types.h>
#include<dirent.h>
#include<stdlib.h>
#include<string.h>
#define SIZE 128
ino_t get_inode(char *dirname);
void get_work_dir(ino_t inode_num);
void inode_to_dirname(ino_t inode_num, char *buf, int buflen);
int main(void)
{
get_work_dir(get_inode("."));
printf("\n");
return 0;
}
ino_t get_inode(char *dirname)
{
struct stat info;
if (stat(dirname, &info) == -1)
{
perror("dirname");
exit(1);
}
return info.st_ino;
}
void get_work_dir(ino_t inode_num)
{
ino_t parent_inode;
char buf[SIZE];
if (get_inode("..") != inode_num)
{
chdir("..");
inode_to_dirname(inode_num, buf, SIZE);
parent_inode = get_inode(".");
get_work_dir(parent_inode);
printf("/%s", buf);
}
}
void inode_to_dirname(ino_t inode_num, char *buf,int buflen)
{
DIR *dir_ptr;
struct dirent *dire;
if ((dir_ptr = opendir(".")) == NULL)
{
perror(".");
exit(1);
}
while ((dire = readdir(dir_ptr)) != NULL)
{
if (dire->d_ino == inode_num)
{
strncpy(buf, dire->d_name, buflen);
buf[strlen(buf)] = '\0';
closedir(dir_ptr);
return ;
}
}
fprintf(stderr, "error looking for inode number %d\n", (int)inode_num);
exit(1);
}
********************************************************************************/