第一种是使用mknod手工创建:# mknod <devfilename> <devtype> <major> <minor>

第二种是自动创建设备节点:利用udev(mdev)来实现设备文件的自动创建,首先应保证支持udev(mdev),由busybox配置。

具体udev相关知识这里不详细阐述,可以移步Linux 文件系统与设备文件系统 —— udev 设备文件系统,这里主要讲使用方法。

在驱动用加入对udev 的支持主要做的就是:在驱动初始化的代码里调用class_create(...)为该设备创建一个class,再为每个设备调用device_create(...)创建对应的设备

内核中定义的struct class结构体,顾名思义,一个struct class结构体类型变量对应一个类,内核同时提供了class_create(…)函数,可以用它来创建一个类,这个类存放于sysfs下面,一旦创建好了这个类,再调用 device_create(…)函数来在/dev目录下创建相应的设备节点。

这样,加载模块的时候,用户空间中的udev会自动响应 device_create()函数,去/sysfs下寻找对应的类从而创建设备节点。

下面是两个函数的解析:

支持字符设备文件自动生成
linux/device.h

struct class *class_create(struct module *owner, const char *name);
/*
  功能:在/sys/class目录下创建一个目录,目录名是name指定的
  参数:
    struct module *owner - THIS_MODULE
    const char *name - 设备名
  返回值:
    成功:class指针
    失败: - bool IS_ERR(const void *ptr)  判断是否出错
        long PTR_ERR(const void *ptr)  转换错误码
*/
void class_destroy(struct class *cls);
/*
  功能:删除class指针指向的目录
  参数:
    struct class *cls - class指针
*/
struct device *device_create(struct class *cls, struct device *parent, dev_t devt, void *drvdata, const char *fmt, ...);
/*
  功能:
    在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)   转换错误码
*/
void device_destroy(struct class *cls, dev_t devt);
/*
  功能:删除device_create创建的目录
  参数:
    struct class *cls - class指针
    dev_t devt - 设备号
*/

创建次序
struct class *class_create(struct module *owner, const char *name);
struct device *device_create(struct class *cls, struct device *parent, dev_t devt, void *drvdata, const char *fmt, ...);
删除次序
void device_destroy(struct class *cls, dev_t devt);
void class_destroy(struct class *cls);

实例:

#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/cdev.h>
#include <linux/fs.h>
#include <linux/errno.h>
#include <asm/current.h>
#include <linux/sched.h>
#include <linux/device.h> MODULE_LICENSE("GPL"); static struct class *cls = NULL; static int major = ;
static int minor = ;
const int count = ; #define DEVNAME "demo" static struct cdev *demop = NULL; //打开设备
static int demo_open(struct inode *inode, struct file *filp)
{
//get command and pid
printk(KERN_INFO "%s : %s : %d\n", __FILE__, __func__, __LINE__);return ;
} //关闭设备
static int demo_release(struct inode *inode, struct file *filp)
{
//get major and minor from inode
printk(KERN_INFO "%s : %s : %d\n", __FILE__, __func__, __LINE__);
return ;
} static struct file_operations fops = {
.owner = THIS_MODULE,
.open = demo_open,
.release= demo_release,
}; static int __init demo_init(void)
{
dev_t devnum;
int ret, i;
struct device *devp = NULL; //1. alloc cdev obj
demop = cdev_alloc();
if(NULL == demop){
return -ENOMEM;
}
//2. init cdev obj
cdev_init(demop, &fops); ret = alloc_chrdev_region(&devnum, minor, count, DEVNAME);
if(ret){
goto ERR_STEP;
}
major = MAJOR(devnum); //3. register cdev obj
ret = cdev_add(demop, devnum, count);
if(ret){
goto ERR_STEP1;
}
cls = class_create(THIS_MODULE, DEVNAME);
if(IS_ERR(cls)){
ret = PTR_ERR(cls);
goto ERR_STEP1;
}
for(i = minor; i < (count+minor); i++){
devp = device_create(cls, NULL, MKDEV(major, i), NULL, "%s%d", DEVNAME, i);
if(IS_ERR(devp)){
ret = PTR_ERR(devp);
goto ERR_STEP2;
}
}
return ; ERR_STEP2:
for(--i; i >= minor; i--){
device_destroy(cls, MKDEV(major, i));
}
class_destroy(cls); ERR_STEP1:
unregister_chrdev_region(devnum, count); ERR_STEP:
cdev_del(demop); //get command and pid
printk(KERN_INFO "%s : %s : %d - fail.\n", __FILE__, __func__, __LINE__);
return ret;
} static void __exit demo_exit(void)
{
int i;
//get command and pid
printk(KERN_INFO "%s : %s : %d - leave.\n", __FILE__, __func__, __LINE__); for(i=minor; i < (count+minor); i++){
device_destroy(cls, MKDEV(major, i));
}
class_destroy(cls); unregister_chrdev_region(MKDEV(major, minor), count); cdev_del(demop);
} module_init(demo_init);
module_exit(demo_exit);

下面可以看几个class几个名字的对应关系:

