今天我们来谈谈字符设备驱动的框架和具体使用吧:
我们先来看看字符驱动的大概框架吧:在这里我用一幅图来看看:
首先我们了解一下设备驱动中的基本步骤吧:
a -- 模块加载函数通过 register_chrdev_region( ) 或 alloc_chrdev_region( )来静态或者动态获取设备号;
b -- 通过 cdev_init( ) 建立cdev与 file_operations之间的连接,通过 cdev_add( ) 向系统添加一个cdev以完成注册;
c -- 模块卸载函数通过cdev_del( )来注销cdev,通过 unregister_chrdev_region( )来释放设备号;
1,首先我们看看用a和c来举个例子来看看:
#include
#include
#include
MODULE_LICENSE("Dual BSD/GPL");
#define CHARDEVICIVEDRIVER_MAJOR 240
#define CHARDEVICIVEDRIVER_MINOR 0
#define CHARDEVICIVEDRIVER_COUNT 1
#define CHARDEVICIVEDRIVER_NAME "chardevicedriver"
static int __init chardevicedriver_init(void)
{
int ret = -EFAULT;
dev_t dev = 0; //32为int数据,高12位主设备号,低20位次设备号
printk("function = %s,line = %d\n",__FUNCTION__,__LINE__);
//创建设备号
dev = MKDEV(CHARDEVICIVEDRIVER_MAJOR,CHARDEVICIVEDRIVER_MINOR);
//静态申请设备号
ret = register_chrdev_region(dev,CHARDEVICIVEDRIVER_COUNT,CHARDEVICIVEDRIVER_NAME);
if(ret >0)
{
printk("register_chrdev_regin can't getr char device : major = %d,name = %s\n",\
CHARDEVICIVEDRIVER_MAJOR,CHARDEVICIVEDRIVER_NAME);
goto failure_register_chrdev;
}
printk("register_chrdev_regin : major = %d,name = %s\n",\
CHARDEVICIVEDRIVER_MAJOR,CHARDEVICIVEDRIVER_NAME);
return ret;
failure_register_chrdev:
return ret;
}
static void __exit chardevicedriver_exit(void)
{
printk("function = %s,line = %d\n",__FUNCTION__,__LINE__);
unregister_chrdev_region(MKDEV(CHARDEVICIVEDRIVER_MAJOR,CHARDEVICIVEDRIVER_MINOR),CHARDEVICIVEDRIVER_COUNT);
}
module_init(chardevicedriver_init);
module_exit(chardevicedriver_exit);
MODULE_AUTHOR("tangtang");
MODULE_VERSION("0.0.1");
编译结果如下:
我们应用设备号构建一个设备文件看看:
2, 添加设备号到cdev结构体里面:
a -- void cdev_init(struct cdev *, const struct file_operations *);
b --struct cdev *cdev_alloc(void);
c -- int cdev_add(struct cdev *p, dev_t dev, unsigned count);
d -- void cdev_del(struct cdev *p);
举个例子来看看吧:
#include
#include
#include
#include
MODULE_LICENSE(Dual BSD/GPL");
#define CHARDEVICIVEDRIVER_MAJOR 240
#define CHARDEVICIVEDRIVER_MINOR 0
#define CHARDEVICIVEDRIVER_COUNT 1
#define CHARDEVICIVEDRIVER_NAME "chardevicedriver"
typedef struct file_operations chardevicedriver_fops = {
.ower = THIS_MOUDLE;
}
static struct cdev chardevicedriver_cdev;
static int __init chardevicedriver_init(void)
{
int ret = -EFAULT;
dev_t dev = 0; //设备号
printk("function = %s,line = %d",__FUNCTION__,__LINE__);
dev = MKDEV(CHARDEVICIVEDRIVER_MAJOR,CHARDEVICIVEDRIVER_MINOR);
ret = register_chrdev_regin(dev,CHARDEVICIVEDRIVER_COUNT,CHARDEVICIVEDRIVER_NAME);
if(ret >0)
{
printk("register_chrdev_regin can't getr char device : major = %d,name = %s\n",\
CHARDEVICIVEDRIVER_MAJOR,CHARDEVICIVEDRIVER_NAME);
goto failure_register_chrdev;
}
printk("register_chrdev_regin : major = %d,name = %s\n",\
CHARDEVICIVEDRIVER_MAJOR,CHARDEVICIVEDRIVER_NAME);
//注册cdev
memset(&chardevicedriver_cdev,0,sizeof( struct cdev));
cdev_init(&chardevicedriver_cdev,&chardevicedriver_fops);
ret = cdev_add(&chardevicedriver_cdev,dev,CHARDEVICIVEDRIVER_COUNT);
if(ret <0)
{
printk("chardevicedriver add dev failure\n");
goto failure_add_cdev;
}
printk("cdev_add hardevicedriver success\n");
return ret;
failure_add_cdev:
unregister_chrdev_regin(dev,CHARDEVICIVEDRIVER_COUNT);
failure_register_chrdev:
return ret;
}
static void __exit chardevicedriver_exit(void)
{
printk("function = %s,line = %d",__FUNCTION__,__LINE__);
//delete cdev
cdev_del(&chardevicedriver_cdev);
unregister_chrdev_regin(MKDEV(CHARDEVICIVEDRIVER_MAJOR,CHARDEVICIVEDRIVER_MINOR),CHARDEVICIVEDRIVER_COUNT);
}
module_init(chardevicedriver_init);
module_exit(chardevicedriver_exit);
MODULE_AUTHOR("tangtang");
MODULE_VERSION("0.0.1")
编译结果如下:
应用程序: