1、字符设备注册
在运行时获得一个独立的cdev结构的代码:
Structcdev*my_cdev=cdev_alloc();
My_codev->ops=&my_fops;
将cdev结构嵌入自己设备特定的结构:
Voidcdev_init(structcdev*cdev,structfile_operations*fops);
Cdev结构建立后,告诉内核:
Intcdev_add(structcdev*dev,dev_tnum,unsignedintcount);
在驱动完全准备好处理设备上的操作后再调用cdev_add。
为系统去除一个字符设备,调用:
Voidcdev_del(structcdev*dev);
1.1、scull中的设备注册
Scull的结构structscull_dev:
structscull_dev{
structscull_qset*data;/*Pointertofirstquantumset*/
intquantum;/*thecurrentquantumsize*/
intqset;/*thecurrentarraysize*/
unsignedlongsize;/*amountofdatastoredhere*/
unsignedintaccess_key;/*usedbysculluidandscullpriv*/
structsemaphoresem;/*mutualexclusionsemaphore*/
structcdevcdev;/*Chardevicestructure*/
};
设备与内核接口的structcdev这个结构必须初始化,并添加到系统中,scull处理这个任务的代码是:
staticvoidscull_setup_cdev(structscull_dev*dev,intindex)
{
interr,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);
/*Failgracefullyifneedbe*/
if(err)
printk(KERN_NOTICE"Error%daddingscull%d",err,index);
}
2、open和release
至此已经快速浏览了这些成员,并在以后scull的函数中使用它们。
2.1、open方法
Open应当做的工作:
●检查设备特定的错误(例如设备没准备好,或者类似的硬件错误)
●如果它第一次打开,初始化设备
●如果需要,更新f_op指针.
●分配并填充要放进filp->private_data的任何数据结构
Open的原型
Int(*open)(structinode*inode,structfile*filp);
container_of(pointer,container_type,container_field);
这个宏使用一个指向container_field类型的成员的指针,它在一个container_type类型的结构中,并
且返回一个指针指向包含结构.在scull_open,这个宏用来找到适当的设备结构:
structscull_dev*dev;/*deviceinformation*/
dev=container_of(inode->i_cdev,structscull_dev,c
filp->private_data=dev;/*forothermethods*/
2.2、release方法
应该实现的任务:
●释放open分配在filp->private_data中的任何东西
在最后的close关闭设备
3、scull的内存使用
scull驱动引入2个核心函数来管理Linux内核中的内存.这些函数,定义在<linux/slab.h>,是:
void*kmalloc(size_tsize,intflags);
voidkfree(void*ptr);
4、读和写
scull中的读写代码需要拷贝一整段数据到或者从用户地址空间.这个能力由下列内核函数提供,它
们拷贝一个任意的字节数组,并且位于大部分读写实现的核心中.
unsignedlongcopy_to_user(void__user*to,constvoid*from,unsignedlongcount);
unsignedlongcopy_from_user(void*to,constvoid__user*from,unsignedlongcount);