字符设备初始化函数

下载了scull的代码,看着学习。

昨天看了LDD3的第三章:字符设备驱动程序。了解了有关设备编号,三个重要的结构,字符设备的注册等。今天主要看看scull代码中字符设备的初始函数。

查看的代码位置D:\Code\scull\examples\scull,源码粘贴:

int scull_init_module(void)
{
	int result, i;
	dev_t dev = 0;

/*
 * Get a range of minor numbers to work with, asking for a dynamic
 * major unless directed otherwise at load time.
 */
	if (scull_major) {
		dev = MKDEV(scull_major, scull_minor);
		result = register_chrdev_region(dev, scull_nr_devs, "scull");
	} else {
		result = alloc_chrdev_region(&dev, scull_minor, scull_nr_devs,
				"scull");
		scull_major = MAJOR(dev);
	}
	if (result < 0) {
		printk(KERN_WARNING "scull: can't get major %d\n", scull_major);
		return result;
	}

        /* 
	 * allocate the devices -- we can't have them static, as the number
	 * can be specified at load time
	 */
	scull_devices = kmalloc(scull_nr_devs * sizeof(struct scull_dev), GFP_KERNEL);
	if (!scull_devices) {
		result = -ENOMEM;
		goto fail;  /* Make this more graceful */
	}
	memset(scull_devices, 0, scull_nr_devs * sizeof(struct scull_dev));

        /* Initialize each device. */
	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);
	}

        /* At this point call the init function for any friend device */
	dev = MKDEV(scull_major, scull_minor + scull_nr_devs);
	dev += scull_p_init(dev);
	dev += scull_access_init(dev);

#ifdef SCULL_DEBUG /* only when debugging */
	scull_create_proc();
#endif

	return 0; /* succeed */

  fail:
	scull_cleanup_module();
	return result;
}
首先分配主次设备号:

如果scull_major事先已知则使用register_chrdev_region函数分配设备编号,反之使用alloc_chrdev_region函数。对返回值检测,看是否分配成功。

接下来看到一句不太明白的代码:

scull_devices = kmalloc(scull_nr_devs * sizeof(struct scull_dev), GFP_KERNEL);
	if (!scull_devices) {
		result = -ENOMEM;
		goto fail;  /* Make this more graceful */
	}
kmalloc函数大致看了下应该是内核使用的内存分配函数。先看一下scull_devices这个结构体,里面有很多信息,有数据,还有对数据的描述内容。我想上面的代码主要是为scull这个假设的设备分配内存,内存分配结束后对该内存清零。

/*
 * Representation of scull quantum sets.
 */
struct scull_qset {
	void **data;
	struct scull_qset *next;
};

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		*/
};
然后代码就是一个for循环:对分配内存的每个设备进行初始化,其中有一函数如下。以及该函数的定义。

scull_setup_cdev(&scull_devices[i], i);
/*
 * Set up the char_dev structure for this device.
 */
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);
}
该函数完成字符设备的注册。
下面的代码看了一下,暂时不太明白,先告一段落吧。
对照着书上的内容从头到尾看一下代码。分配主次设备号->分配设备内存->初始化内存及向内核注册字符设备。

但书上说到struct cdev结构时讲到“如果读者打算在运行时获得一个独立的cdev结构,则应该如下编写代码:struct cdev *my_cdev = cdev_alloc();my_cdev->ops = &my_fops;”

但是代码中似乎没有这么一段。
百度了一下看了别人写的, 才发现自己理解错误了。上面引用的原文是动态初始化,而scull源码中使用的是静态初始化。

参考转载内容:Linux内核中的cdev_alloc和cdev_add

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值