在设备驱动程序中,一般需要关心两个结构体:file 和 inode。
1. file 结构体
file 结构体代表一个打开的文件,系统中每个打开的文件在内核空间都有一个关联的 struct file。
它由内核在打开文件时创建,并传递给在文件上进行操作的任何函数。在文件的所有实例都关闭后,内核释放这个数据结构。
注:在内核和驱动源代码中,struct file 的指针通常被命名为 file 或 filp(即 file pointer)。structfile{
union{
structllist_nodefu_llist;
structrcu_headfu_rcuhead;
}
f_u;
structpathf_path;
structinode*f_inode;/*cachedvalue*/
conststructfile_operations*f_op;/*和文件关联的操作*/
/*
*Protectsf_ep_links,f_flags.
*MustnotbetakenfromIRQcontext.
*/
spinlock_tf_lock;
enumrw_hintf_write_hint;
atomic_long_tf_count;
unsignedintf_flags;/*文件标志,如O_RDONLY、O_NONBLOCK、O_SYNC*/
fmode_tf_mode;/*文件读/写模式,FMODE_READ、FMODE_WRITE*/
structmutexf_pos_lock;
loff_tf_pos;/*当前读写位置*/
structfown_structf_owner;
conststructcred*f_cred;
structfile_ra_statef_ra;
u64f_version;
#ifdefCONFIG_SECURITY
void*f_security;
#endif
/*neededforttydriver,andmaybeothers*/
void*private_data;/*文件私有数据*/
#ifdefCONFIG_EPOLL
/*Usedbyfs/eventpoll.ctolinkallthehookstothisfile*/
structlist_headf_ep_links;
structlist_headf_tfile_llink;
#endif/*#ifdefCONFIG_EPOLL*/
structaddress_space*f_mapping;
errseq_tf_wb_err;
}
__randomize_layout
__attribute__((aligned(4)));/*lestsomethingweirddecidesthat2isOK*/
structfile_handle{
__u32handle_bytes;
inthandle_type;
/*fileidentifier*/
unsignedcharf_handle[0];
};
文件读/写模式 mode、标志 f_flags 都是设备驱动关心的内容,而私有数据指针 private_data 在设备驱动中被广泛应用,大多被指向设备驱动自定义以用于描述设备的结构体。
2. inode 结构体
VFS inode 包含文件访问权限、属主、组、大小、生成时间、访问时间、最后修改事件等信息。它是 Linux 管理文件系统的基本单位,也是文件系统连接任何子目录、文件的桥梁,inode 结构体的定义如下:struct inode {
umode_t i_mode; /* inode的权限 */
unsignedshort i_opflags;
kuid_t i_uid; /* inode拥有者的id */
kgid_t i_gid; /* inode所属的群组id */
unsignedint i_flags;
#ifdef CONFIG_FS_POSIX_ACL
struct posix_acl *i_acl;
struct posix_acl *i_default_acl;
#endif
conststruct inode_operations *i_op;
struct super_block *i_sb;
struct address_space *i_mapping;
#ifdef CONFIG_SECURITY
void *i_security;
#endif
/* Stat data, not accessed from path walking */
unsignedlong i_ino;
/*
* Filesystems may only read i_nlink directly.They shall use the
* following functions for modification:
*
* (set|clear|inc|drop)_nlink
* inode_(inc|dec)_link_count
*/
union{
constunsignedinti_nlink;
unsignedint__i_nlink;
};
dev_t i_rdev; /* 若是设备文件,此字段将记录设备的设备号 */
loff_t i_size; /* inode所代表的文件大小 */
struct timespec i_atime; /* inode最近一次的存取时间 */
struct timespec i_mtime; /* inode最近一次的修改时间 */
struct timespec i_ctime; /* inode的产生时间 */
spinlock_t i_lock; /* i_blocks, i_bytes, maybe i_size */
unsignedshort i_bytes;
unsignedint i_blkbits;
enumrw_hint i_write_hint;
blkcnt_t i_blocks; /* inode所使用的block数,一个block为512字节 */
#ifdef __NEED_I_SIZE_ORDERED
seqcount_t i_size_seqcount;
#endif
/* Misc */
unsignedlong i_state;
struct rw_semaphore i_rwsem;
unsignedlong dirtied_when; /* jiffies of first dirtying */
unsignedlong dirtied_time_when;
struct hlist_node i_hash;
struct list_head i_io_list; /* backing dev IO list */
#ifdef CONFIG_CGROUP_WRITEBACK
struct bdi_writeback *i_wb; /* the associated cgroup wb */
/* foreign inode detection, see wbc_detach_inode() */
int i_wb_frn_winner;
u16 i_wb_frn_avg_time;
u16 i_wb_frn_history;
#endif
struct list_head i_lru; /* inode LRU list */
struct list_head i_sb_list;
struct list_head i_wb_list; /* backing dev writeback list */
union{
struct hlist_head i_dentry;
struct rcu_head i_rcu;
};
u64 i_version;
atomic_t i_count;
atomic_t i_dio_count;
atomic_t i_writecount;
#ifdef CONFIG_IMA
atomic_t i_readcount;/* struct files open RO */
#endif
conststruct file_operations *i_fop; /* former ->i_op->default_file_ops */
struct file_lock_context *i_flctx;
struct address_space i_data;
struct list_head i_devices;
union{
struct pipe_inode_info *i_pipe;
struct block_device *i_bdev; /* 若是块设备,为其对应的block_device结构体指针 */
struct cdev *i_cdev;/* 若是字符设备,为其对应的cdev结构体指针 */
char *i_link;
unsigned i_dir_seq;
};
__u32 i_generation;
#ifdef CONFIG_FSNOTIFY
__u32 i_fsnotify_mask;/* all events this inode cares about */
struct fsnotify_mark_connector __rcu *i_fsnotify_marks;
#endif
#if IS_ENABLED(CONFIG_FS_ENCRYPTION)
struct fscrypt_info *i_crypt_info;
#endif
void *i_private;/* fs or device private pointer */
} __randomize_layout;