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
  • 前言 本文介紹一款使用 C# 與 WPF 開發的音頻播放器,其界面簡潔大方,操作體驗流暢。該播放器支持多種音頻格式(如 MP4、WMA、OGG、FLAC 等),並具備標記、實時歌詞顯示等功能。 另外,還支持換膚及多語言(中英文)切換。核心音頻處理採用 FFmpeg 組件,獲得了廣泛認可,目前 Git ...
  • OAuth2.0授權驗證-gitee授權碼模式 本文主要介紹如何筆者自己是如何使用gitee提供的OAuth2.0協議完成授權驗證並登錄到自己的系統,完整模式如圖 1、創建應用 打開gitee個人中心->第三方應用->創建應用 創建應用後在我的應用界面,查看已創建應用的Client ID和Clien ...
  • 解決了這個問題:《winForm下,fastReport.net 從.net framework 升級到.net5遇到的錯誤“Operation is not supported on this platform.”》 本文內容轉載自:https://www.fcnsoft.com/Home/Sho ...
  • 國內文章 WPF 從裸 Win 32 的 WM_Pointer 消息獲取觸摸點繪製筆跡 https://www.cnblogs.com/lindexi/p/18390983 本文將告訴大家如何在 WPF 裡面,接收裸 Win 32 的 WM_Pointer 消息,從消息裡面獲取觸摸點信息,使用觸摸點 ...
  • 前言 給大家推薦一個專為新零售快消行業打造了一套高效的進銷存管理系統。 系統不僅具備強大的庫存管理功能,還集成了高性能的輕量級 POS 解決方案,確保頁面載入速度極快,提供良好的用戶體驗。 項目介紹 Dorisoy.POS 是一款基於 .NET 7 和 Angular 4 開發的新零售快消進銷存管理 ...
  • ABP CLI常用的代碼分享 一、確保環境配置正確 安裝.NET CLI: ABP CLI是基於.NET Core或.NET 5/6/7等更高版本構建的,因此首先需要在你的開發環境中安裝.NET CLI。這可以通過訪問Microsoft官網下載並安裝相應版本的.NET SDK來實現。 安裝ABP ...
  • 問題 問題是這樣的:第三方的webapi,需要先調用登陸介面獲取Cookie,訪問其它介面時攜帶Cookie信息。 但使用HttpClient類調用登陸介面,返回的Headers中沒有找到Cookie信息。 分析 首先,使用Postman測試該登陸介面,正常返回Cookie信息,說明是HttpCli ...
  • 國內文章 關於.NET在中國為什麼工資低的分析 https://www.cnblogs.com/thinkingmore/p/18406244 .NET在中國開發者的薪資偏低,主要因市場需求、技術棧選擇和企業文化等因素所致。歷史上,.NET曾因微軟的閉源策略發展受限,儘管後來推出了跨平臺的.NET ...
  • 在WPF開發應用中,動畫不僅可以引起用戶的註意與興趣,而且還使軟體更加便於使用。前面幾篇文章講解了畫筆(Brush),形狀(Shape),幾何圖形(Geometry),變換(Transform)等相關內容,今天繼續講解動畫相關內容和知識點,僅供學習分享使用,如有不足之處,還請指正。 ...
  • 什麼是委托? 委托可以說是把一個方法代入另一個方法執行,相當於指向函數的指針;事件就相當於保存委托的數組; 1.實例化委托的方式: 方式1:通過new創建實例: public delegate void ShowDelegate(); 或者 public delegate string ShowDe ...