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

第三章 三个数据结构以及字符设备的注册

2011-07-30 16:25 183 查看
上一篇讲到了注册设备编号,显然,注册设备编号只是编写驱动代码的第一个步骤。为了完成以后的一些步骤,先介绍三个重要的内核数据结构。

file_operation囊括了所有设备操作到设备号的链接。在linux中驱动以文件的方式存在,而file_operation则是对文件(这里是是字符设备)的所有操作的集合。由于file_operation的成员太多,而当前scull项目仅仅用到了其中的几个。 scull项目的file_operation初始化如下:

struct file_operations scull_fops = {
.owner = THIS_MODULE,
.llseek = scull_llseek,
.read = scull_read,
.write = scull_write,
.ioctl = scull_ioctl,
.open = scull_open,
.release = scull_release,
};


  owner指向拥有这个结构的模块,几乎所有情况下,它的值都是THIS_MODULE,这是一个定义在<linux/module.h>中的宏;llseek 方法用作改变文件中的当前读/写位置, 并且新位置作为(正的)返回值;read用来从设备中获取数据;write用来发送数据给设备;.ioctl 用来发出设备特定命令(非read或write);open为打开设备文件,显然这应该是对设备文件进行的第一个操作;.release 释放文件结构。

file数据结构代表一个打开的文件(记住设备被当做了文件)。如同file_operation指定了操作的集合,file就是这些操作的目标对象了。

inode数据结构也表示文件,不过他跟file数据结构不同(估计这个区别以后才能了解)。对于编写驱动来说,这个数据结构就两个字段有用。dev_t i_rdev代表设备编号,struct cdev *i_cdev;代表一个字符设备。详细的信息到使用的时候再深入研究。

要说明的是,linux源代码在初始化这些数据结构的时候一般都是用c语言的标记式结构初始化语法。

linux内核在内部使用类型struct cdev来代表字符设备。而在scull中,使用一个自定义的struct scull_dev类型的

结构来表示每个设备,这个结构包括了一个struct cdev结构:

struct scull_dev {
struct scull_qset *data; /* Pointer to first quantum set */
int quantum; /* the current quantum size */
int qset; /* the current array size */
unsigned long size; /* amount of data stored here */
unsigned int access_key; /* used by sculluid and scullpriv */
struct semaphore sem; /* mutual exclusion semaphore */
struct cdev cdev; /* Char device structure */
};


  初始化这一结构并注册的函数如下:

static void scull_setup_cdev(struct scull_dev *dev, int index)
{
int err, devno = MKDEV(scull_major, scull_minor + index);
cdev_init(&dev->cdev, &scull_fops);
dev->cdev.owner = THIS_MODULE;
dev->cdev.ops = &scull_fops;
err = cdev_add (&dev->cdev, devno, 1);
/* Fail gracefully if need be */
if (err)
printk(KERN_NOTICE "Error %d adding scull%d", err, index);
}


  这样就完成了一个字符设备的初始化和注册。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: