浅谈Linux 中字符设备的注册

Linux中字符设备的注册过程是比较简单的。我们通常可以调用misc_register()函数来注册一个字符设备。Misc设备是一种字符设备,通过该设备可以将fops请求转发给注册的misc设备,从而实现字符设备的功能。用户调用该接口注册Misc字符设备时,可以动态分配设备Minor号,当获取Minor号之后调用class_simple_device_add()或者device_create()函数完成字符设备的创建。Misc字符设备注册函数如下所示:

int misc_register(struct miscdevice * misc)
{
    struct miscdevice *c;
    dev_t dev;
    int err = 0;  

    INIT_LIST_HEAD(&misc->list);  

    mutex_lock(&misc_mtx);      //获取misc设备信号量
    list_for_each_entry(c, &misc_list, list) {  //检查设备是否已经存在
        if (c->minor == misc->minor) {
            mutex_unlock(&misc_mtx);
            return -EBUSY;          //如果设备存在,直接返回
        }
    }  

    if (misc->minor == MISC_DYNAMIC_MINOR) {    //动态分配分配minor号
        int i = DYNAMIC_MINORS;
        while (--i >= 0)
            if ( (misc_minors[i>>3] & (1 << (i&7))) == 0)
                break;
        if (i<0) {
            mutex_unlock(&misc_mtx);
            return -EBUSY;
        }
        misc->minor = i;
    }  

    if (misc->minor < DYNAMIC_MINORS)
        misc_minors[misc->minor >> 3] |= 1 << (misc->minor & 7);
    dev = MKDEV(MISC_MAJOR, misc->minor);  

    misc->this_device = device_create(misc_class, misc->parent, dev,
                      "%s", misc->name);        //创建字符设备(Misc设备)
    if (IS_ERR(misc->this_device)) {
        err = PTR_ERR(misc->this_device);
        goto out;
    }  

    /*
     * Add it to the front, so that later devices can "override"
     * earlier defaults
     */
    list_add(&misc->list, &misc_list);  //将设备保存至misc设备链中,设备访问时需要操作该链表
 out:
    mutex_unlock(&misc_mtx);
    return err;
}

需要注意的是2.6.12内核中创建系统设备时需要调用simple_device的接口class_simple_device_add()。在2.6.23中需要调用device_create()函数完成设备注册。在3.2内核中,simple_device的接口已经不存在了,所以必须调用device_create函数,另外,3.2内核不支持具有相同minor号的字符设备,在2.6.x内核中是支持的。

系统是如何完成fops函数调用的呢?回答这个问题需要分析Misc设备打开过程。在打开Misc设备驱动的时候,Misc设备驱动会根据访问设备的Minor号重定向fops函数集,该程序说明如下:

static int misc_open(struct inode * inode, struct file * file)
{
    int minor = iminor(inode);
    struct miscdevice *c;
    int err = -ENODEV;
    const struct file_operations *old_fops, *new_fops = NULL;  

    mutex_lock(&misc_mtx);  

    list_for_each_entry(c, &misc_list, list) {  //通过minor号来匹配对应的fops函数集
        if (c->minor == minor) {
            new_fops = fops_get(c->fops);
            break;
        }
    }  

    if (!new_fops) {
        mutex_unlock(&misc_mtx);
        request_module("char-major-%d-%d", MISC_MAJOR, minor);
        mutex_lock(&misc_mtx);  

        list_for_each_entry(c, &misc_list, list) {
            if (c->minor == minor) {
                new_fops = fops_get(c->fops);
                break;
            }
        }
        if (!new_fops)
            goto fail;
    }  

    err = 0;
    old_fops = file->f_op;
    file->f_op = new_fops;  //重定向fops函数
    if (file->f_op->open) {     //打开设备
        err=file->f_op->open(inode,file);
        if (err) {
            fops_put(file->f_op);
            file->f_op = fops_get(old_fops);
        }
    }
    fops_put(old_fops);
fail:
    mutex_unlock(&misc_mtx);
    return err;
}

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索file
, 函数
, is_err
, i2c设备驱动字符设备
, 字符
, 注册
, xenbus设备注册
, 字符设备
, minor
, 设备
, 字符设备驱动
major.minor
linux 注册字符设备、linux字符设备驱动、linux 字符设备、linux 字符设备文件、linux 字符设备读写,以便于您获取更多的相关知识。

时间: 2024-10-03 19:38:40

浅谈Linux 中字符设备的注册的相关文章

浅谈js中字符和数组一些基本算法题_javascript技巧

