首页 > 系统相关 >Linux设备文件自动生成

Linux设备文件自动生成

时间:2023-04-16 14:13:33浏览次数:42  
标签:__ struct ERR 生成 自动 Linux device class cls

原文:https://www.cnblogs.com/chen-farsight/p/6154941.html

第一种是使用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 = 0;
static int minor = 0;
const  int count = 6;

#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 0;
}

//关闭设备
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 0;
}

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 0;

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几个名字的对应关系:

标签:__,struct,ERR,生成,自动,Linux,device,class,cls
From: https://www.cnblogs.com/bruce1992/p/17323204.html

相关文章

  • Linux硬盘知识(三)-硬盘的扩容与缩减
    提示:大部分分区的缩减需要挂载到另一个Ubuntu。1、Boot引导分区等可以直接在gparted里挂载的盘挂载到另一个Ubuntu,使用工具gparted对Boot与EFI盘进行操作2、LVM逻辑盘扩张与缩减(LVM一般包括"根目录"与"swap"逻辑)1) 扩张不需要挂载到另一个Ubuntu;详见:https://blog.csdn.net......
  • OMV在ZFS做自动快照计划
    在OMV计划任务中添加两条计划,1、添加计划任务,按选项选择合适的任务时间周期,在命令行加填写:zfssnapshotzfspool@snapshot_$(date+%Y%m%d%H%M%S)snapshot_为快照名前缀,$(date+%Y%m%d)为根据当期日期时间生成快照名的后缀。2、添加计划任务,删除一周前快照zfsdestroyzfspool@......
  • Linux硬盘知识(目录)-目录
    一,清理硬盘  Linux硬盘知识(一)-清理硬盘二,移植系统  Linux硬盘知识(二)-移植系统三,Linux硬盘的扩容与缩减  ......
  • Linux id 命令
    Linuxid命令Linuxid命令用于显示用户的ID,以及所属群组的ID。id会显示用户以及所属群组的实际与有效ID,若两个ID相同,则仅显示实际ID,若仅指定用户名称,则显示目前用户的ID。该命令会显示用户的UID(UserID)、GID(GroupID)以及附属于用户的所有组ID。语法id[-gGnru][--he......
  • Linux groupadd 命令
    Linuxgroupadd命令groupadd命令用于创建一个新的工作组,新工作组的信息将被添加到系统文件中。相关文件:/etc/group组账户信息。/etc/gshadow安全组账户信息。/etc/login.defsShadow密码套件配置。语法groupadd命令语法格式如下:groupadd[-ggid[-o]][-r][-f]......
  • Linux free命令
    Linuxfree命令Linuxfree命令用于显示内存状态。free指令会显示内存的使用情况,包括实体内存,虚拟的交换文件内存,共享内存区段,以及系统核心使用的缓冲区等。语法free[-bkmotV][-s<间隔秒数>]参数说明:-b以Byte为单位显示内存使用情况。-k以KB为单位显示内存使用......
  • Linux who命令
    Linuxwho命令Linuxwho命令用于显示系统中有哪些使用者正在上面,显示的资料包含了使用者ID、使用的终端机、从哪边连上来的、上线时间、呆滞时间、CPU使用量、动作等等。使用权限:所有使用者都可使用。语法who-[husfV][user]参数说明:-H或--heading:显示各栏位的标题......
  • Linux su 命令
    Linuxsu命令Linuxsu(英文全拼:switchuser)命令用于变更为其他使用者的身份,除root外,需要键入该使用者的密码。使用权限:所有使用者。语法su[-fmp][-ccommand][-sshell][--help][--version][-][USER[ARG]]参数说明:-f或--fast不必读启动档(如csh.cshrc等),仅用......
  • Linux w命令
    Linuxw命令Linuxw命令用于显示目前登入系统的用户信息。执行这项指令可得知目前登入系统的用户有哪些人,以及他们正在执行的程序。单独执行w指令会显示所有的用户,您也可指定用户名称,仅显示某位用户的相关信息。语法w[-fhlsuV][用户名称]参数说明:-f开启或关闭显示......
  • Linux uname 命令
    Linuxuname命令快速使用root@jdit:/home#uname-aLinuxjdit5.15.0-58-generic#64-UbuntuSMPThuJan511:43:13UTC2023x86_64x86_64x86_64GNU/Linux简介自动编程常用命令,因为要适配各种内核的操作系统Linuxuname(英文全拼:unixname)命令用于显示操作系统信息,......