Linux设备驱动程序 之 重要数据结构
文件对象
文件对象是进程已经打开文件描述符的内存中的表示,单个文件可能有多个表示打开文件描述符的file结构;
struct file {
union {
struct llist_node fu_llist; /* 文件对象链表 */
struct rcu_head fu_rcuhead; /* 释放之后的RCU链表 */
} f_u;
/* 目录项 */
struct path f_path;
/* inode */
struct inode *f_inode; /* cached value */
/* 文件操作 */
const struct file_operations *f_op;
/*
* Protects f_ep_links, f_flags.
* Must not be taken from IRQ context.
*/
/* 锁 */
spinlock_t f_lock;
/* 引用计数 */
atomic_long_t f_count;
/* 打开文件时所指定的标志 */
unsigned int f_flags;
/* 文件访问模式 */
fmode_t f_mode;
struct mutex f_pos_lock;
/* 文件当前偏移量 */
loff_t f_pos;
/* 拥有者通过信号进行异步IO数据传送 */
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 */
/* tty设备驱动的钩子 */
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;
struct list_head f_tfile_llink;
#endif /* #ifdef CONFIG_EPOLL */
/* 页缓存映射 */
struct address_space *f_mapping;
} __attribute__((aligned())); /* lest something weird decides that 2 is OK */
文件操作
file_operations提供了文件操作函数,这些函数与系统调用进行关联;
/* 文件操作 */
struct file_operations {
/* 拥有该模块的指针,通常被初始化为THIS_MODULE */
struct module *owner;
/*
用来修改文件的当前读写位置,并将新位置作为返回值,由系统调用lseek调用
参数2是一个"长偏移量";
参数3是SEEK_SET,SEEK_CUR,SEEK_END中的一个:
SEEK_SET-参数2设置为新的读写位置
SEEK_CUR-当前读写位置后增加参数2个偏移量
SEEK_END-读写位置指向文件尾后再增加参数2个偏移量
*/
loff_t (*llseek) (struct file *, loff_t, int);
/*
从给定文件的offset偏移出读取count字节数据到buf中,
同时更新文件指针,由系统调用read调用
*/
ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
/*
从给定buf中读取count字节数据,写入给定文件offset偏移处,
同时更新文件指针,由系统调用write调用
*/
ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
/* 同步异步读写 */
ssize_t (*read_iter) (struct kiocb *, struct iov_iter *);
ssize_t (*write_iter) (struct kiocb *, struct iov_iter *); int (*iterate) (struct file *, struct dir_context *);
int (*iterate_shared) (struct file *, struct dir_context *);
/* 睡眠等待给定文件活动,由系统调用poll调用 */
unsigned int (*poll) (struct file *, struct poll_table_struct *);
/*
用来给设备发送名称参数对,当文件是一个被打开的设备节点时,
可以通过它进行设置,由系统调用iotcl调用
*/
long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);
/*
是ioctl函数的可移植变种,被32位应用程序用在64位系统上,
新的驱动程序应该设计自己的ioctl命令,以便所有的驱动程序都是可移植的,
从而使得compat_ioctl和unlocked_ioctl指向同一个函数
*/
long (*compat_ioctl) (struct file *, unsigned int, unsigned long);
/* 将给定的文件映射到指定地址空间行,由系统调用mmap调用 */
int (*mmap) (struct file *, struct vm_area_struct *);
/* 创建一个新的文件对象,并将它和响应的索引节点对象关联起来,由系统调用open调用 */
int (*open) (struct inode *, struct file *);
/* 当已打开文件的引用计数减少时,该函数被VFS调用,它的作用根据具体文件系统而定 */
int (*flush) (struct file *, fl_owner_t id);
/*
当文件最后一个引用被注销时(如当最后一个共享文件描述符进程调用了close()或者退出),
该函数被VFS调用,它的作用根据具体文件系统而定 */
int (*release) (struct inode *, struct file *);
/* 将给定文件的所有被缓存数据写回磁盘,由系统调用fsync调用 */
int (*fsync) (struct file *, loff_t, loff_t, int datasync);
/* 打开或者关闭异步IO的通告信号 */
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);
/* 允许模块检查传递给fcntl(F_SETFL...)调用的标志 */
int (*check_flags)(int);
/* 实现flock()系统调用,该调用提供忠告锁 */
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 **, void **);
long (*fallocate)(struct file *file, int mode, loff_t offset,
loff_t len);
void (*show_fdinfo)(struct seq_file *m, struct file *f);
#ifndef CONFIG_MMU
unsigned (*mmap_capabilities)(struct file *);
#endif
ssize_t (*copy_file_range)(struct file *, loff_t, struct file *,
loff_t, size_t, unsigned int);
int (*clone_file_range)(struct file *, loff_t, struct file *, loff_t,
u64);
ssize_t (*dedupe_file_range)(struct file *, u64, u64, struct file *,
u64);
};
inode对象
内核用inode结构在内部表示文件,因此它和file结构不同,后者表示打开的文件描述符。对单个文件,可能会有多个表示打开文件描述符的file结构,但它们都指向单个inode结构;
inode结构中包含了大量有关文件的信息。作为常规,只有下面两个字段对编写驱动程序代码有用
dev_t i_rdev:
对表示设备文件的inode结构,该字段包含了真正的设备编号;
struct cdev *i_cdev:
表示字符设备的内核的内部结构,当inode指向一个字符设备文件时,该字段包含了指向struct cdev结构的指针;
从inode中获取主设备号和次设备号,使用下面函数,不要直接操作i_rdev:
static inline unsigned iminor(const struct inode *inode)
{
return MINOR(inode->i_rdev);
} static inline unsigned imajor(const struct inode *inode)
{
return MAJOR(inode->i_rdev);
}
Linux设备驱动程序 之 重要数据结构的更多相关文章
- linux设备驱动程序该添加哪些头文件以及驱动常用头文件介绍(转)
原文链接:http://blog.chinaunix.net/uid-22609852-id-3506475.html 驱动常用头文件介绍 #include <linux/***.h> 是 ...
- 【转】linux设备驱动程序之简单字符设备驱动
原文网址:http://www.cnblogs.com/geneil/archive/2011/12/03/2272869.html 一.linux系统将设备分为3类:字符设备.块设备.网络设备.使用 ...
- 【转】linux设备驱动程序中的阻塞机制
原文网址:http://www.cnblogs.com/geneil/archive/2011/12/04/2275272.html 阻塞与非阻塞是设备访问的两种方式.在写阻塞与非阻塞的驱动程序时,经 ...
- Linux设备驱动程序学习----2.内核模块与应用程序的对比
内核模块与应用程序的对比 更多内容请参考Linux设备驱动程序学习----目录 1. 内核模块与应用程序的对比 内核模块和应用程序之间的不同之处: 大多数中小规模的应用程序是从头到尾执行单个任务,而模 ...
- Linux设备驱动程序学习----3.模块的编译和装载
模块的编译和装载 更多内容请参考Linux设备驱动程序学习----目录 1. 设置测试系统 第1步,要先从kernel.org的镜像网站上获取一个主线内核,并安装到自己的系统中,因为学习驱动程序的编写 ...
- Linux设备驱动程序 第三版 读书笔记(一)
Linux设备驱动程序 第三版 读书笔记(一) Bob Zhang 2017.08.25 编写基本的Hello World模块 #include <linux/init.h> #inclu ...
- Linux设备驱动程序学习之分配内存
内核为设备驱动提供了一个统一的内存管理接口,所以模块无需涉及分段和分页等问题. 我已经在第一个scull模块中使用了 kmalloc 和 kfree 来分配和释放内存空间. kmalloc 函数内幕 ...
- 教你写Linux设备驱动程序:一个简短的教程
教你写Linux设备驱动程序:一个简短的教程 http://blog.chinaunix.net/uid-20799298-id-99675.html
- linux设备驱动程序_hello word 模块编译各种问题集锦
在看楼经典书籍<linux设备驱动程序>后,第一个程序就是编写一个hello word 模块. 原以为非常easy,真正弄起来,发现问题不少啊.前两天编过一次,因为没有记录,今天看的时候又 ...
随机推荐
- vue统一注册组件
文件夹下面组件数量较多,如果每一个组件先import然后在 components,虽然灭有问题,但是会导致代码量大,而且不直观 解决办法: 将图元组件进行统一注册 新建一个pixels文件,文件里面的 ...
- android程序复制数据库
一般项目中我们把db文件放到assert或者raw目录下面,在程序第一次启动的时候复制到私有目录下面 在使用过程中,老是发现复制不成功,私有目录下的db文件总是3072 后来发现应该是使用Conten ...
- 5.1 Request 获取请求数据的几种方法
//获取请求头和请求数据 //请求数据(1.通过超链接 2.通过表单) //获取请求数据的时候一般来说 都要先检查 再使用 public class RequestDemo2 extends Http ...
- Spring cloud实战——服务提供者
目录讲解: 一.服务提供者与服务消费者的概念 二.编写一个服务提供者的测试类(code) 1.1. 使用微服务构建的是分布式系统,微服务之间通过网络进行通信.我们使用微服务提供者与服务消费者来描述微服 ...
- Spring Cloud(O)服务的注册与发现(Eureka)
一.微服务架构 1.1什么是分布式 不同模块部署在不同服务器上 作用:分布式解决网站高并发带来问题 1.2什么是集群 多台服务器部署相同应用构成一个集群 作用:通过负载均衡设备共同对外提供服务 1.3 ...
- 移动端设备管理平台 atx server2实践
目录 1.需求背景 2.初步调研 2.1.云测试平台 2.2.开源工具 2.3.VNC 2.4.企业内部自研云测试平台 3.ATX Server安装 依赖环境 安装rethinkdb 安装atx se ...
- Computer Vision_2_Active Shape Models:Active Shape Models-Their Training and Application——1995
此为计算机视觉部分,主要侧重在底层特征提取,视频分析,跟踪,目标检测和识别方面等方面. 1. Active Appearance Models 活动表观模型和活动轮廓模型基本思想来源 Snake,现在 ...
- linux下搭建redis内网端口映射工具-rinetd
最近在工作中使用到了redis缓存,用来提某些业务场景的计算速度和某些情况下的操作频率限制,客户端工具使用了redisDesktopmanager来管理,在本机操作测试的时候,是没有问题的.但是将系统 ...
- java线程基础巩固---如何实现一个自己的显式锁Lock
拋出synchronized问题: 对于一个方法上了同锁如果被一个线程占有了,而假如该线程长时间工作,那其它线程不就只能傻傻的等着,而且是无限的等这线程工作完成了才能执行自己的任务,这里来演示一下这种 ...
- 基于递归的BFS(Level-order)
上篇中学习了二叉树的DFS深度优先搜索算法,这次学习另外一种二叉树的搜索算法:BFS,下面看一下它的概念: 有些抽象是不?下面看下整个的遍历过程的动画演示就晓得是咋回事啦: 了解其概念之后,下面看下如 ...