Linux2 6X核心中檔案相關結構體總結

2021-07-29 11:41:33 字數 4000 閱讀 2185

乙個程序中各主要的檔案相關結構

的關係圖:

下圖為多個程序開啟同一檔案的情況:

struct file結構體定義在include/linux/fs.h中定義。檔案結構體代表乙個開啟的檔案,系統中的每個開啟的檔案在核心空間都有乙個關聯的struct file。它由核心在開啟檔案時建立,並傳遞給在檔案上進行操作的任何函式。在檔案的所有例項都關閉後,核心釋放這個資料結構。在核心建立和驅動原始碼中,struct file的指標通常被命名為file或filp。如下所示:

struct file f_u;

struct path f_path;  包含dentry和mnt兩個成員,用於確定檔案路徑

#define f_dentry  f_path.dentry  f_path的成員之一,當前檔案的dentry結構

#define f_vfsmnt  f_path.mnt  表示當前檔案所在檔案系統的掛載根目錄

const struct file_operations *f_op; 與該檔案相關聯的操作函式

atomic_t  f_count; 檔案的引用計數(有多少程序開啟該檔案)

unsigned int  f_flags;  對應於open時指定的flag

mode_t  f_mode; 讀寫模式:open的mod_t mode引數

off_t  f_pos; 該檔案在當前程序中的檔案偏移量

struct fown_struct f_owner; 該結構的作用是通過訊號進行i/o時間通知的資料。

unsigned int  f_uid, f_gid; 檔案所有者id,所有者組id

struct file_ra_state f_ra;  在linux/include/linux/fs.h中定義,檔案預讀相關

unsigned long f_version;

#ifdef config_security

void  *f_security;

#endif

/* needed for tty driver, and maybe others */

void *private_data;

#ifdef config_epoll

/* used by fs/eventpoll.c to link all the hooks to this file */

struct list_head f_ep_links;

spinlock_t f_ep_lock;

#endif /* #ifdef config_epoll */

};dentry的中文名稱是目錄項,是linux檔案系統中某個索引節點(inode)的鏈結。這個索引節點可以是檔案,也可以是目錄。inode(可理解為ext2 inode)對應於物理磁碟上的具體物件,dentry是乙個記憶體實體,其中的d_inode成員指向對應的inode。也就是說,乙個inode可以在執行的時候鏈結多個dentry,而d_count記錄了這個鏈結的數量。

struct dentry ;

對於每個程序,包含乙個files_struct結構,用來記錄檔案描述符的使用情況,定義在include/linux/file.h中

struct files_struct

;struct fdtable ;

struct fs_struct ;

索引節點物件由inode結構體表示,定義檔案在linux/fs.h中。

例項 2.1 由相對路徑得到絕對路徑

核心的結構體不提供檔案的絕對路徑成員,由相對路徑得到絕對路徑的關鍵在得到當前的工作路徑。

當前的工作路徑可以由current->fs的pwd和pwdmnt成員得到,基本過程:

1、由pwd->d_name.name得到當前路徑名,由pwd->d_parent得到父目錄dentry結構,

一直向上檢索,直到父目錄為"/",此時得到的是檔案在本檔案系統下的路徑。

2、如果current->fs->pwdmnt->mnt_mountpoint的路徑不是"/",說明檔案所在的檔案系統不是掛載在根目錄下,需要得到掛載點。mnt_mountpoint也是乙個dentry變數,方法同1。

3、最後把檔案系統掛載點和檔案在檔案系統中的路徑拼接起來即可。

2.2 由檔案描述符得到檔案的絕對路徑

由當前程序的檔案描述符得到檔案的絕對路徑:

#if linux_version_code >= 0x020616

由current->files->fdt->fd[fd]->f_path.dentry->d_name.name

和current->files->fdt->fd[fd]->f_path.dentry->d_parent

得到在所在檔案系統下的路徑

由current->files->fdt->fd[fd]->f_path.mnt->mnt_mountpoint->d_name.name

和current->files->fdt->fd[fd]->f_path.mnt->mnt_mountpoint->d_parent

得到檔案系統掛載點在系統中掛載點的路徑

#elif linux_version_code >= 0x020610

由current->files->fdt->fd[fd]->f_dentry->d_name.name

和current->files->fdt->fd[fd]->f_dentry->d_parent

得到在所在檔案系統下的路徑

由current->files->fdt->fd[fd]->f_vfsmnt->mnt_mountpoint->d_name.name

和current->files->fdt->fd[fd]->f_vfsmnt->mnt_mountpoint->d_parent

得到檔案系統掛載點在系統中掛載點的路徑

#else

由current->files->fd[fd]->f_dentry->d_name.name

和current->files->fd[fd]->f_dentry->d_parent

得到在所在檔案系統下的路徑

由current->files->fd[fd]->f_vfsmnt->mnt_mountpoint->d_name.name

和current->files->fd[fd]->f_vfsmnt->mnt_mountpoint->d_parent

得到檔案系統掛載點在系統中掛載點的路徑

#endif

2.3 得到當前程序的絕對路徑

#if linux_version_code >= 0x020616

由current->mm->mmap->vm_file->f_path.dentry->d_name.name

和current->mm->mmap->vm_file->f_path.dentry->d_parent

得到在所在檔案系統下的路徑

由current->mm->mmap->vm_file->f_path.mnt->mnt_mountpoint->d_name.name

和current->mm->mmap->vm_file->f_path.mnt->mnt_mountpoint->d_parent

得到檔案系統掛載點在系統中掛載點的路徑

#else

由current->mm->mmap->vm_file->f_dentry->d_name.name

和current->mm->mmap->vm_file->f_dentry->d_parent

得到在所在檔案系統下的路徑

由current->mm->mmap->vm_file->f_vfsmnt->mnt_mountpoint->d_name.name

和current->mm->mmap->vm_file->f_vfsmnt->mnt_mountpoint->d_parent

得到檔案系統掛載點在系統中掛載點的路徑

#endif

在linux核心中讀寫檔案

1.序曲 在使用者態,讀寫檔案可以通過read和write這兩個系統呼叫來完成 c庫函式實際上是對系統呼叫的封裝 但是,在核心態沒有這樣的系統呼叫,我們又該如何讀寫檔案呢?閱讀linux核心原始碼,可以知道陷入核心執行的是實際執行的是sys read和sys write這兩個函式,但是這兩個函式沒有...

在linux核心中讀寫檔案

1.序曲 在使用者態,讀寫檔案可以通過read和write這兩個系統呼叫來完成 c庫函式實際上是對系統呼叫的封裝 但是,在核心態沒有這樣的系統呼叫,我們又該如何讀寫檔案呢?閱讀linux核心原始碼,可以知道陷入核心執行的是實際執行的是sys read和sys write這兩個函式,但是這兩個函式沒有...

在linux核心中讀寫檔案

1.序曲 在使用者態,讀寫檔案可以通過read和write這兩個系統呼叫來完成 c庫函式實際上是對系統呼叫的封裝 但是,在核心態沒有這樣的系統呼叫,我們又該如何讀寫檔案呢?閱讀linux核心原始碼,可以知道陷入核心執行的是實際執行的是sys read和sys write這兩個函式,但是這兩個函式沒有...