本文共 4071 字,大约阅读时间需要 13 分钟。
在文件 include/linux/fs.h 中,内核提供了三个函数来注册一组字符设备编号:
register_chrdev_region()alloc_chrdev_region()register_chrdev()register_chrdev_regionint register_chrdev_region(dev_t from, unsigned count, const char *name)
from:要分配的设备编号范围的初始值,这组连续设备号的起始设备号。count:连续编号范围,是这组设备号的大小(也是次设备号的个数)。name:编号相关联的设备名称(/proc/devices),本组设备的驱动名称。alloc_chrdev_regionint alloc_chrdev_region(dev_t *dev, unsigned baseminor, unsigned count, const char *name)
dev:alloc_chrdev_region函数向内核申请下来的设备号。baseminor:次设备号的起始。count:申请次设备号的个数。name:执行 cat /proc/devices 显示的名称。register_chrdev(老版本的字符设备申请函数)int register_chrdev(unsigned int major, const char *name, const struct file_operations *fops)
major:主设备号,当用户设置为0时,内核会动态分配一个设备号。name:设备名称。fops:文件系统的接口指针。头文件位置 include/linux/kdev_t.h,定义了以下宏:
#define MAJOR(dev) ((unsigned int) ((dev) >> MINORBITS))#define MINOR(dev) ((unsigned int) ((dev) & MINORMASK))#define MKDEV(ma, mi) (((ma) << MINORBITS) | (mi))
MKDEV:将主设备号和次设备号组合成一个 dev_t 类型的设备编号。dev_t 类型是 unsigned int,高12位为主设备号,低20位为次设备号。头文件位置 include/linux/cdev.h,定义了 cdev 结构体:
struct cdev { struct kobject kobj; struct module *owner; const struct file_operations *ops; struct list_head list; dev_t dev; unsigned int count;} cdev.dev:设备号,高12位为主设备号,低20位为次设备号。#include#include #include #include #include #include #define DEVICE_NAME "scdev"#define DEVICE_MINOR_NUM 2#define DEV_MAJOR 0#define DEV_MINOR 0MODULE_LICENSE("Dual BSD/GPL");MODULE_AUTHOR("iTOPEET_dz");int numdev_major = DEV_MAJOR;int numdev_minor = DEV_MINOR;module_param(numdev_major, int, S_IRUSR);module_param(numdev_minor, int, S_IRUSR);static int scdev_init(void) { int ret = 0; dev_t num_dev; printk(KERN_EMERG "numdev_major is %d!\n", numdev_major); printk(KERN_EMERG "numdev_minor is %d!\n", numdev_minor); if (numdev_major) { num_dev = MKDEV(numdev_major, numdev_minor); ret = register_chrdev_region(num_dev, DEVICE_MINOR_NUM, DEVICE_NAME); } else { printk(KERN_EMERG "numdev_major %d is failed!\n", numdev_major); } if (ret < 0) { printk(KERN_EMERG "register_chrdev_region req %d is failed!\n", numdev_major); } printk(KERN_EMERG "scdev_init!\n"); return 0;}static void scdev_exit(void) { printk(KERN_EMERG "scdev_exit!\n"); unregister_chrdev_region(MKDEV(numdev_major, numdev_minor), DEVICE_MINOR_NUM);}module_init(scdev_init);module_exit(scdev_exit);
#!/bin/bashobj-m += request_cdev_num.oKDIR := /home/topeet/iTop4412_Kernel_3.0PWD := $(shell pwd)all: make -C $(KDIR) M=$(PWD) modulesclean: rm -rf *.mod.c *.o *.order *.ko *.mod.o *.symvers
#include#include #include #include #include #include #define DEVICE_NAME "acdev"#define DEVICE_MINOR_NUM 2#define DEV_MAJOR 0#define DEV_MINOR 0MODULE_LICENSE("Dual BSD/GPL");MODULE_AUTHOR("iTOPEET_dz");int numdev_major = DEV_MAJOR;int numdev_minor = DEV_MINOR;module_param(numdev_major, int, S_IRUSR);module_param(numdev_minor, int, S_IRUSR);static int acdev_init(void) { int ret = 0; dev_t num_dev; printk(KERN_EMERG "numdev_major is %d!\n", numdev_major); printk(KERN_EMERG "numdev_minor is %d!\n", numdev_minor); if (numdev_major) { num_dev = MKDEV(numdev_major, numdev_minor); ret = register_chrdev_region(num_dev, DEVICE_MINOR_NUM, DEVICE_NAME); } else { ret = alloc_chrdev_region(&num_dev, numdev_minor, DEVICE_MINOR_NUM, DEVICE_NAME); numdev_major = MAJOR(num_dev); printk(KERN_EMERG "adev_region req %d !\n", numdev_major); } if (ret < 0) { printk(KERN_EMERG "register_chrdev_region req %d is failed!\n", numdev_major); } printk(KERN_EMERG "acdev_init!\n"); return 0;}static void acdev_exit(void) { printk(KERN_EMERG "acdev_exit!\n"); unregister_chrdev_region(MKDEV(numdev_major, numdev_minor), DEVICE_MINOR_NUM);}module_init(acdev_init);module_exit(acdev_exit);
[root@iTOP-4412]# insmod request_acdev_num.ko[root@iTOP-4412]# rmmod request_acdev_num
转载地址:http://idwh.baihongyu.com/