字符設備驅動程序中重要的三個數據結構file_operations、inode、file


在學習字符設備驅動的開始,我們必須了解的是三個很重要的數據結構,他們分別是file_operations、inode、file。下面陶毛毛同學就和大家一起來學習這三個數據結構。

struct _file_operations在Fs.h這個文件里面被定義的,如下所示:

struct file_operations {
    struct module *owner;//擁有該結構的模塊的指針,一般為THIS_MODULES
    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 *);//向設備發送數據

    ssize_t (*aio_read) (struct kiocb *, const struct iovec *, unsigned long, loff_t);//初始化一個異步的讀取操作
    ssize_t (*aio_write) (struct kiocb *, const struct iovec *, unsigned long, loff_t);//初始化一個異步的寫入操作
    int (*readdir) (struct file *, void *, filldir_t);//僅用於讀取目錄,對於設備文件,該字段為NULL
    unsigned int (*poll) (struct file *, struct poll_table_struct *); //輪詢函數,判斷目前是否可以進行非阻塞的讀寫或寫入
    int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long); //執行設備I/O控制命令
    long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long); //不使用BLK文件系統,將使用此種函數指針代替ioctl
    long (*compat_ioctl) (struct file *, unsigned int, unsigned long); //在64位系統上,32位的ioctl調用將使用此函數指針代替
    int (*mmap) (struct file *, struct vm_area_struct *); //用於請求將設備內存映射到進程地址空間
    int (*open) (struct inode *, struct file *); //打開
    int (*flush) (struct file *, fl_owner_t id);
    int (*release) (struct inode *, struct file *); //關閉
    int (*fsync) (struct file *, struct dentry *, int datasync); //刷新待處理的數據
    int (*aio_fsync) (struct kiocb *, int datasync); //異步刷新待處理的數據
    int (*fasync) (int, struct file *, int); //通知設備FASYNC標志發生變化
    int (*lock) (struct file *, int, struct file_lock *);
    ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int);
    unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);
    int (*check_flags)(int);
    int (*flock) (struct file *, int, struct file_lock *);
    ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *, size_t, unsigned int);
    ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *, size_t, unsigned int);
    int (*setlease)(struct file *, long, struct file_lock **);
};

Linux使用file_operations結構訪問驅動程序的函數,這個結構的每一個成員的名字都對應着一個調用。用戶進程利用在對設備文件進行諸如read/write操作的時候,系統調用通過設備文件的主設備號找到相應的設備驅動程序,然后讀取這個數據結構相應的函數指針,接着把控制權交給該函數,這是Linux的設備驅動程序工作的基本原理。

下面是struct inode結構體。

