Linux内核 设备号dev_t的使用(静态和动态创建)

今天我们来谈谈字符设备驱动的框架和具体使用吧:

我们先来看看字符驱动的大概框架吧:在这里我用一幅图来看看:

Linux内核 设备号dev_t的使用(静态和动态创建)_第1张图片

 

 

首先我们了解一下设备驱动中的基本步骤吧:

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");

编译结果如下:

Linux内核 设备号dev_t的使用(静态和动态创建)_第2张图片

 我们应用设备号构建一个设备文件看看:

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")

编译结果如下:

Linux内核 设备号dev_t的使用(静态和动态创建)_第3张图片 

应用程序:

 

 

 

 

 

你可能感兴趣的:(linux驱动入门)