字符设备驱动详解

字符设备建立的步骤:
1.通过MKDEV宏获取字符设备的设备号
MKDEV的宏原型为#define MKDEV(ma,mi) (((ma) << 20) | (mi))
根据宏MKDEV可以知道字符设备的设备号为32位,高12为主设备号,低20位为次设备号

2.注册设备号
如果我们在注册字符设备时,已经获取到了设备号则直接用int register_chrdev_region(dev_t from, unsigned count, const char *name);  
from: 注册的指定起始设备编号,比如:MKDEV(100, 0),表示起始主设备号100, 起始次设备号为0,即为MKDEV的返回值。

count:需要连续注册的次设备编号个数,比如: 起始次设备号为0,count=100,表示0~99的次设备号都要绑定在同一个file_operations操作方法结构体上

*name:字符设备名称

当返回值小于0,表示注册失败

如果我们在注册字符设备时,不知道设备编号,则通过int alloc_chrdev_region(dev_t *dev, unsigned baseminor, unsigned count,const char *name);
函数动态分配获取设备号并注册
*dev: 存放起始设备编号的指针,当注册成功, *dev就会等于分配到的起始设备编号,可以通过MAJOR()和MINNOR()函数来提取主次设备号

baseminor:次设备号基地址,也就是起始次设备号

count:需要连续注册的次设备编号个数,比如: 起始次设备号(baseminor)为0,baseminor=2,表示0~1的此设备号都要绑定在同一个file_operations操作方法结构体上

*name:字符设备名称

当返回值小于0,表示注册失败

3.设备号注册完成后得动态申请设备结构体内存
/globalmem 设备结构体/
根据自己需求定义设备结构体,如struct globalmem_dev *globalmem_dev;

globalmem_devp = kmalloc(sizeof(struct globalmem_dev), GFP_KERNEL);

4.初始化并注册cdev
1)动态申请设备内存完成后,下一步进行初始化并注册字符设备cdev,初始化字符设备的函数如下:
void cdev_init(struct cdev *cdev, const struct file_operations *fops);

2)将cdev结构体添加到系统中,并将dev(注册好的设备编号)放入dev里, count(次设备编号个数)
int cdev_add(struct cdev *p, dev_t dev, unsigned count);

其中cdev结构体的成员,如下所示:

struct cdev {

       struct kobject    kobj;                   // 内嵌的kobject对象

       struct module   *owner;                   //所属模块

       const struct file_operations  *ops;     //操作方法结构体

       struct list_head  list;            //与 cdev 对应的字符设备文件inode->i_devices 的链表头

       dev_t dev;                    //起始设备编号,可以通过MAJOR(),MINOR()来提取主次设备号

       unsigned int count;                //连续注册的次设备号个数

};

主要是初始化.owner = THIS_MODULE;
.ops = &globalmem_fops;(指向自己定义的file_operations结构体变量globamen_fops);
例如我的的globalmen_fops结构体初始化如下:
/文件操作结构体/

static const struct file _ operations globalmem _ fops =
{
	.owner = THIS _ MODULE,
	.llseek = globalmem _ llseek,
	.read = globalmem _ read,
	.write = globalmem _ write,
	.ioctl = globalmem _ ioctl,
	.open = globalmem _ open,
	.release = globalmem _ release,
};

5.卸载模块
1)卸载模块主要包括注销cdev设备:void cdev_del(struct cdev *p);
2)释放设备结构体内存kfree(); kfree在linux内核源码中是一个宏,原型为# define kfree(x) do{if(x)free(x);}while (0)
宏定义中用到了do{;}while(0),在函数中只执行一次因此do{;}while(0)一般在宏定义中使用比较多
3)释放设备号: /注销字符设备/

void unregister_chrdev_region(dev_t from, unsigned count);

from: 注销的指定起始设备编号,比如:MKDEV(100, 0),表示起始主设备号100, 起始次设备号为0,即为MKDEV的返回值。

count:需要连续注销的次设备编号个数,比如: 起始次设备号为0,baseminor=100,表示注销掉0~99的次设备号。

以上步骤就是基本字符设备从注册->初始化->添加->卸载 的基本流程。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值