乙個程序中各主要的檔案相關結構
的關係圖:
下圖為多個程序開啟同一檔案的情況:
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這兩個函式,但是這兩個函式沒有...