Linux设备文件自动生成的更多相关文章

  1. (转载)使用 udev 高效、动态地管理 Linux 设备文件

    概述: Linux 用户常常会很难鉴别同一类型的设备名,比如 eth0, eth1, sda, sdb 等等.通过观察这些设备的内核设备名称,用户通常能知道这些是什么类型的设备,但是不知道哪一个设备是 ...

  2. 嵌入式 使用udev高效、动态地管理Linux 设备文件

    本文以通俗的方法阐述 udev 及相关术语的概念.udev 的配置文件和规则文件,然后以 Red Hat Enterprise Server 为平台演示一些管理设备文件和查询设备信息的实例.本文会使那 ...

  3. 【转】使用 udev 高效、动态地管理 Linux 设备文件

    简介: 本文以通俗的方法阐述 udev 及相关术语的概念.udev 的配置文件和规则文件,然后以 Red Hat Enterprise Server 为平台演示一些管理设备文件和查询设备信息的实例.本 ...

  4. 使用maven根据JSON文件自动生成Java POJO类(Java Bean)源文件

    根据JSON文件自动生成Java POJO类(Java Bean)源文件 本文介绍使用程序jsonschema2pojo来自动生成Java的POJO类源文件,本文主要使用maven,其他构建工具请参考 ...

  5. CCS 6新建文件自动生成注释

    对于CCS6,可以通过配置,达到新建源文件或者头文件时,自动生成适当的注释: 一.新建源文件自动生成配置. 在某个文件夹下右击选择 New - Source File. 点击 Configure,再选 ...

  6. 使用 udev 高效、动态地管理 Linux 设备文件

    本文转自:https://www.ibm.com/developerworks/cn/linux/l-cn-udev/index.html 概述: Linux 用户常常会很难鉴别同一类型的设备名,比如 ...

  7. 使用 udev 管理 Linux 设备文件

    本文以通俗的方法阐述 udev 及相关术语的概念.udev 的配置文件和规则文件,然后以 Red Hat Enterprise Server 为平台演示一些管理设备文件和查询设备信息的实例.本文会使那 ...

  8. 文件参数化-utp框架之根据yaml文件自动生成python文件+utp运行用例

    根据yaml文件自动生成python文件 utp框架: bin目录:存放执行文件(run.py) cases目录:存放生成的用例的python文件(该目录下的文件为根据data目录下的测试用例生成的p ...

  9. IntelliJ IDEA 创建的文件自动生成 Author 注释 签名

    IntelliJ IDEA 创建的文件自动生成 Author 注释 签名1.打开 File --> Setting2.找到 Editor --> File and Code Templat ...

随机推荐

  1. 批量执行插入的sql和自动补零

    DECLARE @invoice_no int SET @invoice_no=3 WHILE @invoice_no<=100 --需要插入的次数 BEGIN --此处需要执行的插入sql文 ...

  2. js子窗口修改父窗口内容

    在框架中,我用 JavaScript 获取 JSON 数据,组织成 HTML 代码,最后将其填充至上层文档的一个元素中.按照一般的写法,我们需要用到类似如下的语句: 1.window.parent.d ...

  3. (四 )Knockout - ViewModel 的使用3 - 对象属性变化的实时更新

    ko.observableArray()就可以自动检测属性,其实他只是监控对象,而不是对象中的属性 使用ko.observable()进行处理 DEMO1 实时更新属性 //定义user数据对象 va ...

  4. storm教程

    二.安装部署   一.storm伪分布式安装 (一)环境准备1.OS:debian 72.JDK 7.0 (二)安装zookeeper1.下载zookeeper并解压 wget http://mirr ...

  5. 转载:详解CSS选择器、优先级与匹配原

    转载网址:http://polaris1119.javaeye.com/blog/764428 文章就CSS选择器的优先级问题做了一些总结,严格来讲,选择器的种类可以分为三种:标签名选择器.类选择器和 ...

  6. phpwind伪静态规则(IIS,Nginx,Apache)的介绍及代码

    phpwind iis下伪静态规则[ISAPI_Rewrite]RewriteRule ^(.*)/(.*)-htm-(.*)-(.*).html$ $1/$2.php?$3=$4RewriteRul ...

  7. LRU缓存算法 - C++版

    LRU是Least Recently Used的缩写,意思是最近最少使用,它是一种Cache替换算法. 实现思路: hashtable + 双向链表 时间复杂度: 插入,查找,删除:O(1) 空间使用 ...

  8. Linux_ERROR 1045 (28000): Access denied for user 'root'@'localhost'

    MySQL生成了root用户的随机密码(如下截图所示),并将这个随机密码放置在/root/.mysql_secret中.并且强制在第一次登陆时修改root用户的密码.Mysql 5.6及以后版本出处于 ...

  9. Linux下的QQ折腾记

        用Linux最重要是要把QQ装好了,webqq很不好用.qq for linux是古董,Linux还是悲惨,很多软件有windows版本,有mac版本,就是不出linux版本.只好用wine来 ...

  10. 【转】s3c2440 按键驱动 — 字符设备

    原文网址:http://www.xuebuyuan.com/632893.html 主机:VM - redhat 9.0 开发板:FL2440,linux-2.6.12 arm-linux-gcc:3 ...