前言
這是我在網上看到的關於文件操作的文章的一個整理和集合,這是第一版。
主要參考:
http://sharep.blog.51cto.com/539048/114299
http://blog.chinaunix.net/u2/73528/showart_1086375.html
http://hi.baidu.com/hp_roc/blog/item/f1db16085e618035b0351d45.html
http://www.diybl.com/course/3_program/c/c_js/20091014/178731.html
其原文或有重復,或不妥當之處,均按我的理解在文中做了修改。
第一部分 文件的結構
一,文件的定義
struct file結構體定義在/linux/include/linux/fs.h(Linux 2.6.11內核)中,其原型是:
721struct file {
722 /*
723 * fu_list becomes invalid after file_free is called and queued via
724 * fu_rcuhead for RCU freeing
725 */
726 union {
727 struct list_head fu_list;
728 struct rcu_head fu_rcuhead;
729 } f_u;
730 struct path f_path;
731#define f_dentry f_path.dentry
732#define f_vfsmnt f_path.mnt
733 const struct file_operations *f_op;
734 atomic_t f_count;
735 unsigned int f_flags;
736 mode_t f_mode;
737 loff_t f_pos;
738 struct fown_struct f_owner;
739 unsigned int f_uid, f_gid;
740 struct file_ra_state f_ra;
741
742 unsigned long f_version;
743#ifdef CONFIG_SECURITY
744 void *f_security;
745#endif
746 /* needed for tty driver, and maybe others */
747 void *private_data;
748
749#ifdef CONFIG_EPOLL
750 /* Used by fs/eventpoll.c to link all the hooks to this file */
751 struct list_head f_ep_links;
752 spinlock_t f_ep_lock;
753#endif /* #ifdef CONFIG_EPOLL */
754 struct address_space *f_mapping;
755};
二、作用:
文件結構體代表一個打開的文件,系統中每個打開的文件在內核空間都有一個關聯的
struct file。它由內核在打開文件時創建,並傳遞給在文件上進行操作的任何函數。在文件的所有實例都關閉後,內核釋放這個數據結構。在內核創建和驅動源碼中,
struct file的指針通常被命名為
file或
filp。
三、各個字段詳解:
1、
union { struct list_head fu_list; struct rcu_head rcuhead;}f_u;其中的
struct list_head定義在
linux/include/linux/list.h中,原型為:
21struct list_head { 22 struct list_head *next, *prev;
23};
list_head是內核中最常用的建立雙向循環鏈表的結構,在此用於通用文件對象鏈表的指針。
struct rcu_head定義在
linux/include/linux/rcupdate.h中,其原型為:
50struct rcu_head { 51 struct rcu_head *next;
52 void (*func)(struct rcu_head *head);
53};
RCU(Read-Copy Update)是
Linux 2.6內核中新的鎖機制,具體參考:
http://www.ibm.com/developerworks/cn/linux/l-rcu/
在此用於更新文件。
fu_list在
file_free()函數被調用以後就無效了,隊列通過
rcu_head來釋放
RCU。
2、struct path f_path;被定義在
linux/include/linux/namei.h中,其原型為:
32struct path { 33 struct vfsmount *mnt;
34 struct dentry *dentry;
35};
在早些版本的內核中並沒有此結構,而是直接將
path的兩個數據成員作為
struct file的數據成員,
struct vfsmount *mnt的作用是指出該文件的已安裝文件系統,
struct dentry *dentry是與文件相關的目錄項對象。
3、
const struct file_operations *f_op;被定義在
linux/include/linux/fs.h中,其中包含著與文件關聯的操作,如
:loff_t (*llseek) (struct file *, loff_t, int);ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);等。當打開一個文件時,內核就創建一個與該文件相關聯的
struct file結構,其中的
*f_op就指向的是具體對該文件進行操作的函數。例如用戶調用系統調用
read來讀取該文件的內容時,那麼系統調用
read最終會陷入內核調用
sys_read函數,而
sys_read最終會調用與該文件關聯的
struct file結構中的
f_op->read函數對文件內容進行讀取。
4、
atomic_t f_count;atomic_t被定義為:
typedef struct { volatile int counter; } atomic_t;volatile修飾字段告訴
gcc不要對該類型的數據做優化處理,對它的訪問都是對內存的訪問,而不是對寄存器的訪問。本質是
int類型,之所以這樣寫是讓編譯器對基於該類型變量的操作進行嚴格的類型檢查。此處
f_count的作用是記錄對文件對象的引用計數,也即當前有多少個使用
CLONE_FILES標志克隆的進程在使用該文件。典型的應用是在
POSIX線程中。就像在內核中普通的引用計數模塊一樣,最後一個進程調用
put_files_struct()來釋放文件描述符。
5、
unsigned int f_flags;當打開文件時指定的標志,對應系統調用
open的
int flags參數。驅動程序為了支持非阻塞型操作需要檢查這個標志。
六、
mode_t f_mode;對文件的讀寫模式,對應系統調用
open的
mod_t mode參數。如果驅動程序需要這個值,可以直接讀取這個字段。
mod_t被定義為:
typedef unsigned int __kernel_mode_t;typedef __kernel_mode_t mode_t;7、
loff_t f_pos;當前的文件指針位置,即文件的讀寫位置。
loff_t被定義為:
typedef long long __kernel_loff_t;typedef __kernel_loff_t loff_t;8、
struct fown_struct f_owner;struct fown_struct在
linux/include/linux/fs.h被定義,原型為
:
688struct fown_struct {
689 rwlock_t lock; /* protects pid, uid, euid fields */
690 struct pid *pid; /* pid or -pgrp where SIGIO should be sent */
691 enum pid_type pid_type;/*Kind of process group SIGIO should be sent to*/
692 uid_t uid, euid; /* uid/euid of process setting the owner */
693 int signum; /* posix.1b rt signal to be delivered on IO */
694};
該結構的作用是通過信號進行
I/O時間通知的數據。
9、
unsigned int f_uid, f_gid;標識文件的所有者
id,所有者所在組的
id.10、
struct file_ra_state f_ra;struct file_ra_state結構被定義在
/linux/include/linux/fs.h中,原型為:
699struct file_ra_state{ 700 pgoff_t start; /* where readahead started */
701 unsigned long size; /* # of readahead pages */
702 unsigned long async_size; /* do asynchronous readahead when
703 there are only # of pages ahead */
704
705 unsigned long ra_pages; /* Maximum readahead window */
706 unsigned long mmap_hit; /* Cache hit stat for mmap accesses */
707 unsigned long mmap_miss; /* Cache miss stat for mmap accesses */
708 unsigned long prev_index; /* Cache last read() position */
709 unsigned int prev_offset; /* Offset where last read() ended in a page */
710};
文件預讀狀態,文件預讀算法使用的主要數據結構,當打開一個文件時,
f_ra中除了
perv_page(默認為-
1)和
ra_apges(對該文件允許的最大預讀量
)這兩個字段外,其他的所有字端都置為
0。
11、
unsigned long f_version;記錄文件的版本號,每次使用後都自動遞增。
12、
#ifdef CONFIG_SECURITYvoid *f_security;#endif此處我的理解是如果在編譯內核時配置了安全措施,那麼
struct file結構中就會有
void *f_security數據項,用來描述安全措施或者是記錄與安全有關的信息。
13、
void *private_data;系統在調用驅動程序的
open方法前將這個指針置為
NULL。驅動程序可以將這個字段用於任意目的,也可以忽略這個字段。驅動程序可以用這個字段指向已分配的數據,但是一定要在內核釋放
file結構前的
release方法中清除它。
14、
#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 */被用在
fs/eventpoll.c來鏈接所有鉤到這個文件上。其中
f_ep_links是文件的事件輪詢等待者鏈表的頭,
f_ep_lock是保護
f_ep_links鏈表的自旋鎖。
15、
struct address_space *f_mapping;struct address_space被定義在
/linux/include/linux/fs.h中,此處是指向文件地址空間的指針。
四、應用:
在驅動開發中,文件讀
/寫模式
mode、標志
f_flags都是設備驅動關心的內容,而私有數據指針
private_data在驅動中被廣泛使用,大多被指向設備驅動自定義的用於描述設備的結構體。驅動程序中常用如下類似的代碼來檢測用戶打開文件的讀寫方式:
if (file->f_mode & FMODE_WRITE) //用戶要求可寫
{ } if (file->f_mode & FMODE_READ) //用戶要求可讀
{ } 下面的代碼可用於判斷以阻塞還是非阻塞方式打開設備文件:
if (file->f_flags & O_NONBLOCK) //非阻塞
pr_debug("open:non-blocking\n"); else //阻塞
pr_debug("open:blocking\n");本文出自 “技術成長,不斷進步!” 博客,請務必保留此出處http://norawoo.blog.51cto.com/751155/287654