内核使用struct cdev结构表示字符设备,定义在<linux/cdev.h>。
分配和初始化cdev的方式有两种:
第一种:
#include <linux/init.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/kdev_t.h>
#include <linux/fs.h>
#include <linux/cdev.h>
//#define ALLOC_CDEV
static int major = 277;
static int minor = 0;
static dev_t devnum1;
static struct cdev cdev1;
static struct cdev *pcdev1;
static struct file_operations hello_ops;
static int hello_init(void)
{
printk("hello_init\n");
devnum1 = MKDEV(major,minor);
printk("major:%d, minor:%d\n", MAJOR(devnum1), MINOR(devnum1));
if (register_chrdev_region(devnum1, 1, "hello1"))//分配设备号
{
printk("register_chrdev_region failed\n");
return -1;
}
#ifndef ALLOC_CDEV
cdev_init(&cdev1, &hello_ops);//初始化cdev,绑定fops
if (cdev_add(&cdev1, devnum1, 1) < 0)//添加设备到内核
{
printk("cdev_add failed\n");
unregister_chrdev_region(devnum1, 1);
return -1;
}
#else
pcdev1 = cdev_alloc();
pcdev1->ops = &hello_ops;
if (cdev_add(pcdev1, devnum1, 1) < 0)//添加设备到内核
{
printk("cdev_add failed\n");
unregister_chrdev_region(devnum1, 1);
return -1;
}
#endif
return 0;
}
static void hello_exit(void)
{
printk("hello_exit\n");
#ifndef ALLOC_CDEV
cdev_del(&cdev1);
#else
cdev_del(pcdev1);
#endif
unregister_chrdev_region(devnum1, 1);
}
MODULE_LICENSE("GPL");
module_init(hello_init);
module_exit(hello_exit);
int cdev_add(struct cdev *p, dev_t dev, unsigned count);
p:cdev,dev:设备号,count:添加的字符设备数量(和该设备关联的设备编号的数量,即次设备号数量)
第二种:(早期方法)
#include <linux/init.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/kdev_t.h>
#include <linux/fs.h>
#include <linux/cdev.h>
static int major = 277;
static struct file_operations hello_ops;
static int hello_init(void)
{
printk("hello_init\n");
if (register_chrdev(major, "hello1", &hello_ops) < 0)
{
printk("register_chrdev failed \n");
return -1;
}
return 0;
}
static void hello_exit(void)
{
printk("hello_exit\n");
unregister_chrdev(major, "hello1");
}
MODULE_LICENSE("GPL");
module_init(hello_init);
module_exit(hello_exit);
register_chrdev函数将为给定的主设备号注册0~255作为次设备号,并为每个设备建立一个对应的默认cdev结构。使用register_chrdev函数的驱动程序必须能够处理所有256个次设备号上的open调用(不论它们是否真正对应于实际的设备),而且也不能使用大于255的主设备号和次设备号。