Class create, device create, device create file

开始写Linux设备驱动程序的时候,很多时候都是利用mknod命令手动创建设备节点(包括ldd3中不少例子也是这样),实际上现在Linux内核为我们提供了一组函数,可以用来在模块加载的时候自动在/dev目录下创建相应设备节点,并在卸载模块时删除该节点。

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

此外,利用device_create_file函数可以在/sys/class/下创建对应的属性文件,从而通过对该文件的读写实现特定的数据操作。

  • 1 一、class_create
  • 2 二、device_create
  • 3 三、device_create_file
    • 3.1 a.在驱动程序中使用 device_create_file创建属性文件
    • 3.2 b.在用户空间读取属性
  • 4 四、使用示例

一、class_create

官方说明:

/* This is a #define to keep the compiler from merging different* instances of the __key variable */
#define class_create(owner, name)       \
({                      \static struct lock_class_key __key;    \__class_create(owner, name, &__key);   \
})/*** class_create - create a struct class structure* @owner: pointer to the module that is to "own" this struct class* @name: pointer to a string for the name of this class.* @key: the lock_class_key for this class; used by mutex lock debugging** This is used to create a struct class pointer that can then be used* in calls to device_create().** Returns &struct class pointer on success, or ERR_PTR() on error.** Note, the pointer created here is to be destroyed when finished by* making a call to class_destroy().*/
struct class *__class_create(struct module *owner, const char *name,struct lock_class_key *key)

关键的一句是:

 * This is used to create a struct class pointer that can then be used* in calls to device_create().-->这个函数用来创建一个struct class的结构体指针,这个指针可用作device_create()函数的参数。

也就是说,这个函数主要是在调用device_create()前使用,创建一个struct class类型的变量,并返回其指针。

二、device_create

官方说明:

/*** device_create - creates a device and registers it with sysfs* @class: pointer to the struct class that this device should be registered to* @parent: pointer to the parent struct device of this new device, if any* @devt: the dev_t for the char device to be added* @drvdata: the data to be added to the device for callbacks* @fmt: string for the device's name** This function can be used by char device classes.  A struct device* will be created in sysfs, registered to the specified class.** A "dev" file will be created, showing the dev_t for the device, if* the dev_t is not 0,0.* If a pointer to a parent struct device is passed in, the newly created* struct device will be a child of that device in sysfs.* The pointer to the struct device will be returned from the call.* Any further sysfs files that might be required can be created using this* pointer.** Returns &struct device pointer on success, or ERR_PTR() on error.** Note: the struct class passed to this function must have previously* been created with a call to class_create().*/
struct device *device_create(struct class *class, struct device *parent,dev_t devt, void *drvdata, const char *fmt, ...)

首先解释一下"sysfs":sysfs是linux2.6所提供的一种虚拟档案系统;在设备模型中,sysfs文件系统用来表示设备的结构,将设备的层次结构形象的反应到用户空间中,从而可以通过修改sysfs中的文件属性来修改设备的属性值;sysfs被挂载到根目录下的"/sys"文件夹下。

三、device_create_file

官方说明:

/*** device_create_file - create sysfs attribute file for device.* @dev: device.* @attr: device attribute descriptor.*/
int device_create_file(struct device *dev,const struct device_attribute *attr)

使用这个函数时要引用 device_create所返回的device*指针,作用是在/sys/class/下创建一个属性文件,从而通过对这个属性文件进行读写就能完成对应的数据操作。

如:

a.在驱动程序中使用 device_create_file创建属性文件

static DEVICE_ATTR(val, S_IRUGO | S_IWUSR, hello_val_show, hello_val_store);  /*读取寄存器val的值到缓冲区buf中,内部使用*/
static ssize_t __hello_get_val(struct xxx_dev* dev, char* buf) {  int val = 0;          /*同步访问*/  if(down_interruptible(&(dev->sem))) {                  return -ERESTARTSYS;          }          val = dev->val;          up(&(dev->sem));          return snprintf(buf, PAGE_SIZE, "%d/n", val);
}  /*把缓冲区buf的值写到设备寄存器val中去,内部使用*/
static ssize_t __hello_set_val(struct xxx_dev* dev, const char* buf, size_t count) {  int val = 0;          /*将字符串转换成数字*/          val = simple_strtol(buf, NULL, 10);          /*同步访问*/          if(down_interruptible(&(dev->sem))) {                  return -ERESTARTSYS;          }          dev->val = val;          up(&(dev->sem));  return count;
}  /*读取设备属性val*/
static ssize_t hello_val_show(struct device* dev, struct device_attribute* attr, char* buf) {  struct xxx_dev* hdev = (struct xxx_dev*)dev_get_drvdata(dev);          return __hello_get_val(hdev, buf);
}  /*写设备属性val*/
static ssize_t hello_val_store(struct device* dev, struct device_attribute* attr, const char* buf, size_t count) {   struct xxx_dev* hdev = (struct xxx_dev*)dev_get_drvdata(dev);    return __hello_set_val(hdev, buf, count);
} /*模块加载方法*/
static int __init xxx_init(void){   ... /*在/sys/class/xxx/xxx目录下创建属性文件val*/  err = device_create_file(temp, &dev_attr_val);  if(err < 0) {  printk(KERN_ALERT"Failed to create attribute val.");                  goto destroy_device;  }...
} 

b.在用户空间读取属性

...
read(dev->fd, val, sizeof(*val));
...
write(dev->fd, &val, sizeof(val));
...

四、使用示例

    /*在/sys/class/目录下创建设备类别目录xxx*/ g_vircdev_class = class_create(THIS_MODULE, VIRCDEV_CLASS_NAME);if(IS_ERR(g_vircdev_class)) {  err = PTR_ERR(g_vircdev_class);  printk(KERN_ALERT "Failed to create class.\n");  goto CLASS_CREATE_ERR;  }/*在/dev/目录和/sys/class/xxx目录下分别创建设备文件xxx*/dev = device_create(g_vircdev_class, NULL, devt, NULL, VIRCDEV_DEVICE_NAME);if(IS_ERR(dev)) {  err = PTR_ERR(dev);  printk(KERN_ALERT "Failed to create device.\n");  goto DEVICE_CREATE_ERR;  }/*在/sys/class/xxx/xxx目录下创建属性文件val*/ err = device_create_file(dev, attr);  if(err < 0) {  printk(KERN_ALERT"Failed to create attribute file.");                  goto DEVICE_CREATE_FILE_ERR;  }

Class create, device create, device create file相关推荐

  1. 成功解决NotFoundError (see above for traceback): Failed to create a directory: ; No such file or directo

    成功解决NotFoundError (see above for traceback): Failed to create a directory: ; No such file or directo ...

  2. Git报错:fatal: Unable to create ‘xx/.git/index.lock‘: File exis

    一 报错:fatal: Unable to create 'xx/.git/index.lock': File exis 如下: $ git commit fatal: Unable to creat ...

  3. xcode打包bundle资源在unity上导入的时候出现Could not create asset from XXXX.png: File could not be read

    我xcode打包的bundle资源在unity上导入的时候出现Could not create asset from XXXX.png: File could not be read,排查了蛮久才发现 ...

  4. idea 创建maven项目报错: Failed to create parent directories for tracking file

    由于最近想换成idea开发,但是在创建maven项目的时候报了: Failed to create parent directories for tracking file,这个错误我在看了下错误的信 ...

  5. Create and Drop Database, Create, Alter and Drop Tables, Select, Insert, Update, Delete Commands

    此文仅做自我学习记录用!!! Introduction (Descriptive) Content:- Creating and Maintaining Tables, Objectives, The ...

  6. Jetson设备下使用docker报错的排错过程完整记录,failed to create shim: OCI runtime create failed: container_linux.go:38

    起因是要使用nvidia部署好的ngc镜像部署 nvidia@nvidia-desktop:~$ sudo docker images REPOSITORY TAG IMAGE ID CREATED ...

  7. MySQL create table as与create table like对比

    对于mysql的复制相同表结构方法,有create table as 和create table like 两种,区别是什么呢? create table t2 as select * from t1 ...

  8. mysql create很多table,SQL CREATE TABLE 语句

    原标题:SQL CREATE TABLE 语句 SQL CREATE TABLE 语句 CREATE TABLE 语句用于创建数据库中的表. 表由行和列组成,每个表都必须有个表名. SQL CREAT ...

  9. mysql create database to_MySQL中CREATE DATABASE和CREATE SCHEMA区别(转)

    在使用MS SQL的时候,一般创建数据库我们都习惯于使用CREATE DATABASE 来完成,而使用CREATE SCHEMA来创建架构,但是在MySQL中,官方的中文文档在 CREATE DATA ...

  10. android+图标+i_explore+无背景,Android Studio中Android Device Monitor中的File Explore不显示文...

    环境:操作系统是Mac,模拟器 问题:Android Studio中Android Device Monitor中的File Explore不显示文件 本人在自学文件存储,想查看"dada/ ...

最新文章

  1. 如何开好一个 OKR 评审会议?
  2. 汇总|目标检测中的数据增强、backbone、head、neck、损失函数
  3. iOS 工程师被要求写小程序,过分吗?| 每日趣闻
  4. Cenos 软件安装
  5. Angular应用里具有back功能的按钮实现
  6. 【渝粤题库】广东开放大学 信息安全数学基础 形成性考核 (2)
  7. sql server 2005 (select查询语句用法)
  8. php递归查询 大数组,php 递归 实现无限分类 格式化数组
  9. java课程心得_Java课程感想
  10. springboot学习总结
  11. 【第102期】游戏策划:在校生求职简历怎么写?
  12. EasyDarwin测试
  13. 轻松访问Google Chrome浏览器中的浏览历史记录
  14. 改变世界的webp图片技术,节约你的流量和带宽
  15. 一台计算机多个屏幕,一台电脑两个显示器怎么设置
  16. 直角三角形 纪中 1385 数学_斜率
  17. Hibernate中No row with the given identifier exis
  18. linux 安装snap7,基于linux7的ectd安装与部署
  19. ClickHouse正则匹配内网IP
  20. 5G前传网络之损伤仿真测试(5G Fronthaule, eCPRI, RoE, 25GbE)

热门文章

  1. mysql php 连接查询_php如何连接mysql并查询数据
  2. 手机mstsc远程工具_ToDesk — 免费不限速的远程控制软件
  3. python实现人脸识别比对_人脸识别并比对实现(基于face_recognition)
  4. 解决statsmodels报错ValueError: Pandas data cast to numpy dtype of object.
  5. mysql被更新失败_更新mysql出错:出错原因 You are using safe update mode
  6. lc滤波电路电感电容值选择_电感器变压器选型与应用
  7. HTTP1.1/2.0与QUIC协议
  8. Git 学习笔记(二)分支管理
  9. RSA加密、解密、签名、校验签名
  10. PAI算法组件详解:PLDA