Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1709363
  • 博文数量: 143
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 1462
  • 用 户 组: 普通用户
  • 注册时间: 2016-08-23 11:14
文章分类

全部博文(143)

文章存档

2022年(3)

2021年(13)

2020年(21)

2019年(8)

2018年(28)

2017年(7)

2016年(63)

我的朋友

分类: 嵌入式

2018-10-21 15:58:42

背景摘要:之前在“spi子系统代码走读”章节中的spi驱动时,有如下几个函数:register_chrdev(),class_create(),device_create(),本节我来详细说明一下他们的作用。

一、注册设备节点

参考:百度“register_chrdev” 百度“register_chrdev register_chrdev_region”

int register_chrdev (unsigned int major, const  char *name, struct file_operations*fops);

第一个参数是主设备号,0代表动态分配,如#define SPIDEV_MAJOR 153,这里spi的主设备号是153。(对于已完成注册的设备,用cat /proc/devices可以查询到)

第二个参数是设备的名字。

第三个参数是文件操作指针。

每个设备文件对应有两个设备号:一个是主设备号,标识该设备的种类,也标识了该设备所使用的驱动程序;另一个是次设备号,标识使用同一设备驱动程序的不同硬件设备。设备文件的主设备号(device_create()时)必须与设备驱动程序在登录该设备时申请的主设备号(register_chrdev()时)一致,否则用户进程将无法访问到设备驱动程序。

注意:除了register_chrdev()函数,在2.6的内核之后,新增了一个register_chrdev_region()函数,同时也保留了原有的register_chrdev()函数。

register_chrdev()调用了__register_chrdev_region(),并强制指定了起始次设备号为0256个,把一个主设备号下的所有次设备号都申请光了;同时它还封装了cdev_init() cdev_add(),倒是很省事。这种方式每一个主设备号只能存放一种设备,它们使用相同的 file_operation 结构体,也就是说内核最多支持 256 个字符设备驱动程序。模块卸载时,register_chrdev()对应需要调用unregister_chrdev()注销字符设备。

register_chrdev_region也调用了__register_chrdev_region(),但是次设备号可以根据自己需要进行申请;同时我们需要手动 cdev_init()cdev_add()。这种方式支持将同一个主设备号下的次设备号进行分段,每一段供给一个字符设备驱动程序使用,使得资源利用率大大提升。模块卸载时,register_chrdev_region()对应需要调用unregister_chrdev_region()释放原先申请的设备号;cdev_init()cdev_add()对应需要调用cdev_del()来释放cdev占用的内存。

但是,在 2.6 的内核中这两种方法都会调用到 __register_chrdev_region 函数。

用法:

点击(此处)折叠或打开

  1. #if old
  2.     major = register_chrdev(0, "hello", &hello_fops);
  3. #else
  4.     if(major==0)
  5.     {
  6.         alloc_chrdev_region(&devid, 0, 2, "hello");
  7.         major = MAJOR(devid);
  8.     }
  9.     else
  10.     {
  11.         devid = MKDEV(major, 0);
  12.             register_chrdev_region(devid, 2, "hello");
  13.     }

  14.     cdev_init(&hello_cdev, &hello_fops);
  15.     cdev_add(&hello_cdev, devid, 2);
  16. #endif

实例1.2.2 使用register_chrdev注册字符设备 字符设备之register_chrdev与register_chrdev_region

二、创建设备节点

参考:class_create(),device_create自动创建设备文件结点 一步一步学习 Linux 驱动之自动创建设备节点

刚开始学习驱动的时候,每次都需要mknod /dev/timer c 500 0 这样手动去创建一个设备节点。实际上Linux内核提供一组函数,可以用来在驱动模块加载的时候自动在/dev目录下创建相应的设备节点(my_device),并在卸载模块时删除该节点(my_device)。

class_createowner, name)和class_destroy(struct class *cls);配对使用

device_createstruct class *class, struct device *parent,dev_t devt, void *drvdata, const char *fmt, ...)和device_destroy(struct class *class,dev_t devt)配对使用

内核中定义了struct class结构体,顾名思义,一个struct class结构体类型变量对应一个类,内核同时提供了class_create()函数,可以用它来创建一个类,这个类存放于sysfs下面,一旦创建好了这个类,再调用device_create()函数来在/dev目录下创建相应的设备节点。这样,加载模块的时候,用户空间中的udev会自动响应device_create()函数,去/sysfs下寻找对应的类从而创建设备节点。

注意:在2.6较早的内核版本中,device_create()函数名称不同,是class_device_create()

实例一步一步学习 Linux 驱动之自动创建设备节点 字符设备之register_chrdev与register_chrdev_region

阅读(3666) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~