注册字符设备驱动新接口

目录

新接口与老接口

cdev介绍

设备号

register_chrdev_region主动申请设备号编程实战:

第一步:注册/分配主次设备号

第二步:注册字符设备驱动

注销设备驱动:

下面提供一个最简单的范例:

alloc_chrdev_region自动分配设备号:

接口分析:

 老接口分析 

新接口分析


新接口与老接口

(1)老接口:register_chrdev
(2)新接口:register_chrdev_region(自己指定申请设备号)/alloc_chrdev_region(系统自动分配设备号)(这两个的驱动都还没注册) + cdev(结构体,注册驱动)

模块加载函数通过 register_chrdev_region( ) 或 alloc_chrdev_region( )来静态或者动态获取设备号;

通过 cdev_init( ) 建立cdev与 file_operations之间的连接,通过 cdev_add( ) 向系统添加一个cdev以完成注册;

模块卸载函数通过cdev_del( )来注销cdev,通过 unregister_chrdev_region( )来释放设备号;

cdev介绍

去cdev.h里找

struct cdev {
   struct kobject kobj;          // 内嵌的内核对象,每个 cdev 都是一个 kobject
   struct module *owner;       // 指向实现驱动的模块
   const struct file_operations *ops;   // 操纵这个字符设备文件的方法
   struct list_head list;       // 与 cdev 对应的字符设备文件的 inode->i_devices 的链表头,用来将已经向内核注册的所有字符设备形成链表
   dev_t dev;                   // 字符设备的设备号,由主设备号和次设备号构成
   unsigned int count;       // 隶属于同一主设备号的次设备号的个数.
};

设备号

(1)=主设备号+次设备号
(2)dev_t类型
(3)MKDEV、MAJOR、MINOR三个宏

MKDEV:由主设备号和次设备号算出主次设备号

MAJOR:由设备号提取出主设备号

MINOR:由设备号提取出次设备号

相关函数:cdev_alloc、cdev_init、cdev_add(注册驱动)、cdev_del(注销驱动)

register_chrdev_region主动申请设备号编程实战:

使用register_chrdev_region + cdev_init + cdev_add进行字符设备驱动的注册

第一步:注册/分配主次设备号

#define MYMAJOR		200
#define MYCNT		1
#define MYNAME		"testchar"

static dev_t mydev;


static int __init chrdev_init(void)
{	
/*第一步*/
	int retval;
	printk(KERN_INFO "chrdev_init helloworld init\n");

    mydev = MKDEV(MYMAJOR, 0);//算出主次设备号
    retval = register_chrdev_region(mydev, MYCNT, MYNAME);//自己指定申请设备号(主次设备号,数量,设备名)
	if (retval) {
		printk(KERN_ERR "Unable to register minors for %s\n", MYNAME);
		return -EINVAL;
	}
	printk(KERN_INFO "register_chrdev_region success\n");


/*第二步见下方*/


}

第二步:注册字符设备驱动

static struct cdev test_cdev;
static const struct file_operations test_fops = {
	.owner		= THIS_MODULE,				// 惯例,直接写即可
	
	.open		= test_chrdev_open,			// 将来应用open打开这个设备时实际调用的
	.release	= test_chrdev_release,		// 就是这个.open对应的函数
	.write 		= test_chrdev_write,
	.read		= test_chrdev_read,
};

// 第2步:注册字符设备驱动
	cdev_init(&test_cdev, &test_fops);//初始化cdev
	retval = cdev_add(&test_cdev, mydev, MYCNT);//注册cdev
	if (retval) {
		printk(KERN_ERR "Unable to cdev_add\n");
		return -EINVAL;
	}
	printk(KERN_INFO "cdev_add success\n");

注销设备驱动:

// 注销分2步:
	// 第一步真正注销字符设备驱动用cdev_del
	cdev_del(&test_cdev);
	// 第二步去注销申请的主次设备号
	unregister_chrdev_region(mydev, MYCNT);

下面提供一个最简单的范例:

#include <linux/init.h>
#include <linux/module.h>
#include <linux/kdev_t.h>
#include <linux/fs.h>
#include <linux/cdev.h>

static int major = 237;
static int minor = 0;
static dev_t devno;
static struct cdev cdev;
static int hello_open (struct inode *inode, struct file *filep)
{
	printk("hello_open()\n");
	return 0;
}
static struct file_operations hello_ops = 
{
	.open = hello_open,
};
static int hello_init(void)
{
	int result;
	int error;	
	printk("hello_init \n");
	devno = MKDEV(major,minor);	
	result = register_chrdev_region(devno, 1, "test");
	if(result<0)
	{
		printk("register_chrdev_region fail \n");
		return result;
	}
	cdev_init(&cdev,&hello_ops);
	error = cdev_add(&cdev,devno,1);
	if(error < 0)
	{
		printk("cdev_add fail \n");
		unregister_chrdev_region(devno,1);
		return error;
	}
	return 0;
}
static void hello_exit(void)
{
	printk("hello_exit \n");
	cdev_del(cdev);
	unregister_chrdev_region(devno,1);
	return;
}
module_init(hello_init);
module_exit(hello_exit);

应用程序如果要想使用,还必须创建字符设备节点

mknod /dev/test c 237 0

alloc_chrdev_region自动分配设备号:

register_chrdev_region是在事先知道要使用的主、次设备号时使用的;先cat /proc/devices去看看没有使用。
更简便、更智能的方法是让内核给我们自动分配一个主设备号,使用alloc_chrdev_region就可以自动分配了。

自动分配的设备号,我们必须去知道他的主次设备号,否则后面没法去mknod创建他对应的设备文件。

接口分析:

 老接口分析 

register_chrdev
    __register_chrdev

        __register_chrdev_region
        cdev_alloc
        cdev_add

新接口分析

register_chrdev_region
    __register_chrdev_region

alloc_chrdev_region
    __register_chrdev_region

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值