目錄項和超級塊,節點的概念不同,它在設備上沒有對應的磁盤數據結構。相反,它是目錄文 件的一部分。linux中目錄也是一種文件,類型是'd'。但是目錄中的內容和普通文件不同,它是由目錄項組成的。注意目錄項不是目錄。我們經常用路徑名 執行相關操作,目錄項就是爲了查找方便的。
struct dirt_entry{
unsigned
short inode;
char
name[NAME_LEN];
};
可 以看到一個目錄項中包含了文件的i節點號和文件的名稱。路徑有兩種,一種是絕對路徑,一種是相對路徑。比如/home/fish就是絕對路徑,它以根目錄 /爲開頭,而 X11/xorg.conf就是相對路徑,它相對於目錄/etc,也就是說後者的絕對路徑是/etc/X11/xorg.conf。路徑是由目錄項組成 的。拿 /home/fish/fish.c來說,第一個目錄是/,即根目錄。在根目錄文件中有名字爲home的目錄項。然後通過home目錄項中的i節點就可以 找到home文件,通過i節點中的i_mode字段可知它是一個目錄,在這個文件中有名爲fish的目錄項,然後根據這個目錄項中的i節點號找到fish 文件。同樣由fish的inode->i_mode知這也是個目錄。同樣在fish文件中找到名爲fish.c的目錄項,就可以找出fish.c的 i節點,搜索完成。
namei.c 是內核中最長的一個文件,它包含了許多關於目錄的操作,如find_entry(從一個目錄中搜索制定的目錄項),add_entry(往指定的目錄中添 加一個文件目錄項),get_dir(根據路徑名找到指定的目錄),dir_namei(返回指定目錄的i節點指針),還有namei(根據路徑名找到指 定路徑的i節點)等等。我們就先拿find_entry來看一下。
//dir:指定目錄的i節點指針。name:文件名,namelen:文件名長度。
//返回:高速緩衝區指針和相應的目錄項指針。
static struct buffer_head* find_entry(struct m_inode **dir,const char*name,int namelen,struct dir_entry **res_dir)
{
int
entries;
int
block ,i;
struct
buffer_head *bh;
struct
dir_entry *de;
struct
super_blocl *sb;
//如果定義了NO_TRUNCATE,則如果文件名大於最大長度NAME_LEN,返回。
#ifdef NO_TRUNCATE
if(namelen
>NAME_LEN)
return
NULL;
#else
if(namelen>NAME_LEN)
namelen=NAME_LEN;
//計算本目錄中的目錄項數
entries=(*dir)->i_size/(sizeof(struct
dir_entry));
*res_dir=NULL;
if(!namelen)
return
NULL;
//如果是目錄'..',對其進行特殊處理.
if(namelen==2&&get_fs_byte(name)=='.'&&get_fs_byte(name+1)=='.'){
//如果本目錄是進程的根目錄,那麼就將文件名修改爲'.'.
if((*dir)==current->root)
namelen=1;
//如果本目錄是文件系統的根目錄,那麼取出文件系統的超級塊
else
if((*dir)->i_num==ROOT_INO){
sb=get_super((*dir)->i_dev);
//如果本文件系統的安裝節點存在,那麼就釋放原i節點,將*dir指向被安裝到的i節點。對於根文件系統來說,就是它的根節點。
if(sb->s_imount){
iput(*dir);
(*dir)=sb->s_imount;
(*dir)->i_count++;
}
}
}
//如果第i節點指向的第一個直接塊號爲0,則返回
if(!block=(*dir)->i_zone[0]))
return
NULL;
//讀取節點坐在設備的目錄項數據。也就是本目錄文件的內容
if(!(bh=bread((*dir)->i_dev,block)))
return
NULL;
//在bh中搜索指定的目錄項
i=0;
de=(struct
dir_entry*)bh->data;
while(i<entries){
//如果當前的文件塊搜索完畢,則準備搜索下一塊
if((char*)de>=BLOCK_SIZE+bh->b_data){
brelse(bh);
struct dirt_entry{
};
可 以看到一個目錄項中包含了文件的i節點號和文件的名稱。路徑有兩種,一種是絕對路徑,一種是相對路徑。比如/home/fish就是絕對路徑,它以根目錄 /爲開頭,而 X11/xorg.conf就是相對路徑,它相對於目錄/etc,也就是說後者的絕對路徑是/etc/X11/xorg.conf。路徑是由目錄項組成 的。拿 /home/fish/fish.c來說,第一個目錄是/,即根目錄。在根目錄文件中有名字爲home的目錄項。然後通過home目錄項中的i節點就可以 找到home文件,通過i節點中的i_mode字段可知它是一個目錄,在這個文件中有名爲fish的目錄項,然後根據這個目錄項中的i節點號找到fish 文件。同樣由fish的inode->i_mode知這也是個目錄。同樣在fish文件中找到名爲fish.c的目錄項,就可以找出fish.c的 i節點,搜索完成。
namei.c 是內核中最長的一個文件,它包含了許多關於目錄的操作,如find_entry(從一個目錄中搜索制定的目錄項),add_entry(往指定的目錄中添 加一個文件目錄項),get_dir(根據路徑名找到指定的目錄),dir_namei(返回指定目錄的i節點指針),還有namei(根據路徑名找到指 定路徑的i節點)等等。我們就先拿find_entry來看一下。
//dir:指定目錄的i節點指針。name:文件名,namelen:文件名長度。
//返回:高速緩衝區指針和相應的目錄項指針。
static struct buffer_head* find_entry(struct m_inode **dir,const char*name,int namelen,struct dir_entry **res_dir)
{
//如果定義了NO_TRUNCATE,則如果文件名大於最大長度NAME_LEN,返回。
#ifdef NO_TRUNCATE
#else
//計算本目錄中的目錄項數
//如果是目錄'..',對其進行特殊處理.
//如果本目錄是進程的根目錄,那麼就將文件名修改爲'.'.
//如果本目錄是文件系統的根目錄,那麼取出文件系統的超級塊
//如果本文件系統的安裝節點存在,那麼就釋放原i節點,將*dir指向被安裝到的i節點。對於根文件系統來說,就是它的根節點。
//如果第i節點指向的第一個直接塊號爲0,則返回
//讀取節點坐在設備的目錄項數據。也就是本目錄文件的內容
//在bh中搜索指定的目錄項
//如果當前的文件塊搜索完畢,則準備搜索下一塊