33.Linux-實現U盤自動掛載(詳解)

来源:http://www.cnblogs.com/lifexy/archive/2017/11/24/7891883.html
-Advertisement-
Play Games

1.當我們每次插入u盤後,都會自動創鍵U盤的設備節點/dev/sda%d 這是因為裡面調用了device_create()實現的, busybox的mdev機制就會根據主次設備號等信息,在/dev下創建設備節點,如下圖所示: 而想使用上面的sda1設備節點,讀寫數據時,還需要使用mount /dev ...


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 = 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[]兩個字元串數組裡面存的環境變數參數來創建設備節點的

3.2接下來便在kobject_uevent_env()函數里添加列印信息, 然後重新燒內核:

 

 

3.3然後我們以註冊一個按鍵驅動為例 

輸入 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

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);
 ... ... 
}

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); //如果是卸載設備節點 }

從上面的代碼和註釋分析到,要使用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來卸載

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • max_connections 和 max_user_connections:max_connections預設是151,當MySQL與Apache Web伺服器一起使用時,可以提高性能。mysqld實際上允許max_connections + 1客戶端連接,額外的1個連接預留給具有超級許可權的帳戶使... ...
  • 上圖中即為redis中5種基本數據類型,在沒接觸過redis之前,聽過最多相關的字眼就是鍵值對key-value之類,立馬讓我想到了HashMap。在HashMap中,key和value的的數據類型都可以指定,value也可以是HashMap類型。而在這裡,redis的基本數據類型是針對的value ...
  • 昨天有幫助網友解決的個字元串截取的問題,《截取字元串中最後一個中文詞語(MS SQL)》http://www.cnblogs.com/insus/p/7883606.html 雖然實現了,但始終覺得代碼寫得很複雜。MS SQL Server中沒有一個如同C#一樣的函數LastIndexOf。沒有,我 ...
  • 1、zookeeper操作相關命令: 2、hdfs操作相關命令: 3、yarn操作相關命令: 4、hive相關操作命令: 5、hbase操作相關命令: ...
  • 工具:win10系統 orcl11G 問題:INS-13001環境不滿足最低要求 解決方法: 1 找到你解壓後的文件,點擊打開database文件夾 ==》stage文件夾 ==》cvu文件夾 ==》cvu_prereq.xml文件,用記事本打開cvu_prereq.xml文件; 2 在<CERTI ...
  • /etc/my.cnf 參考配置: [mysqld] #skip-grant-tables #default-character-set=utf8 #character-set-server=utf8 port= 3306 skip-external-locking key_buffer_size ...
  • [20171124]手工使用Seed_Database.dfb和Seed_Database.ctl建庫.txt--//昨天看yueli34的帖子,鏈接http://www.itpub.net/thread-2094530-1-1.html,註解與說明來自鏈接,感謝yueli34操作提示.--//自己 ...
  • 大概是用Win7的時候把IE關掉了,升級Win10之後就發現IE不見了,在Windows功能裡面也沒有;最近因為某些原因需要用到IE,還是用的虛擬機。 網上找到的方法普遍是執行命令:FORFILES /P %WINDIR%\servicing\packages /M Microsoft-Window ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...