• uevent机制


    uevent, user space event. 内核与用户空间的一种通信机制,基于netlink机制,主要用于设备驱动模型,例如热插拔。

    1、调用/sbin/mdev的流程分析

    在驱动程序中经常出现class_device_create这个函数,它用来在/dev目录下创建各个设备的设备节点,那么,这个是怎么实现的呢?下面就来分析这个过程的实现,直接进到class_device_create函数中层层分析它。

    class_device_create
        class_device_register
            class_device_add
                kobject_uevent(&class_dev->kobj, KOBJ_ADD);
                    kobject_uevent_env(kobj, action, NULL);
                        // action_string  = "add";
                        action_string = action_to_string(action);
                        /* 分配、保存环境变量的内存 */
                        /* environment values */
                        buffer = kmalloc(BUFFER_SIZE, GFP_KERNEL);
                        
                        /* 设置环境变量 */
                        nvp [i++] = scratch;
                        scratch += sprintf(scratch, "ACTION=%s", action_string) + 1;
                        envp [i++] = scratch;
                        scratch += sprintf (scratch, "DEVPATH=%s", devpath) + 1;
                        envp [i++] = scratch;
                        scratch += sprintf(scratch, "SUBSYSTEM=%s", subsystem) + 1;
    
                        /* 调用应用程序:比如mdev */
                        /* 在/etc/init.d/rcS 中的echo /sbin/mdev > /proc/sys/kernel/hotplug指定了应用程序*/
                        argv [0] = uevent_helper;    // = "/sbin/mdev"
                        argv [1] = (char *)subsystem;
                        argv [2] = NULL;
                        call_usermodehelper (argv[0], argv, envp, 0);

    从上面的调用关系可以看出,最终内核会调用用户空间的/sbin/mdev程序,并且使用该程序的环境变量。

    2、mdev源码分析

    接下来看到busy_box下的mdev机制的实现,直接看到mdev.c文件,列出调用关系:

    mdev_main
        temp = "/sys/class/buttons/buttons"
        make_device(temp, 0);
            /* 确定设备文件名,类型,主设备号,次设备号 */
            path = "/sys/class/buttons/buttons"
            device_name = bb_basename(path); = "buttons"
            type = path[5]=='c' ? S_IFCHR : S_IFBLK;  // ='c'是字符设备节点
            
            根据 "/sys/class/buttons/buttons/dev"的内容确定主次设备号
            mknod(device_name, mode | type, makedev(major, minor)

    从上面的调用关系可以看出mdev最终通过mknod生成了设备节点

    3、利用mdev机制实现U盘的挂接

    分析mdev源码可以知道,它还可以根据/etc/mdev.conf这个配置文件来执行某个命令,这个文件的格式如下:

    mdev.conf的格式:
    <device regex> <uid>:<gid> <octal permissions> [<@|$|*> <command>]

    每个字段的含义如下:

    device regex:正则表达式,表示哪一个设备
    uid:owner
    gid:组id
    octal permissions:以八进制表示的属性
    @ :创建设备节点之后执行命令    
    $: 删除设备节点之前执行命令
    * :创建设备节点之后执行命令    和   删除设备节点之前执行命令
    command:要执行的命令

    正则表达式的介绍如下:

    正则表达式:
    1、在电脑上查文件,*.c(*表示通配符,表示任意字符)
    2、用正则表达式
        .表示任意字符(换行符除外)
        *表示重复0次或更多次
        +重复1次或更多次
        ?重复0次或1次
        [...]表示中括号里面的字符的某一个

    假设需要自动挂载U盘,它的/etc/mdev.conf可以这么写:

    sda[1-9]+ 0:0 777 * if [ $ACTION = "add" ]; then mount /dev/$MDEV /mnt;else umount /mnt; fi

    其中sda[1-9]+表示sda1-sda9中的一个或多个。后面跟着shell命令,如果是有U盘加载的话,那么挂接到/mnt上,否则的话,就卸载。

    当然也可以把shell命令写成脚本的形式,脚本存放在/bin/add_remove_udisk.sh

    sda[1-9]+ 0:0 777 * /bin/add_remove_udisk.sh
    
    /bin/add_remove_udisk.sh
    #!/bin/sh
    if [ $ACTION = "add" ]; 
    then 
        mount /dev/$MDEV /mnt;
    else 
        umount /mnt; 
    fi
  • 相关阅读:
    HDU 2089 不要62 【数位dp】
    HDU 3507 Print Article(dp+斜率优化)
    HDU 1078 FatMouse and Cheese【记忆化搜索】
    codeforces 366C Dima and Salad 【限制性01背包】
    HDU
    HDU 2844 Coins 【多重背包】(模板)
    hdu 2167 方格取数 【状压dp】(经典)
    poj 1160 Post Office 【区间dp】
    Poj
    HDU 1542 矩形面积并【离散化+线段树+扫描线】
  • 原文地址:https://www.cnblogs.com/andyfly/p/11305454.html
Copyright © 2020-2023  润新知