struct inode {
struct hlist_node   i_hash; //哈希表
struct list_head   i_list;      //索引節點鏈表
struct list_head   i_sb_list;//目錄項鏈表
struct list_head   i_dentry;
unsigned long       i_ino;     //節點號
atomic_t       i_count;          //引用記數
unsigned int       i_nlink;    //硬鏈接數
uid_t           i_uid;                /*使用者id */
gid_t           i_gid;                 /*使用者id組*/
dev_t           i_rdev;             //該成員表示設備文件的inode結構,它包含了真正的設備編號。
u64             i_version;
loff_t           i_size;              /*inode多代表的文件的大小*/
#ifdef __NEED_I_SIZE_ORDERED
seqcount_t       i_size_seqcount;
#endif
struct timespec       i_atime;        /*inode最后一次存取的時間*/
struct timespec       i_mtime;       /*inode最后一次修改的時間*/
struct timespec       i_ctime;       /*inode的創建時間*/
unsigned int       i_blkbits;          /*inode在做I/O時的區塊大小*/
blkcnt_t       i_blocks;                 /*inode所石油的block塊數*/
unsigned short          i_bytes;
umode_t           i_mode;    /*inode的權限*/
spinlock_t       i_lock;   /* i_blocks, i_bytes, maybe i_size */
struct mutex       i_mutex;
struct rw_semaphore   i_alloc_sem;
const struct inode_operations   *i_op;
const struct file_operations   *i_fop;   /* former ->i_op->default_file_ops */
struct super_block   *i_sb;
struct file_lock   *i_flock;
struct address_space   *i_mapping;
struct address_space   i_data;
#ifdef CONFIG_QUOTA
struct dquot       *i_dquot[MAXQUOTAS];
#endif
struct list_head   i_devices;    /*若是字符設備,為其對應的cdev結構體指針*/
union {
struct pipe_inode_info   *i_pipe;
struct block_device   *i_bdev;     /*若是塊設備,為其對應的cdev結構體指針*/
struct cdev       *i_cdev; //該成員表示字符設備的內核的 內部結構。當inode指向一個字符設備文件時,該成員包含了指向struct cdev結構的指針,其中cdev結構是字符設備結構體。
};
int           i_cindex;
__u32           i_generation;
#ifdef CONFIG_DNOTIFY
unsigned long       i_dnotify_mask; /* Directory notify events */
struct dnotify_struct   *i_dnotify; /* for directory notifications */
#endif
#ifdef CONFIG_INOTIFY
struct list_head   inotify_watches; /* watches on this inode */
struct mutex       inotify_mutex;   /* protects the watches list */
#endif
unsigned long       i_state;
unsigned long       dirtied_when;   /* jiffies of first dirtying */
unsigned int       i_flags;
atomic_t       i_writecount;
#ifdef CONFIG_SECURITY
void           *i_security;
#endif
void           *i_private; /* fs or device private pointer */
};

內核中用inode結構表示具體的文件,也就是對應與硬盤上面具體的文件。提供了設備文件的信息。inode譯成中文就是索引節點。每個存儲設備或存儲設備的分區(存儲設備是硬盤、軟盤、U盤 ... ... )被格式化為文件系統后,應該有兩部份,一部份是inode,另一部份是Block,Block是用來存儲數據用的。而inode呢,就是用來存儲這些數據的信息,這些信息包括文件大小、屬主、歸屬的用戶組、讀寫權限等。inode為每個文件進行信息索引,所以就有了inode的數值。操作系統根據指令,能通過inode值最快的找到相對應的文件。

最后是struct file。

struct file {
/*
* fu_list becomes invalid after file_free is called and queued via
* fu_rcuhead for RCU freeing
*/
union {
struct list_head    fu_list;
struct rcu_head     fu_rcuhead;
} f_u;
struct path        f_path;
#define f_dentry    f_path.dentry   //該成員是對應的 目錄結構 。
#define f_vfsmnt    f_path.mnt
const struct file_operations    *f_op; //該操作 是定義文件關聯的操作的。內核在執行open時對這個指針賦值。
atomic_long_t        f_count;//文件的引用計數(有多少進程打開該文件)
unsigned int           f_flags; //該成員是文件標志。
mode_t            f_mode;//讀寫模式:open的mod_t mode參數
loff_t               f_pos;//該文件在當前進程中的文件偏移量
struct fown_struct    f_owner;//該結構的作用是通過信號進行I/O時間通知的數據
unsigned int              f_uid, f_gid;//文件所有者id,所有者組id
struct file_ra_state  f_ra;

u64            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 */
struct address_space    *f_mapping;
#ifdef CONFIG_DEBUG_WRITECOUNT
unsigned long f_mnt_write_state;
#endif
};

文件結構代表一個打開的文件描述符,它不是專門給驅動程序使用的,系統中每一個打開的文件在內核中都有一個關聯的struct file。它由內核在open時創建,並傳遞給在文件上操作的任何函數,知道最后關閉。當文件的所有實例都關閉之后,內核釋放這個數據結構。

最后:總結一下,struct operations存在於設備驅動程序內部,起着聯系應用程序和設備驅動的作用。struct inode存在於磁盤上,作為描述設備驅動文件的信息的作用。struct file是在執行open函數時產生的,每打開一個文件就產生一個struct file,供設備驅動關聯的函數使用。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM