Linux设备文件的创建

/************************************************************************************

*本文为个人学习记录,如有错误,欢迎指正。

*本文参考资料: 

*        http://www.cnblogs.com/chen-farsight/p/6154941.html

*        https://blog.csdn.net/yueqian_scut/article/details/46771595

************************************************************************************/

1. 创建设备文件的两种方式

(1)手动创建:mknod命令

在驱动程序insmod成功之后,通过mknod命令手动创建设备文件至/dev目录下:mknod /dev/xxx  c  主设备号 次设备号。("c"表示字符设备、"b"表示块设备、"p"表示网络设备)

(2)自动创建设备文件:mdev

在设备驱动注册到系统后,调用class_create为该设备在/sys/class目录下创建一个设备类,再调用device_create函数为每个设备创建对应的设备,并通过uevent机制调用mdev(嵌入式linux由busybox提供)来调用mknod创建设备文件至/dev目录下。

2. 自动创建设备文件过程分析

2.1 相关数据结构

struct class和struct device则通过sysfs向用户层提供信息。

 class_private是class的私有结构,class通过class_private注册到系统中;device_private是device的私有结构,device通过device_private注册到系统中。注册到系统中也是将相应的数据结构加入到系统已经存在的链表中,但是这些链接的细节并不希望暴露给用户,也没有必要暴露出来,所以才有private的结构。

//所在文件/kernel/include/linux/device.h
//设备类
struct class 
{
  const char *name; //设备类名称
  struct module *owner;//创建设备类的module
  struct class_attribute *class_attrs;//设备类属性
  struct device_attribute *dev_attrs;//设备属性
  struct kobject *dev_kobj;//kobject再sysfs中代表一个目录
  .....................
  struct class_private *p;//设备类得以注册到系统的连接件
};

//drivers/base/base.h
struct class_private
{
  struct klist class_devices;//设备类包含的设备(kobject)
  ..................................
  struct class *class;//指向设备类数据结构,即要创建的本级目录信息
};

 

//所在文件/kernel/include/linux/device.h
struct device 
{
  struct device *parent;        //sysfs/devices/中的父设备
  struct device_private *p;     //设备得以注册到系统的连接件
  struct kobject kobj;          //设备目录
  const char *init_name;        //设备名称
  struct bus_type *bus;         //设备所属总线
  struct device_driver *driver; //设备使用的驱动
  struct klist_node knode_class;//连接到设备类的klist
  struct class *class;          //所属设备类
  .....................
};
//所在文件/kernel/drivers/base/base.h
struct device_private 
{
    struct klist klist_children;    //连接子设备
    struct klist_node knode_parent; //加入到父设备链表
    struct klist_node knode_driver; //加入到驱动的设备链表
    struct klist_node knode_bus;    //加入到总线的链表
    struct device *device;          //对应设备结构
};

2.2 创建过程

step1:调用class_create函数在/sys/class目录下创建一个设备类。

/*
  功能:在/sys/class目录下创建一个目录,目录名是name指定的
  参数:
    struct module *owner - THIS_MODULE
    const char *name - 设备名
  返回值:
    成功:class指针
    失败: - bool IS_ERR(const void *ptr)  判断是否出错
         long PTR_ERR(const void *ptr) 转换错误码
*/
struct class *class_create(struct module *owner, const char *name);

step2:调用device_create函数在step1创建的设备类目录下创建具体的设备目录和设备属性文件。

/* 
  功能:
    在class指针指向的目录下再创建一个目录,目录名由const char *fmt, ...指出、并导出设备信息(dev_t)
  参数:
    struct class *cls - class指针
    struct device *parent - 父对象,NULL
    dev_t devt - 设备号
    void *drvdata - 驱动私有数据
    const char *fmt, ... - fmt是目录名字符串格式,...就是不定参数
  返回值:
    成功 - device指针
    失败 - bool IS_ERR(const void *ptr)  判断是否出错
       long PTR_ERR(const void *ptr)   转换错误码
*/
struct device *device_create(struct class *cls, struct device *parent, dev_t devt, void *drvdata, const char *fmt, ...);

step3:在/dev创建设备文件(系统自动进行)

step1、step2都是在sysfs文件系统中创建目录或者文件,而应用程序访问的设备文件则需要创建在/dev/目录下。该项工作由mdev完成(需保证根文件系统支持mdev,由busybox配置)。

2.2 注销过程

step1:删除设备类目录下的设备

/*
  功能:删除device_create创建的目录
  参数:
    struct class *cls - class指针
    dev_t devt - 设备号
*/
void device_destroy(struct class *cls, dev_t devt);

step2:删除/sys/class目录下的设备类

/*
  功能:删除class指针指向的目录
  参数:
    struct class *cls - class指针
*/
void class_destroy(struct class *cls);
posted @ 2018-07-16 10:38  LinFeng-Learning  阅读(7099)  评论(0编辑  收藏  举报