最近在刷 fcc的题,跟升级打怪一样,一关一关的过,还挺吸引我的.今天抽时间把 Basic Algorithm Scritping  这部分题做了,根据一些提示,还是比较简单的.有些题的处理方式 方法,我想值得借鉴.比如在项目中有时候要处理一个字符,如果想不到一些相关的方法,还挺费事的,所以,在此记录下来,如果以后遇到一些字符或者数组处理,可以来翻翻这篇文章,希望以此得到一些提示而不是去翻文档. 看到此博文的博友,有更好更简单的代码或者好的想法,请留言交流(我一直觉得只有学习别人的优秀代码才能进

浅谈Linux中的chattr与lsattr命令_Linux

PS:有时候你发现用root权限都不能修改某个文件,大部分原因是曾经用chattr命令锁定该文件了.chattr命令的作用很大,其中一些功能是由Linux内核版本来支持的,不过现在生产绝大部分跑的linux系统都是2.6以上内核了.通过chattr命令修改属性能够提高系统的安全性,但是它并不适合所有的目录.chattr命令不能保护/./dev./tmp./var目录.lsattr命令是显示chattr命令设置的文件属性. 这两个命令是用来查看和改变文件.目录属性的,与chmod这个命令相比,ch

【我的技术我做主】浅谈linux中umask值及其对应的文件权限

 最近刚好系统学习到linux文件权限这一块,在"umask值及其对应的文件权限"这一个问题上,找过视频看(老男孩老师的视频,强烈推荐),也看过鸟哥的书,当然也在网上找了找,发现计算方法都是多种多样的,但是个人觉得掌握一种就好了,看了各种方法,觉得其实大多数都是在找规律,不是找规律的又实在是太复杂,因此个人感觉不太好记,时间一长可能就忘记了,于是就根据自己的理解,做各种测试,发现有了如下更好的方法.(从理解和记忆的层次上更好的方法)  1.问题引出:设置umask为004与005时,创

浅谈Linux中ldconfig和ldd的用法_Linux

ldd 查看程序依赖库 ldd 作用:用来查看程式运行所需的共享库,常用来解决程式因缺少某个库文件而不能运行的一些问题. 示例:查看test程序运行所依赖的库: /opt/app/todeav1/test$ldd test libstdc++.so.6 => /usr/lib64/libstdc++.so.6 (0x00000039a7e00000) libm.so.6 => /lib64/libm.so.6 (0x0000003996400000) libgcc_s.so.1 => /

浅谈linux中的whoami与 who指令_Linux

whoami 功能说明: 显示用户名称 语法: whoami 补充说明: 显示自身的用户名称,本指令相当于执行  id -un 指令 whoami 与 who am i的区别 who这个命令重点在用来查看当前有那些用户登录到了本台机器上 who -m的作用和who am i的作用是一样的 who am i显示的是实际用户的用户名,即用户登陆的时候的用户ID.此命令相当于who -m whoami显示的是有效用户ID ,是当前操作用户的用户名 命令实践: [test@test~]$ whoami 

浅谈php中urlencode与rawurlencode的区别_php实例

前段时间说自己遇到了个<URL加号引发错误>的BUG,引起这个bug的原因就是自己在URL中使用了 urlencode 函数,该函数会把空格转换成加号,这样就导致URL解析出错,而空格只有转换成 %20 才可以可以正常解析,这时我们就需要使用 rawurlencode 函数. 下面就介绍一下 urlencode 函数与 rawurlencode 函数的区别: urlencode 函数: 返回字符串,此字符串中除了 -_. 之外的所有非字母数字字符都将被替换成百分号(%)后跟两位十六进制数,空格

浅谈PHP中Stream(流)_php技巧

流(stream)的概念源于UNIX中管道(pipe)的概念.在UNIX中,管道是一条不间断的字节流,用来实现程序或进程间的通信,或读写外围设备.外部文件等.根据流的方向又可以分为输入流和输出流,同时可以在其外围再套上其它流,比如缓冲流,这样就可以得到更多流处理方法. PHP里的流和Java里的流实际上是同一个概念,只是简单了一点.由于PHP主要用于Web开发,所以"流"这块的概念被提到的较少.如果有Java基础,对于PHP里的流就更容易理解了.其实PHP里的许多高级特性,比如SPL,

在 Linux 中管理设备

探索 /dev 目录可以让您知道如何直接访问到 Linux 中的设备. Linux 目录结构中有很多有趣的功能,这次我会讲到 /dev 目录一些迷人之处.在继续阅读这篇文章之前,建议你看看我前面的文章.Linux 文件系统,一切皆为文件,这两篇文章介绍了一些有趣的 Linux 文件系统概念.请先看看 - 我会等你看完再回来. -- 太好了 !欢迎回来.现在我们可以继续更详尽地探讨 /dev 目录. 设备文件 设备文件也称为设备特定文件.设备文件用来为操作系统和用户提供它们代表的设备接口.所有的 

浅谈 Linux 高负载的系统化分析

讲解 Linux Load 高如何排查的话题属于老生常谈了,但多数文章只是聚焦了几个点,缺少整体排查思路的介绍.所谓 "授人以鱼不如授人以渔".本文试图建立一个方法和套路,来帮助读者对 Load 高问题排查有一个更全面的认识. 从消除误解开始 没有基线的 Load,是不靠谱的 Load 从接触 Unix/Linux 系统管理的第一天起,很多人就开始接触 System Load Average 这个监控指标了,然而,并非所有人都知道这个指标的真正含义.一般说来,经常能听到以下误解: Lo