1.当我们每次插入u盘后,都见面自行创键U盘的装备节点/dev/sda%d

1.当我们每次插入u盘后,都见面自行创键U盘的设备节点/dev/sda%d

当即是以中调用了device_create()实现之, busybox的mdev机制就见面根据程序设备号当消息,在/dev下创造设备节点,如下图所示:

旋即是坐内调用了device_create()实现之, busybox的mdev机制就会见依据程序设备号当消息,在/dev下创造设备节点,如下图所示:

 图片 1

 图片 2

如想使方面的sda1设备节点,读写多少经常,还需要使用mount /dev/sda1
 /mnt,来吊载u盘才行,会展示格外辛苦,如下图所示:

一旦想以方面的sda1配备节点,读写多少经常,还索要以mount /dev/sda1
 /mnt,来吊载u盘才行,会显煞是麻烦,如下图所示:

 图片 3

 图片 4

 

 

 

 

 

 

2.其实,可以在/etc/mdev.conf文件里在一行语句就能够实现自动装载u盘,也可于其间涉及任何与设施节点相关的从事

2.其实,可以在/etc/mdev.conf文件里进入一行语句就会落实全自动装载u盘,也可以中涉及别与设备节点相关的事

2.1而/etc/mdev.conf又是呀?

2.1而/etc/mdev.conf以是什么?

她是属mdev的一个部署文件,而mdev之前便讲讲了了,它要的法力是管理/dev目录底下的配备节点

它们是属mdev的一个部署文件,而mdev之前即叙了了,它要的职能是治本/dev目录底下的配备节点

当系统遭到发生自动注册设备节点的时节,mdev就会见调用/etc/mdev.conf一不好,
该文件可以实现与设备节点相关的行,比如自动装载usb,打印创建的设施节点信息等

当系统受来机关注册设备节点的下,mdev就见面调用/etc/mdev.conf一不成,
该文件可以实现同装备节点相关的转业,比如自动装载usb,打印创建的配备节点信息等

 

 

3.咱们首先来分析device_create(),是哪些来调用到/etc/mdev.conf的,后面还谈什么样使用mdev.conf(也得以一直跳过,直接扣下第4小节,如何运用)

3.我们先是来分析device_create(),是何许来调用到/etc/mdev.conf的,后面更称怎么使mdev.conf(也得以直接跳过,直接扣下第4小节,如何使用)

(PS:
之前创建字符设备节点用底class_device_create(),其实是和device_create功能差不多)

(PS:
之前创建字符设备节点用的class_device_create(),其实是暨device_create功能差不多)

3.1
device_create()最终调用了:device_create()->device_register()->device_add():

3.1
device_create()最终调用了:device_create()->device_register()->device_add():

device_create()->device_register()->device_add()函数如下所示:

int class_device_add(struct class_device *class_dev)
{
       ... ...
       kobject_uevent(&class_dev->kobj, KOBJ_ADD);         // KOBJ_ADD是一个枚举值
              //调用了kobject_uevent_env(kobj, action, NULL);              // action=KOBJ_ADD
}
device_create()->device_register()->device_add()函数如下所示:

int class_device_add(struct class_device *class_dev)
{
       ... ...
       kobject_uevent(&class_dev->kobj, KOBJ_ADD);         // KOBJ_ADD是一个枚举值
              //调用了kobject_uevent_env(kobj, action, NULL);              // action=KOBJ_ADD
}

3.2
device_create()->device_register()->device_add()->kobject_uevent_env()函数如下所示:

3.2
device_create()->device_register()->device_add()->kobject_uevent_env()函数如下所示:

int kobject_uevent_env(struct kobject *kobj, enum kobject_action action,char *envp_ext[])
{
       char **envp;
       char *buffer;
       char *scratch;
       int i = 0;
       ... ...

       /* 通过KOBJ_ADD获取字符串"add",所以action_string="add"  */
       action_string = action_to_string(action);              // action=KOBJ_ADD


       /* environment index */
       envp = kzalloc(NUM_ENVP * sizeof (char *), GFP_KERNEL);      //分配一个环境变量索引值

       /* environment values */
    buffer = kmalloc(BUFFER_SIZE, GFP_KERNEL);     //分配一个环境变量缓冲值      

/* event environemnt for helper process only */
/*设置环境变量*/
       envp[i++] = "HOME=/";
       envp[i++] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
       scratch = buffer;
       envp [i++] = scratch;
       scratch += sprintf(scratch, "ACTION=%s", action_string) + 1;  //"ACTION= add"
       envp [i++] = scratch;
       scratch += sprintf (scratch, "DEVPATH=%s", devpath) + 1;
       envp [i++] = scratch;
       scratch += sprintf(scratch, "SUBSYSTEM=%s", subsystem) + 1;
       ... ...
       /*调用应用程序,比如mdev*/
       if (uevent_helper[0]) {
            char *argv [3];
              argv [0] = uevent_helper;       // uevent_helper[]= "/sbin/hotplug";
              argv [1] = (char *)subsystem;
              argv [2] = NULL;
              call_usermodehelper (argv[0], argv, envp, 0);        //调用应用程序,根据传入的环境变量参数来创建设备节点
       }
}
int kobject_uevent_env(struct kobject *kobj, enum kobject_action action,char *envp_ext[])
{
       char **envp;
       char *buffer;
       char *scratch;
       int i = 0;
       ... ...

       /* 通过KOBJ_ADD获取字符串"add",所以action_string="add"  */
       action_string = action_to_string(action);              // action=KOBJ_ADD


       /* environment index */
       envp = kzalloc(NUM_ENVP * sizeof (char *), GFP_KERNEL);      //分配一个环境变量索引值

       /* environment values */
    buffer = kmalloc(BUFFER_SIZE, GFP_KERNEL);     //分配一个环境变量缓冲值      

/* event environemnt for helper process only */
/*设置环境变量*/
       envp[i++] = "HOME=/";
       envp[i++] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
       scratch = buffer;
       envp [i++] = scratch;
       scratch += sprintf(scratch, "ACTION=%s", action_string) + 1;  //"ACTION= add"
       envp [i++] = scratch;
       scratch += sprintf (scratch, "DEVPATH=%s", devpath) + 1;
       envp [i++] = scratch;
       scratch += sprintf(scratch, "SUBSYSTEM=%s", subsystem) + 1;
       ... ...
       /*调用应用程序,比如mdev*/
       if (uevent_helper[0]) {
            char *argv [3];
              argv [0] = uevent_helper;       // uevent_helper[]= "/sbin/hotplug";
              argv [1] = (char *)subsystem;
              argv [2] = NULL;
              call_usermodehelper (argv[0], argv, envp, 0);        //调用应用程序,根据传入的环境变量参数来创建设备节点
       }
}

起点的代码和注释来拘禁,最终经*argv[],
*envp[]有数单字符串数组里面存的环境变量参数来创造设备节点的

从者的代码和注释来拘禁,最终经*argv[],
*envp[]少独字符串数组里面存的环境变量参数来创造设备节点的

3.2连着下去便以kobject_uevent_env()函数里上加打印信息,
然后再也烧内核:

3.2连接下去就是在kobject_uevent_env()函数里添加打印信息,
然后更烧内核:

 图片 5

 图片 6

 

 

3.3然后我们坐登记一个按键驱动为例 

3.3然后我们因为登记一个按键驱动为例 

输入 insmod
key.ko,打印了以下语句:

输入 insmod
key.ko,打印了以下语句:

class_device: argv[0]=/sbin/mdev                 //调用mdev

class_device: argv[1]=sixth_dev                      //类名

class_device: envp[0]=HOME=/

class_device: envp[1]=PATH=/sbin:/bin:/usr/sbin:/usr/bin

class_device: envp[2]=ACTION=add             //add:表示添加设备节点,  若=remove:表示卸载设备节点

class_device: envp[3]=DEVPATH=/class/sixth_dev/buttons   //设备的路径

class_device: envp[4]=SUBSYSTEM=sixth_dev                //类名

class_device: envp[5]=SEQNUM=745

class_device: envp[6]=MAJOR=252                          //主设备号

class_device: envp[7]=MINOR=0
class_device: argv[0]=/sbin/mdev                 //调用mdev

class_device: argv[1]=sixth_dev                      //类名

class_device: envp[0]=HOME=/

class_device: envp[1]=PATH=/sbin:/bin:/usr/sbin:/usr/bin

class_device: envp[2]=ACTION=add             //add:表示添加设备节点,  若=remove:表示卸载设备节点

class_device: envp[3]=DEVPATH=/class/sixth_dev/buttons   //设备的路径

class_device: envp[4]=SUBSYSTEM=sixth_dev                //类名

class_device: envp[5]=SEQNUM=745

class_device: envp[6]=MAJOR=252                          //主设备号

class_device: envp[7]=MINOR=0

3.4结尾这些参数根据/sbin/mdev就进了busybox的mdev.c的mdev_main()函数里:

3.4最终这些参数根据/sbin/mdev就进去了busybox的mdev.c的mdev_main()函数里:

int mdev_main(int argc, char **argv)
{
... ...
action = getenv("ACTION");           //获取传进来的执行参数,它等于“add”,则表示创建设备节点
env_path = getenv("DEVPATH");      //获取设备的路径“/class/sixth_dev/buttons”
sprintf(temp, "/sys%s", env_path);   //指定temp (真正设备路径)为“/sys/class/sixth_dev/buttons”

if (!strcmp(action, "remove"))           //卸载设备节点
                    make_device(temp, 1);

else if (!strcmp(action, "add")) {       //创建设备节点
                     make_device(temp, 0);
 ... ... 
}
int mdev_main(int argc, char **argv)
{
... ...
action = getenv("ACTION");           //获取传进来的执行参数,它等于“add”,则表示创建设备节点
env_path = getenv("DEVPATH");      //获取设备的路径“/class/sixth_dev/buttons”
sprintf(temp, "/sys%s", env_path);   //指定temp (真正设备路径)为“/sys/class/sixth_dev/buttons”

if (!strcmp(action, "remove"))           //卸载设备节点
                    make_device(temp, 1);

else if (!strcmp(action, "add")) {       //创建设备节点
                     make_device(temp, 0);
 ... ... 
}

3.5说到底调用mdev_main
()->make_device()函数来创造/卸载设备节点,该函数如下所示:

3.5末调用mdev_main
()->make_device()函数来创造/卸载设备节点,该函数如下所示:

static void make_device(char *path, int delete) //delete=0:创建, delete=1:卸载
{
       /*判断创建的设备节点是否是有效的设备*/
       if (!delete) {
              strcat(path, "/dev");
              len = open_read_close(path, temp + 1, 64);
              *temp++ = 0;
              if (len < 1) return;
       }

device_name = bb_basename(path);    //通过设备路径,来获取要创建/卸载的设备节点名称
                      //例: path =“/sys /class/sixth_dev/buttons”,那么device_name=“buttons”



type = path[5]=='c' ? S_IFCHR : S_IFBLK;     //判断如果是在/sys/class/目录下,那么就是字符设备
                                              //因为块设备,是存在/sys/block/目录下的


/* 如果配置了支持mdev.conf选项,那么就解析里边内容并执行   */
 if (ENABLE_FEATURE_MDEV_CONF) { 
       /* mmap the config file */
fd = open("/etc/mdev.conf", O_RDONLY);     //调用/etc/mdev.conf配置文件

      ... ...         //开始操作 mdev.conf配置文件
}



       if (!delete) {                  //如果是创建设备节点

              if (sscanf(temp, "%d:%d", &major, &minor) != 2) return;   //获取主次设备号

        /*调用mknod ()创建字符设备节点*/
if (mknod(device_name, mode | type, makedev(major, minor)) && errno != EEXIST)
                     bb_perror_msg_and_die("mknod %s", device_name);


              if (major == root_major && minor == root_minor)
                     symlink(device_name, "root");

              /*若配置了支持mdev.conf选项,则调用chown命令来改变属主,默认uid和gid=0 */
              if (ENABLE_FEATURE_MDEV_CONF) chown(device_name, uid, gid);
}

     if (delete) unlink(device_name);           //如果是卸载设备节点
}
static void make_device(char *path, int delete) //delete=0:创建, delete=1:卸载
{
       /*判断创建的设备节点是否是有效的设备*/
       if (!delete) {
              strcat(path, "/dev");
              len = open_read_close(path, temp + 1, 64);
              *temp++ = 0;
              if (len < 1) return;
       }

device_name = bb_basename(path);    //通过设备路径,来获取要创建/卸载的设备节点名称
                      //例: path =“/sys /class/sixth_dev/buttons”,那么device_name=“buttons”



type = path[5]=='c' ? S_IFCHR : S_IFBLK;     //判断如果是在/sys/class/目录下,那么就是字符设备
                                              //因为块设备,是存在/sys/block/目录下的


/* 如果配置了支持mdev.conf选项,那么就解析里边内容并执行   */
 if (ENABLE_FEATURE_MDEV_CONF) { 
       /* mmap the config file */
fd = open("/etc/mdev.conf", O_RDONLY);     //调用/etc/mdev.conf配置文件

      ... ...         //开始操作 mdev.conf配置文件
}



       if (!delete) {                  //如果是创建设备节点

              if (sscanf(temp, "%d:%d", &major, &minor) != 2) return;   //获取主次设备号

        /*调用mknod ()创建字符设备节点*/
if (mknod(device_name, mode | type, makedev(major, minor)) && errno != EEXIST)
                     bb_perror_msg_and_die("mknod %s", device_name);


              if (major == root_major && minor == root_minor)
                     symlink(device_name, "root");

              /*若配置了支持mdev.conf选项,则调用chown命令来改变属主,默认uid和gid=0 */
              if (ENABLE_FEATURE_MDEV_CONF) chown(device_name, uid, gid);
}

     if (delete) unlink(device_name);           //如果是卸载设备节点
}

于者的代码和注释分析到,要利用mdev.conf配置文件,还待配备busybox的menuconfig,
使mdev支持mdev.conf选项才行

从上面的代码和注释分析及,要运mdev.conf配置文件,还欲配置busybox的menuconfig,
使mdev支持mdev.conf选项才行

正如图,进入busybox目录,然后输入make
menuconfig,发现我们既配备了了该选项了

如下图,进入busybox目录,然后输入make
menuconfig,发现我们早已配备了了该选项了

 图片 7

 图片 8

 

 

 

 

 

 

4.接下来,便来看看哪些以mdev.conf, 
参考busybox-1.7.0/docs/mdev.txt文档

4.接下来,便来看望哪下mdev.conf, 
参考busybox-1.7.0/docs/mdev.txt文档

使方式如下所示:

动方法如下所示:

the format:

the format:

       <device
regex
> <uid>:<gid> <octal
permissions
> [<@|$|*>
<command>]

       <device
regex
> <uid>:<gid> <octal
permissions
> [<@|$|*>
<command>]

The special characters
have the meaning:

The special characters
have the meaning:

@ Run after
creating the device.

@ Run after
creating the device.

$ Run before
removing the device.

$ Run before
removing the device.

* Run both after
creating and before removing the device.

* Run both after
creating and before removing the device.

大约就是是:

大约就是:

安排文件格式:

部署文件格式:

<device regex> <uid>:<gid> <octal permissions> [<@|$|*> <command>]  
<device regex> <uid>:<gid> <octal permissions> [<@|$|*> <command>]  

依次参数代表的义如下:  

逐一参数代表的意思如下:  

device regex:

device regex:

正则表达式,来抒发哪一个装置 ,正则表达式讲解链接:https://deerchao.net/tutorials/regex/regex.htm

正则表达式,来发挥哪一个装备 ,正则表达式讲解链接:https://deerchao.net/tutorials/regex/regex.htm

uid: 

uid: 

owner       (uid,gid:注册设备节点时,就会见给chown命令调用,来转设备的属主,默认都填0即可)

owner       (uid,gid:注册设备节点时,就会让chown命令调用,来改变设备的属主,默认都填0即可)

gid: 

gid: 

组ID  

组ID  

octal permissions:

octal permissions:

盖八进制表示的权位值,会受chmod命令调用,来改设备的访问权限,默认填660即可

坐八进制表示的权值,会吃chmod命令调用,来改变设备的访权限,默认填660即可

@
创设备节点之后执行命令  

@
始建设备节点之后执行命令  

$  :
 
删除设备节点前执行命令  

$  :
 
剔除设备节点前执行命令  

*  
创办设备节点之后 和 删除设备节点前 执行命令  

*  
缔造设备节点之后 和 删除设备节点前 执行命令  

command
倘尽之一声令下  

command
比方实行的下令  

 

 

5.接下来就来行使mdev.conf,实现u盘自动装载

5.接下来就是来用mdev.conf,实现u盘自动装载

vi /etc/mdev.conf

vi /etc/mdev.conf

添加以下一句子:

增长以下一词:

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

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

 

 



[1-9] : 匹配1~9的数字,

[1-9] : 匹配1~9的数字,


 :  再次匹配同差或重频繁


 :  重新匹配同软还是更累

$ACTION==”add”   :代表注册设备节点,否则便是收回设备节点

$ACTION==”add”   :表示注册设备节点,否则就是是取消设备节点

/dev/$MDEV      :意味着如创造/注销的深设备节点

/dev/$MDEV      :代表一旦开创/注销的良设备节点



 

 

故而当我们插上u盘,自动创建了/dev/sda1不时,mdev就会跻身/etc/mdev.conf配置文件,然后实施mount
/dev/
命令,即可自动装载U盘,一般来说图所示:

之所以当我们插上u盘,自动创建了/dev/sda1常常,mdev就会进/etc/mdev.conf配置文件,然后实施mount
/dev/
命令,即可自动装载U盘,正如图所示:

 图片 9

 图片 10

输入ls
/dev/sda1
 -l,可以见见都是由此mdev.conf里安排信息来创造的装置节点,如下图所示:

输入ls
/dev/sda1
 -l,可以观看都是由此mdev.conf里部署信息来创造的设备节点,如下图所示:

图片 11

图片 12

只要取出u盘时,同样自动umount
 /mnt来卸载

如果取出u盘时,同样自动umount
 /mnt来卸载