您的位置:首页 > 理论基础 > 数据结构算法

字符设备(二)之主要数据结构

2013-01-29 10:50 344 查看
一.linux文件系统和字符设备驱动

应用程序和VFS之间的接口是系统调用,而VFS和磁盘文件系以及普通设备之间接口是file_operation结构体成员函数,这个结构包含打开,关闭,读,写等各种对文件的操作

字符设备上层不涉及到磁盘,所以字符设备的file_operation成员函数直接由设备驱动提供。file_operation是字符设备的操作核心。

1.file结构体

文件结构体代表一个文件(若是设备,则为设备文件),系统中每个打开的文件在内核中都有个一个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;//2.6新加入的锁机制
} f_u;
struct path		f_path;
#define f_dentry	f_path.dentry//目录入口
#define f_vfsmnt	f_path.mnt
const struct file_operations	*f_op;//和文件关联的操作
spinlock_t		f_lock;  /* f_ep_links, f_flags, no IRQ */
atomic_long_t		f_count;
unsigned int 		f_flags;//文件标识,O_RDONLY,O_NONBLOCK,O_SYNC
fmode_t			f_mode;//文件读写模式
loff_t			f_pos;
struct fown_struct	f_owner;
const struct cred	*f_cred;
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;
#endif /* #ifdef CONFIG_EPOLL */
struct address_space	*f_mapping;
#ifdef CONFIG_DEBUG_WRITECOUNT
unsigned long f_mnt_write_state;
#endif
};
要点:文件读写模式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");
2.inode结构体

VFS inode包含文件的各种信息,eg:大小,权限等,是linux管理文件系统的最小单位,也是文件系统连接任何子目录,文件的桥梁

struct inode {
struct hlist_node	i_hash;
struct list_head	i_list;		/* backing dev IO 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;//inode拥有者的id
gid_t			i_gid;//inode所属的群组id
dev_t			i_rdev;//若是设备文件,记录设备的设备号
u64			i_version;
loff_t			i_size;
#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的产生时间
blkcnt_t		i_blocks;//inode所使用的block数,一个block为512byte
unsigned int		i_blkbits;//inode做I/O时的区块大小
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;
union {
struct pipe_inode_info	*i_pipe;
struct block_device	*i_bdev;//块设备
struct cdev		*i_cdev;//字符设备
};

__u32			i_generation;

#ifdef CONFIG_FSNOTIFY
__u32			i_fsnotify_mask; /* all events this inode cares about */
struct hlist_head	i_fsnotify_mark_entries; /* fsnotify mark entries */
#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
#ifdef CONFIG_FS_POSIX_ACL
struct posix_acl	*i_acl;
struct posix_acl	*i_default_acl;
#endif
void			*i_private; /* fs or device private pointer */
};
二.file_operations结构体

struct file_operations {
struct module *owner;//一般为THIS_MODULE
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);//读取目录
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);
long (*compat_ioctl) (struct file *, unsigned int, unsigned long);
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);
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 **);
};
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: