scull字符设备源代码完全解析
基础篇
⾸先是模块装载到内核时调⽤的初始化部分:int scull_init_module(void);
⾸先对于字符设备的访问时通过/dev下的设备名称进⾏的,在Linux操作系统的/dev下利⽤ls -l命令可以查看⽂件的详细信息,开头字母为c的即为字符设备⽂件,在⽇期前的两个数字就是相应设备的主设备号和次设备号。在本函数中如果scull_major不为0,则利⽤MKDEV(scull_major, scull_minor)函数获得设备号的dev_t类型,利⽤register_chrdev_region(dev, scull_nr_devs, "scull")函数分配设备编号,参数scull_nr_devs为申请设备编号的个数。如果scull_major为0,则利⽤
alloc_chrdev_region(&dev, scull_minor, scull_nr_devs,
"scull")函数动态分配设备编号,利⽤MAJOR宏获得主设备编号。接下来632-635⾏是动态分配设备号失败情况的处理。
在讲解下⾯的函数之前要了解⼀些驱动程序中重要的数据结构:
主要是file_operations结构,⾥⾯主要存放⼀些设备⽅法的函数指针。
file结构,系统为每个打开的⽂件在内核中对应⼀个file结构,其中⼀个重要的成员就是⼀个file_operation结构的指针。
inode结构,需要注意的是对于单个⽂件也许有多个file结构,但只会有⼀个inode结构。
在scull中,利⽤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  */
};
好了,接着回到代码
程序的641⾏scull_devices = kmalloc(scull_nr_devs * sizeof(struct scull_dev), GFP_KERNEL)就是为了设备申请空间,⼤⼩为设备编号数⽬和表⽰每个设备的scull_dev结构⼤⼩。642⾏到644⾏是申请失败时的处理。下⾯memset(scull_devices, 0, scull_nr_devs * sizeof(struct scull_dev))函数来清空申请的内存。
接下来的初始化可以帮助我们理解scull内存使⽤的结构
for (i = 0; i < scull_nr_devs; i++) {
scull_devices[i].quantum = scull_quantum;
scull_devices[i].qset = scull_qset;
init_MUTEX(&scull_devices[i].sem);
scull_setup_cdev(&scull_devices[i], i);
}
可以通过下⾯这张图来理解scull中的内存使⽤结构:
for (i = 0; i < scull_nr_devs; i++) {
scull_devices[i].quantum = scull_quantum;
scull_devices[i].qset = scull_qset;
init_MUTEX(&scull_devices[i].sem);
scull_setup_cdev(&scull_devices[i], i);
}
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);
}
我们⼀共申请了4个设备编号,要对四个设备的内存进⾏初始化,所以最外层的for循环很好理解
quantum表⽰量⼦的⼤⼩
qset表⽰数组的⼤⼩,即图中指向每个量⼦的指针数组的⼤⼩。
下⾯是信号互斥量的定义,以后再说
之后也是结构体的⼀些简单填充,在这⾥只是简单的赋值,只要熟悉即可,在下篇中的read函数中会详细讲到此结构体。
下⾯的部分函数可以暂时不看,今天只是刚刚接触到Linux驱动程序的开始,就先写这么多,还不太习惯,以后会常常更新,争取和⼤家共同进步。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。