33.Linux-实现U盘自动挂载(详解)
1.当我们每次插入u盘后,都会自动创键U盘的设备节点/dev/sda%d
这是因为里面调用了device_create()实现的, busybox的mdev机制就会根据主次设备号等信息,在/dev下创建设备节点,如下图所示:
而想使用上面的sda1设备节点,读写数据时,还需要使用mount /dev/sda1 /mnt,来挂载u盘才行,会显得非常麻烦,如下图所示:
2.其实,可以在/etc/mdev.conf文件里加入一行语句就能实现自动装载u盘,也可以在里面干其它与设备节点相关的事
2.1而/etc/mdev.conf又是什么?
它是属于mdev的一个配置文件,而mdev之前就讲过了,它主要的功能是管理/dev目录底下的设备节点
当系统中有自动注册设备节点的时候,mdev就会调用/etc/mdev.conf一次, 该文件可以实现与设备节点相关的事,比如自动装载usb,打印创建的设备节点信息等
3.我们首先来分析device_create(),是如何来调用到/etc/mdev.conf的,后面再讲如何使用mdev.conf(也可以直接跳过,直接看下面第4小节,如何使用)
(PS: 之前创建字符设备节点用的class_device_create(),其实是和device_create功能差不多)
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
}
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 = ;
... ... /* 通过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) + ; //"ACTION= add"
envp [i++] = scratch;
scratch += sprintf (scratch, "DEVPATH=%s", devpath) + ;
envp [i++] = scratch;
scratch += sprintf(scratch, "SUBSYSTEM=%s", subsystem) + ;
... ...
/*调用应用程序,比如mdev*/
if (uevent_helper[]) {
char *argv [];
argv [] = uevent_helper; // uevent_helper[]= "/sbin/hotplug";
argv [] = (char *)subsystem;
argv [] = NULL;
call_usermodehelper (argv[], argv, envp, ); //调用应用程序,根据传入的环境变量参数来创建设备节点
}
}
从上面的代码和注释来看,最终通过*argv[], *envp[]两个字符串数组里面存的环境变量参数来创建设备节点的
3.2接下来便在kobject_uevent_env()函数里添加打印信息, 然后重新烧内核:
3.3然后我们以注册一个按键驱动为例
输入 insmod key.ko,打印了以下语句:
class_device: argv[]=/sbin/mdev //调用mdev class_device: argv[]=sixth_dev //类名 class_device: envp[]=HOME=/ class_device: envp[]=PATH=/sbin:/bin:/usr/sbin:/usr/bin class_device: envp[]=ACTION=add //add:表示添加设备节点, 若=remove:表示卸载设备节点 class_device: envp[]=DEVPATH=/class/sixth_dev/buttons //设备的路径 class_device: envp[]=SUBSYSTEM=sixth_dev //类名 class_device: envp[]=SEQNUM= class_device: envp[]=MAJOR= //主设备号 class_device: envp[]=MINOR=
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, ); else if (!strcmp(action, "add")) { //创建设备节点
make_device(temp, );
... ...
}
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 + , );
*temp++ = ;
if (len < ) return;
} device_name = bb_basename(path); //通过设备路径,来获取要创建/卸载的设备节点名称
//例: path =“/sys /class/sixth_dev/buttons”,那么device_name=“buttons” type = path[]=='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) != ) 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选项才行
如下图,进入busybox目录,然后输入make menuconfig,发现我们已经配置过了该选项了
4.接下来,便来看看如何使用mdev.conf, 参考busybox-1.7.0/docs/mdev.txt文档
使用方法如下所示:
the format:
<device regex> <uid>:<gid> <octal permissions> [<@|$|*> <command>]
The special characters have the meaning:
@ Run after creating the device.
$ Run before removing the device.
* Run both after creating and before removing the device.
大概就是:
配置文件格式:
<device regex> <uid>:<gid> <octal permissions> [<@|$|*> <command>]
各个参数代表的含义如下:
device regex:
正则表达式,来表达哪一个设备 ,正则表达式讲解链接:https://deerchao.net/tutorials/regex/regex.htm
uid:
owner (uid,gid:注册设备节点时,就会被chown命令调用,来改变设备的属主,默认都填0即可)
gid:
组ID
octal permissions:
以八进制表示的权限值,会被chmod命令调用,来更改设备的访问权限,默认填660即可
@ : 创建设备节点之后执行命令
$ : 删除设备节点之前执行命令
* : 创建设备节点之后 和 删除设备节点之前 执行命令
command : 要执行的命令
5.接下来便来使用mdev.conf,实现u盘自动装载
vi /etc/mdev.conf
添加以下一句:
sda[1-9]+ 0:0 660 * if [ $ACTION = "add" ]; then mount /dev/$MDEV /mnt; else umount /mnt; fi
[1-9] : 匹配1~9的数字,
+ : 重复匹配一次或更多次
$ACTION=="add" :表示注册设备节点,否则就是注销设备节点
/dev/$MDEV :表示要创建/注销的那个设备节点
所以当我们插上u盘,自动创建了/dev/sda1时,mdev便会进入/etc/mdev.conf配置文件,然后执行mount /dev/ 命令,即可自动装载U盘,如下图所示:
输入ls /dev/sda1 -l,可以看到都是通过mdev.conf里配置信息来创建的设备节点,如下图所示:
而取出u盘时,同样自动umount /mnt来卸载
接下来下章来学习如何制作多分区U盘自动挂载:https://www.cnblogs.com/lifexy/p/10107310.html
33.Linux-实现U盘自动挂载(详解)的更多相关文章
- linux 实现U盘自动挂载
某些场景下,服务器可能没有必要的键盘等输入设备.屏幕等输出设备.此时需要在没有人为干预的情况下实现当插入U盘或者硬盘后自动挂载,并执行某些脚本动作.以下是我的实践过程. 必要组件 udev,udisk ...
- 48.Linux-普通U盘以及多分区U盘自动挂载
在上章学习33.Linux-实现U盘自动挂载(详解)后,只是讲解了普通U盘挂载,并没有涉及到多分区U盘,接下来本章来继续学习 1.多分区U盘和普通U盘区别 1)U盘插上只会创建一个/dev/sda文件 ...
- Linux基础知识之挂载详解(mount,umount及开机自动挂载)
Linux基础知识之挂载详解(mount,umount及开机自动挂载) 转载自:http://www.linuxidc.com/Linux/2016-08/134666.htm 挂载概念简述: 根文件 ...
- 二十三、uevnet机制和U盘自动挂载
一.uevent机制 在分析之前,我们首先要知道uevent作用是什么.在此我们先来看一个uevent机制的框架图: 该图片来自:Linux设备模型(3)_Uevent 通过图片我们可以确定ueven ...
- 什么是挂载?linux中挂载详解
目录 一:什么是挂载,linux中挂载详解 一:什么是挂载,linux中挂载详解 1.linux中'一切皆文件',所有文件都放置在以根目录为树根的树形目录结构中.在linux看来,任何硬件设备也都是文 ...
- Linux添加新硬盘自动挂载硬盘
Linux添加新硬盘自动挂载硬盘的具体步骤 1.插入新硬盘,启动Linux服务器,使用fdisk -l 查看硬盘 #fdisk -l Disk /dev/sdb: 1000.2 GB, 1000204 ...
- linux mount命令参数及用法详解
linux mount命令参数及用法详解 非原创,主要来自 http://www.360doc.com/content/13/0608/14/12600778_291501907.shtml. htt ...
- linux dd命令参数及用法详解---用指定大小的块拷贝一个文件(也可整盘备份)
linux dd命令参数及用法详解---用指定大小的块拷贝一个文件 日期:2010-06-14 点击:3830 来源: 未知 分享至: linux dd命令使用详解 dd 的主要 ...
- Linux设置程序开机自启动,系统命令chkconfig及linux /etc/rc.d/目录的详解
整理了linux下程序开启几种方式,转载相关博客做统一记录 <linux程序设置开机自启动>转载自:https://www.cnblogs.com/flcz/p/7691532.html ...
随机推荐
- Virgo标签打印
去年刚换新的公司,熟悉新的业务和代码,在修改公司打印标签的时候,感觉到无比烦躁与头痛.只因为不好维护,所有的标签打印,全部是GDI+绘制,每次修改微调,都只能全部运行才能看到效果.程序过大,编译过慢, ...
- 通信技术:SSE设计方案(一)--- 前端Server-Sent Events概念讲解和基础类库完善发布
好了,开篇还是要扯扯的,否则感觉这个技术讲的么有那么冻人,嗯,这个晚上是有点冷了,秋衣秋裤大家都该加起来了,反正我不帮你买,妹子除外,嘻嘻. 之前几篇博客,研究前端通信技术的第一层ajax技术,从最基 ...
- Appium-desktop安装与使用
Appium-desktop是什么? 项目描述: Appium Server and Inspector in Desktop GUIs for Mac, Windows, and Linux. Ap ...
- VCI_CAN二次开发摘机
1. 关于CAN滤波的设置的几个参数 PVCI_INIT_CONFIG结构,VCI_InitCAN函数调用时使用 AccCode: 验收码(左对齐) 帧过滤验收码.对经过屏蔽码过滤为"有关位 ...
- SQL Server Alwayson概念总结
一.alwayson概念 “可用性组” 针对一组离散的用户数据库(称为“可用性数据库” ,它们共同实现故障转移)支持故障转移环境. 一个可用性组支持一组主数据库以及一至八组对应的辅助数据库(包括一个主 ...
- 【转】Linux设备驱动--块设备(一)之概念和框架
原文地址:Linux设备驱动--块设备(一)之概念和框架 基本概念 块设备(blockdevice) --- 是一种具有一定结构的随机存取设备,对这种设备的读写是按块进行的,他使用缓冲区来存放暂时 ...
- MongoDB用户权限管理
创建用户账号: (roles参数指定了用户的角色以及这个账号授权的数据库,在同一个数据库中不能同时创建两个用户名相同的账号) Mongodb内置的用户角色: 数据库用户角色:read.readWrit ...
- LeetCode 252. Meeting Rooms (会议室)$
Given an array of meeting time intervals consisting of start and end times [[s1,e1],[s2,e2],...] (si ...
- ssm框架的整合
首先创建一个web工程,我这里使用的IDE为eclipse. 结果目录如下: 添加相关的jar包: 接下来是完成配置文件 首先我们先配置web.xml: <?xml version=" ...
- AngularJS学习篇(二十一)
AngularJS 动画 AngularJS 提供了动画效果,可以配合 CSS 使用. AngularJS 使用动画需要引入 angular-animate.min.js 库. <!doctyp ...