LDD3学习笔记(5):字符驱动3

 

1、字符设备注册

在运行时获得一个独立的cdev结构的代码:

Struct cdev* my_cdev=cdev_alloc();

My_codev->ops=&my_fops;

cdev结构嵌入自己设备特定的结构:

Void cdev_init(struct cdev* cdev , struct file_operations* fops);

Cdev结构建立后,告诉内核:

Int cdev_add(struct cdev*dev dev_t num,unsigned int count);

在驱动完全准备好处理设备上的操作后再调用cdev_add

为系统去除一个字符设备,调用:

Void cdev_del(struct cdev*dev);

1.1scull中的设备注册

Scull的结构struct scull_dev:

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 */

};

设备与内核接口的struct cdev这个结构必须初始化,并添加到系统中,scull处理这个任务的代码是:

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);

}

2、openrelease

至此已经快速浏览了这些成员,并在以后scull的函数中使用它们。

2.1open方法

Open应当做的工作:

●     检查设备特定的错误(例如设备没准备好或者类似的硬件错误)

●     如果它第一次打开初始化设备

●     如果需要更新 f_op 指针.

●     分配并填充要放进 filp->private_data 的任何数据结构

Open的原型

Int *open)(struct inode* inode, struct file*filp);

container_of(pointer, container_type, container_field); 

这个宏使用一个指向 container_field 类型的成员的指针它在一个 container_type 类型的结构中

且返回一个指针指向包含结构在 scull_open, 这个宏用来找到适当的设备结构:

struct scull_dev *dev; /* device information */ 

dev = container_of(inode->i_cdev, struct scull_dev, c

filp->private_data = dev; /* for other methods */

2.2release方法

应该实现的任务:

●     释放 open 分配在 filp->private_data 中的任何东西

在最后的 close 关闭设备

3、scull的内存使用

scull 驱动引入 个核心函数来管理 Linux 内核中的内存这些函数定义在 <linux/slab.h>, :

void *kmalloc(size_t size, int flags); 

void kfree(void *ptr);

4、读和写

scull 中的读写代码需要拷贝一整段数据到或者从用户地址空间这个能力由下列内核函数提供

们拷贝一个任意的字节数组并且位于大部分读写实现的核心中.

unsigned long copy_to_user(void __user *to,const void *from,unsigned long count); 

unsigned long copy_from_user(void *to,const void __user *from,unsigned long count); 

你可能感兴趣的:(LDD3学习笔记(5):字符驱动3)