设备编号分为:
1. 主设备编号: 标识设备对应的驱动程序
2. 此设备编号: 内核使用,用于确定设备文件所指向的设备
linux/types.h 中定义 dev_t(32位)类型 用来保存设备编号 前20为minor 后12为major
linux/kdev_t.h 定义了宏:
MAJOR(dev_t dev); //获取主设备编号
MINOR(dev_t dev); //获取此设备编号
MKDEV(int major, int minor); //将主设备编号和此设备编号转化成dev_t类型
linux/fs.h 中声明:
int register_chrdev_region(dev_t first, unsigned int count, char *name); //这是一种定义好主设备编号的情况下,分配设备编号的情况;其中次设备号常被置0
//分配成功返回 0,失败返回一个负的错误码;
int alloc_chrdev_region(dev_t *dev, unsigned int minor,unsigned int count,char *name);
//动态分配设备编号避免了分配编号时与已有编号重叠的现象;其中 minor 通常为0
设备编号的释放:
void unregister_chrdev_region(dev_t first,unsigned int count);
//在模块的清除函数中调用此函数;
example:
..........
#define DEV_NAME Gusen_led
#define DEV_COUNT 1
static int major_num = 0;
static int minor_num = 0;
........
static int __init led_init(void)
{
dev_t dev_num;
int res;
if(major_num)
{
dev_num=MKDEV(major_num,minor_num);
res=register_chrdev_region(dev_num,DEV_COUNT,DEV_NAME);
}
else //动态分配设备号
{
res=alloc_chrdev_region(&dev_num,minor_num,DEV_COUNT,DEV_NAME);
major_num=MAJOR(dev_num);
}
if(res<0)
{
printk(
KERN_WARNING
"Gusen_led: can't get major %d\n"
, major_num
);
return res;
}
}
static void __exit irq_exit(void)
{
dev_t dev_num;
dev_num=MKDEV(major_num,minor_num);
.........
unregister_chrdev_region(dev_num,DEV_COUNT);
}