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进行节点创建*/

  • 相关阅读:
    C# 文件类的操作---删除
    C#实现Zip压缩解压实例
    UVALIVE 2431 Binary Stirling Numbers
    UVA 10570 meeting with aliens
    UVA 306 Cipher
    UVA 10994 Simple Addition
    UVA 696 How Many Knights
    UVA 10205 Stack 'em Up
    UVA 11125 Arrange Some Marbles
    UVA 10912 Simple Minded Hashing
  • 原文地址:https://www.cnblogs.com/TaigaCon/p/2804307.html
Copyright © 2011-2022 走看看