zoukankan      html  css  js  c++  java
  • Linux下的device_create创建字符设备节点流程

      对于字符设备驱动,当file_operations注册好了之后,这只是实现了该驱动的内部功能,我们还要向用户提供操作接口,也就是在/dev/目录下创建字符设备节点,其中device_create函数就用于实现该功能。

      创建设备节点是device_create的功能之一,下面主要分析该功能的主要流程。

    以下基于Linux2.6.32.2

     device_create函数分析:  

    device_create        /*creates a device and registers it with sysfs*/

        device_create_vargs

            device_register

                device_add

                    kobject_uevent(&dev->kobj, KOBJ_ADD);

                        kobject_uevent_env(kobj, action, NULL);    /*send an uevent with environmental data*/

                            if (uevent_helper[0]){

                            ...

                            call_usermodehelper(argv[0], argv,env->envp, UMH_WAIT_EXEC);}

    其中kobject_uevent_env是实现该功能的主要函数

    该函数功能分两部分:

    1.分配设置环境变量env:

      env = kzalloc(sizeof(struct kobj_uevent_env), GFP_KERNEL);      //分配环境变量

      add_uevent_var(env, "ACTION=%s", action_string);           //env->envp[0] = ACTION=add  如果是删除设备的时候该值就是remove,

      add_uevent_var(env, "DEVPATH=%s", devpath);              //env->envp[1] = DEVPATH=/devices/virtual/hello/hello0

      add_uevent_var(env, "SUBSYSTEM=%s", subsystem);          //env->envp[2] = SUBSYSTEM=hello

      uevent_ops->uevent(kset, kobj, env);                   //env->envp[3] = MAJOR=253

                                            //env->envp[4] = MINOR=0

                                            //env->envp[5] = DEVNAME=hello0

      add_uevent_var(env, "SEQNUM=%llu", (unsigned long long)seq);     //env->envp[6] = SEQNUM=582

      add_uevent_var(env, "HOME=/");                     //env->envp[7] = HOME=/

      add_uevent_var(env,"PATH=/sbin:/bin:/usr/sbin:/usr/bin");        //env->envp[8] = PATH=/sbin:/bin:/usr/sbin:/usr/bin

    2.设置完环境变量后

      if (uevent_helper[0]){    //如果有该参数(该参数实际上是mdev入口/sbin/mdev,因为在/etc/init.d/rcS中:echo /sbin/mdev > /proc/sys/kernel/hotplug

               ...

               call_usermodehelper(argv[0], argv,env->envp, UMH_WAIT_EXEC);}    //调用mdev,然后mdev会根据先前设置的环境变量进行处理

    测试:

    如果在call_usermodehelper函数之前添加打印语句:

      int i=0;

      printk("Testing: uevent_helper = %s\n",uevent_helper);

      for(;env->envp[i];i++)
        printk("env->envp[%d] = %s\n",i,env->envp[i]);

    就会在每次运行到函数kobject_uevent_env时都会打印uevent_helper跟环境变量

    例子如下:

      Testing : uevent_helper = /sbin/mdev

      env->envp[0] = ACTION=add
      env->envp[1] = DEVPATH=/devices/virtual/hello/hello0
      env->envp[2] = SUBSYSTEM=hello
      env->envp[3] = MAJOR=253
      env->envp[4] = MINOR=0
      env->envp[5] = DEVNAME=hello0
      env->envp[6] = SEQNUM=582
      env->envp[7] = HOME=/
      env->envp[8] = PATH=/sbin:/bin:/usr/sbin:/usr/bin

    kobject_uevent_env函数最后调用了mdev,mdev的入口函数在busybox的mdev_main

    mdev_main

        if (argv[1] && !strcmp(argv[1], "-s"))    //先判断参数1是否为-s,如果为-s则表明mdev为开机执行的情况(mdev -s位于/etc/init.d/rcS中)

        else

        getenv    /*提取各个环境变量*/

        make_device  /*根据action创建设备*/

            /*对于设备,当我们创建其节点时,我们可以通过配置文件进行配置

             *该配置文件位于/etc/mdev.conf              

             *            设备名称正则表达式用户id   组id         节点属性    创建的设备节点路径        shell命令   

             *配置方式为<device regex> <uid>:<gid> <octal permissions> [=path] [@|$|*<command>]

             *配置的帮助文件为busybox下的mdev.txt

             */

            parser = config_open2("/etc/mdev.conf", fopen_for_read);    /*打开/etc/mdev.conf文件*/

            while (config_read(parser, tokens, 4, 3, "# \t", PARSE_NORMAL))  /*分析mdev.conf文件内容,并执行相关操作command*/

            {...}

            mknod(device_name, mode | type, makedev(major, minor))     /*调用mknod进行节点创建*/

  • 相关阅读:
    Unity基础:AR(增强现实)的学习
    Fire Balls 04——平台组合,场景的美化
    Fire Balls 12——UI界面的制作
    Fire Balls 11——修正游戏的BUG
    Unity使用Rider作为IDE的体验
    Unity 5 使用Roslyn编译器支持C# 7
    MySQL 5.5主从复制(Replication)
    使用libcurl的正确姿势
    U盘安装Ubuntu Server 14.04
    arguments介绍(二)
  • 原文地址:https://www.cnblogs.com/TaigaCon/p/2804307.html
Copyright © 2011-2022 走看看