詳解Linux實現(xiàn)U盤自動掛載(圖文教程)
1.當我們每次插入u盤后,都會自動創(chuàng)鍵U盤的設(shè)備節(jié)點/dev/sda%d
這是因為里面調(diào)用了device_create()實現(xiàn)的, busybox的mdev機制就會根據(jù)主次設(shè)備號等信息,在/dev下創(chuàng)建設(shè)備節(jié)點,如下圖所示:
而想使用上面的sda1設(shè)備節(jié)點,讀寫數(shù)據(jù)時,還需要使用mount /dev/sda1 /mnt,來掛載u盤才行,會顯得非常麻煩,如下圖所示:
2.其實,可以在/etc/mdev.conf文件里加入一行語句就能實現(xiàn)自動裝載u盤,也可以在里面干其它與設(shè)備節(jié)點相關(guān)的事
2.1而/etc/mdev.conf又是什么?
它是屬于mdev的一個配置文件,而mdev之前就講過了,它主要的功能是管理/dev目錄底下的設(shè)備節(jié)點
當系統(tǒng)中有自動注冊設(shè)備節(jié)點的時候,mdev就會調(diào)用/etc/mdev.conf一次, 該文件可以實現(xiàn)與設(shè)備節(jié)點相關(guān)的事,比如自動裝載usb,打印創(chuàng)建的設(shè)備節(jié)點信息等
3.我們首先來分析device_create(),是如何來調(diào)用到/etc/mdev.conf的,后面再講如何使用mdev.conf(也可以直接跳過,直接看下面第4小節(jié),如何使用)
(PS: 之前創(chuàng)建字符設(shè)備節(jié)點用的class_device_create(),其實是和device_create功能差不多)
3.1 device_create()最終調(diào)用了:device_create()->device_register()->device_add():
device_create()- >device_register() ->device_add() 函數(shù)如下所示: int class_device_add(struct class_device *class_dev) { ... ... kobject_uevent(&class_dev->kobj, KOBJ_ADD); // KOBJ_ADD是一個枚舉值 //調(diào)用了kobject_uevent_env(kobj, action, NULL); // action=KOBJ_ADD }
3.2 device_create()->device_register()->device_add()->kobject_uevent_env()函數(shù)如下所示:
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); //分配一個環(huán)境變量索引值 /* environment values */ buffer = kmalloc(BUFFER_SIZE, GFP_KERNEL); //分配一個環(huán)境變量緩沖值 /* event environemnt for helper process only */ /*設(shè)置環(huán)境變量*/ 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; ... ... /*調(diào)用應(yīng)用程序,比如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); //調(diào)用應(yīng)用程序,根據(jù)傳入的環(huán)境變量參數(shù)來創(chuàng)建設(shè)備節(jié)點 } }
從上面的代碼和注釋來看,最終通過*argv[], *envp[]兩個字符串數(shù)組里面存的環(huán)境變量參數(shù)來創(chuàng)建設(shè)備節(jié)點的
3.2接下來便在kobject_uevent_env()函數(shù)里添加打印信息, 然后重新燒內(nèi)核:
3.3然后我們以注冊一個按鍵驅(qū)動為例
輸入 insmod key.ko,打印了以下語句:
class_device: argv[0]=/sbin/mdev //調(diào)用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:表示添加設(shè)備節(jié)點, 若=remove:表示卸載設(shè)備節(jié)點 class_device: envp[3]=DEVPATH=/class/sixth_dev/buttons //設(shè)備的路徑 class_device: envp[4]=SUBSYSTEM=sixth_dev //類名 class_device: envp[5]=SEQNUM=745 class_device: envp[6]=MAJOR=252 //主設(shè)備號 class_device: envp[7]=MINOR=0
3.4最終這些參數(shù)根據(jù)/sbin/mdev就進入了busybox的mdev.c的mdev_main()函數(shù)里:
int mdev_main(int argc, char **argv) { ... ... action = getenv("ACTION"); //獲取傳進來的執(zhí)行參數(shù),它等于“add”,則表示創(chuàng)建設(shè)備節(jié)點 env_path = getenv("DEVPATH"); //獲取設(shè)備的路徑“/class/sixth_dev/buttons” sprintf(temp, "/sys%s", env_path); //指定temp (真正設(shè)備路徑)為“/sys/class/sixth_dev/buttons” if (!strcmp(action, "remove")) //卸載設(shè)備節(jié)點 make_device(temp, 1); else if (!strcmp(action, "add")) { //創(chuàng)建設(shè)備節(jié)點 make_device(temp, 0); ... ... }
3.5最終調(diào)用mdev_main ()->make_device()函數(shù)來創(chuàng)建/卸載設(shè)備節(jié)點,該函數(shù)如下所示:
static void make_device(char *path, int delete) //delete=0:創(chuàng)建, delete=1:卸載 { /*判斷創(chuàng)建的設(shè)備節(jié)點是否是有效的設(shè)備*/ if (!delete) { strcat(path, "/dev"); len = open_read_close(path, temp + 1, 64); *temp++ = 0; if (len < 1) return; } device_name = bb_basename(path); //通過設(shè)備路徑,來獲取要創(chuàng)建/卸載的設(shè)備節(jié)點名稱 //例: path =“/sys /class/sixth_dev/buttons”,那么device_name=“buttons” type = path[5]=='c' ? S_IFCHR : S_IFBLK; //判斷如果是在/sys/class/目錄下,那么就是字符設(shè)備 //因為塊設(shè)備,是存在/sys/block/目錄下的 /* 如果配置了支持mdev.conf選項,那么就解析里邊內(nèi)容并執(zhí)行 */ if (ENABLE_FEATURE_MDEV_CONF) { /* mmap the config file */ fd = open("/etc/mdev.conf", O_RDONLY); //調(diào)用/etc/mdev.conf配置文件 ... ... //開始操作 mdev.conf配置文件 } if (!delete) { //如果是創(chuàng)建設(shè)備節(jié)點 if (sscanf(temp, "%d:%d", &major, &minor) != 2) return; //獲取主次設(shè)備號 /*調(diào)用mknod ()創(chuàng)建字符設(shè)備節(jié)點*/ 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選項,則調(diào)用chown命令來改變屬主,默認uid和gid=0 */ if (ENABLE_FEATURE_MDEV_CONF) chown(device_name, uid, gid); } if (delete) unlink(device_name); //如果是卸載設(shè)備節(jié)點 }
從上面的代碼和注釋分析到,要使用mdev.conf配置文件,還需要配置busybox的menuconfig, 使mdev支持mdev.conf選項才行
如下圖,進入busybox目錄,然后輸入make menuconfig,發(fā)現(xiàn)我們已經(jīng)配置過了該選項了
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>]
各個參數(shù)代表的含義如下:
deviceregex:
正則表達式,來表達哪一個設(shè)備,正則表達式講解鏈接:https://deerchao.net/tutorials/regex/regex.htm
uid:
owner (uid,gid:注冊設(shè)備節(jié)點時,就會被chown命令調(diào)用,來改變設(shè)備的屬主,默認都填0即可)
gid:
組ID
octalpermissions:
以八進制表示的權(quán)限值,會被chmod命令調(diào)用,來更改設(shè)備的訪問權(quán)限,默認填660即可
@ :創(chuàng)建設(shè)備節(jié)點之后執(zhí)行命令
$ : 刪除設(shè)備節(jié)點之前執(zhí)行命令
* :創(chuàng)建設(shè)備節(jié)點之后和刪除設(shè)備節(jié)點之前執(zhí)行命令
command :要執(zhí)行的命令
5.接下來便來使用mdev.conf,實現(xiàn)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的數(shù)字,
+ : 重復(fù)匹配一次或更多次
$ACTION=="add" :表示注冊設(shè)備節(jié)點,否則就是注銷設(shè)備節(jié)點
/dev/$MDEV :表示要創(chuàng)建/注銷的那個設(shè)備節(jié)點
所以當我們插上u盤,自動創(chuàng)建了/dev/sda1時,mdev便會進入/etc/mdev.conf配置文件,然后執(zhí)行mount /dev/ 命令,即可自動裝載U盤,如下圖所示:
輸入ls /dev/sda1 -l,可以看到都是通過mdev.conf里配置信息來創(chuàng)建的設(shè)備節(jié)點,如下圖所示:
而取出u盤時,同樣自動umount /mnt來卸載。
總結(jié)
以上所述是小編給大家介紹的Linux實現(xiàn)U盤自動掛載,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復(fù)大家的。在此也非常感謝大家對腳本之家網(wǎng)站的支持!
相關(guān)文章
完美解決eclipse中導(dǎo)入工程后中文注釋出現(xiàn)亂碼的問題
以下是對eclipse中導(dǎo)入工程后中文注釋出現(xiàn)亂碼的解決辦法進行了詳細的分析介紹,需要的朋友可以過來參考下2013-08-08解決Cent0S 6.7直接在/etc/resolv.conf文件下修改DNS地址重啟不生效問題
這篇文章主要介紹了解決Cent0S 6.7直接在/etc/resolv.conf文件下修改DNS地址重啟不生效問題 ,需要的朋友可以參考下2017-07-07Linux定時任務(wù)的設(shè)置及 crontab 配置指南
這篇文章主要介紹了Linux定時任務(wù)的設(shè)置及 crontab 配置指南,需要的朋友可以參考下2017-07-07