字符设备驱动相关函数及数据结构简介.docx
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
1.设备号
分为主次设备号,看上去像是两个号码,但在内核中用dev_t(vlinux/types.h>)—种结构表示,同时不应该口
己玄假设赋值设备号,而是使用宏(vlinux/kdev_t.h>)来取得.
MAJOR(dev_t dev);
MINOR(dev_t dev);
即使你冇确定的主,次设备号也要用
dev=MKDEV(int major, int minor);
1.1分配设备号
静态分配
int register_chrdev_region(dev_t first, unsigned int count, char Fame);
first是你耍分配的起始设备编号.first的次编号部分常常是0,但是没冇耍求是那个效果.
count是你请求的连续设备编号的总数.注意,如果count太人,你要求的范围可能溢出到下一个次编号;
但是只要你要求的编号范围可用,一切都仍然会正确工作.
name是应当连接到这个编号范圉的设备的名了;它会出现在/proc/devices和sysfs +
动态分配
int alloc_chrdev_region(dev_t *dev, unsigned int firstminor, unsigned int count, char *name);
dev是一个只输出的参数,它在函数成功完成时持有你的分配范围的第一个数.
fisetminor应当是请求的第一个要用的次编号;它常常是0.
count 和name 参数如同给request_chrdev_region 的一样
>>>应该始终使用动态分配,但最好为定制设备号留冇接口,以参数形式,以name_major=0做为默认值,可能
的操作如下:
i f (scull_major) {
dev = MKDEV(scul1 major, scul1 minor);
result = register_chrdev_region(dev, scull_nr_devs, "scull");
} else {
result = alloc chrdcv region(&dcv, scull minor, scull nr devs, "scull"); scull_major =
MAJOR(dev);
}
if (result < 0) {
printk(KERNJVARNING "scull: can* t get major %d\n", scull_major):
return result;
}
1.2释放设备号
void unregister_chrdev_region(dev_t first, unsigned int count);
2 •重耍的数据结构
2.1文件操作
<linux/fs.h>中的file_operation 结构,其成员
struct module *owner
第一个file_operations成员根本不是一个操作;几乎所有时间中,它被简单初始化为THIS_MODULE,
一个在<linux/module.h>中定义的宏.
loff_t (*llseek) (struct file *, loff_t, int);
llseek方法用作改变文件中的当前读/写位置,并且新位置作为(正的)返回值.Ioff_t参数是一个“long offsef,并R就算在32位平台上也至少64位宽.错误由一个负返回值指示.如果这个函数指针是NULL, seek调用会以潜在地无法预知的方式修改file结构中的位置计数器
ssize_t (*read) (struct file *, char _user *, size_t, loff_t *);
用来从设备中获取数据.在这个位置的一个空指针导致read系统调用以-EINVALC'Invalid argument") 失败.一个非负返回值代表了成功读取的字节数(返回值是一个••signed size”类型,常常是目标平台本地
的整数类型).
ssize_t (*aio_read)(struct kiocb *, char _user *, size_t, loff_t);
初始化一个异步读-可能在函数返回前不结束的读操作.如果这个方法是NULL,所有的操作会由read
代替进行(同步地).
ssize_t (*write) (struct file *, const char _user *, size_t, loff_t *);
发送数据给设备.如果NULL, -EINVAL返回给调用write系统调用的程序.如果非负,返回值代衣成功
写的字节数.
ssize_t (*aio_write)(struct kiocb *, const char _user *, size_t, loff_t *);
初始化设备上的一个异步写.
int (*readdir) (struct file *, void *, filldir_t);
对于设备文件这个成员应当为NULL;它用來读取目录,并fU乂对文件系统冇用.
unsigned int (*poll) (struct file *, struct poll_table_struct *);
poll方法是3个系统调用的后端:poll, epoll,和select,都用作查询对一个或多个文件描述符的读或写是否会阻塞.poll方法应当返回一个位掩码指示是否非阻塞的读或写是可能的,并且,可能地,提供给内核信息用來使调用进程睡眠直到I/O变为可能•如果一个驱动的poll方法为NULL,设备假定为不阻塞地可
读可写.
int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long);