Android的儲存系統—Vold與MountService分析(二),voldmountservice

來源:互聯網
上載者:User

Android的儲存系統—Vold與MountService分析(二),voldmountservice

Android的儲存系統(二)

回顧:前貼主要分析了Android儲存系統的架構和原理圖,簡要的介紹了整個從Kernel-->Vold-->上層MountService之間的資料轉送流程,在這樣的基礎上,我們開始今天的源碼分析!

【源碼分析】

1. Vold的main函數

  Vold也是通過init進程啟動,它在init.rc中的定義如下:

1 service vold /system/bin/vold2     class core3     socket vold stream 0660 root mount4     ioprio be 2

  Vold服務放到了core分組,這就意味著系統啟動時,它就會被init進程啟動。這裡定義的一個socket,主要用語Vold和Java層的MountService通訊。

   Vold模組的原始碼位於system/vold,我們看看入口函數main(),代碼如下:

1 int main() {2     VolumeManager *vm;3     CommandListener *cl;4     NetlinkManager *nm;56     SLOGI("Vold 2.1 (the revenge) firing up");7     8     mkdir("/dev/block/vold", 0755);                 // 建立vold目錄910    klog_set_level(6);1112    if (!(vm = VolumeManager::Instance())) {        // 建立VolumeManager對象13        exit(1);14    };15     16    if (!(nm = NetlinkManager::Instance())) {       // 建立NetlinkManager對象17        exit(1);18    };1922    cl = new CommandListener();                     // 建立CommandListener對象23    vm->setBroadcaster((SocketListener *) cl);      // 建立vm和cl的聯絡24    nm->setBroadcaster((SocketListener *) cl);      // 建立nm和cl的聯絡2526    if (vm->start()) {                              // 啟動VolumeManager27        exit(1);28    }2930    if (process_config(vm)) {                       // 建立檔案/fstab.xxx中定義的Volume對象31        SLOGE("Error reading configuration (%s)... continuing anyways", strerror(errno));32    }3334    cryptfs_pfe_boot();3536    if (nm->start()) {                              // 啟動NetlinkManager,會調用NetlinkManager的start()方法,它建立PF_NETLINK socket,並開啟線程從此socket中讀取資料37        exit(1);38    }3940    coldboot("/sys/block");                         // 冷啟動,建立/sys/block下的節點檔案4142    if (cl->startListener()) {                      // 開始監聽Framework的socket43        exit(1);44    }45    46    while(1) {                                      // 進入迴圈47        sleep(1000);                                // 主線程進入休眠48    }49
50 SLOGI("Vold exiting");51 exit(0);52 }

   main函數的主要工作是建立3個對象:VolumeManager、NetlinkManager和CommandListener,同時將CommandListener對象分別設定到了VolumeManager對象和NetlinkManager對象中。

  從前貼的架構圖中可以發現,CommandListener對象用於和Java層的NativeDaemonConnector對象進行socket通訊,因此,無論是VolumeManager對象還是NetlinkManager對象都需要擁有CommandListener對象的引用。

2. 監聽驅動發出的訊息—Vold的NetlinkManager對象

  NetlinkManager對象的主要工作是監聽驅動發出的uevent訊息。

  main()函數中調用NetlinkManager類的靜態函數Instance()來建立NetlinkManager對象,代碼如下:

1 NetlinkManager *NetlinkManager::Instance() {2       if (!sInstance)3           sInstance = new NetlinkManager();      // NetlinkManager對象通過靜態變數sInstance來引用,這意味著vold進程中只有一個NetlinkManager對象。4       return sInstance;5 }

  看下NetlinkManager的建構函式,代碼如下:

1 NetlinkManager::NetlinkManager() {2       mBroadcaster = NULL;3 }

  NetlinkManager的建構函式只是對mBroadcaster進行了初始化。我們可以發現main()函數中通過調用NetlinkManager的setBroadcaster()函數來給變數mBroadcaster重新賦值。

nm->setBroadcaster((SocketListener *) cl);

  main()函數還調用了NetlinkManager的start()函數,我們觀察一下NetlinkManager中的start()方法,代碼如下:

 1 int NetlinkManager::start() { 2      struct sockaddr_nl nladdr; 3      int sz = 64 * 1024; 4      int on = 1; 5  6      memset(&nladdr, 0, sizeof(nladdr)); 7      nladdr.nl_family = AF_NETLINK; 8      nladdr.nl_pid = getpid(); 9      nladdr.nl_groups = 0xffffffff;10      /*建立一個socket用於核心空間和使用者空間的非同步通訊,監控系統的hotplug事件*/11      if ((mSock = socket(PF_NETLINK,SOCK_DGRAM,NETLINK_KOBJECT_UEVENT)) < 0) {12          SLOGE("Unable to create uevent socket: %s", strerror(errno));13          return -1;14      }15      /*設定緩衝區大小為64KB*/16      if (setsockopt(mSock, SOL_SOCKET, SO_RCVBUFFORCE, &sz, sizeof(sz)) < 0) {17          SLOGE("Unable to set uevent socket SO_RCVBUFFORCE option: %s", strerror(errno));18          goto out;19      }20      /*設定允許 SCM_CREDENTIALS 控制訊息的接收*/21      if (setsockopt(mSock, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on)) < 0) {22          SLOGE("Unable to set uevent socket SO_PASSCRED option: %s", strerror(errno));23          goto out;24      }25      /*綁定 socket 地址*/26      if (bind(mSock, (struct sockaddr *) &nladdr, sizeof(nladdr)) < 0) {27          SLOGE("Unable to bind uevent socket: %s", strerror(errno));28          goto out;29      }30      /*利用新建立的socket執行個體化一個NetlinkHandler類對象用於監聽socket,NetlinkHandler繼承了類NetlinkListener,NetlinkListener又繼承了類SocketListener*/31      mHandler = new NetlinkHandler(mSock);32       if (mHandler->start()) {                                               // 啟動NetlinkHandler,調用NetlinkHandler的start()函數33           SLOGE("Unable to start NetlinkHandler: %s", strerror(errno));34           goto out;35      }36 37      return 0;38 39 out:40      close(mSock);41      return -1;42 }

   我們看一下NetlinkManager的家族關係,如:

上面的虛線為啟動時的調用流程:

  (1) class NetlinkManager(在其start函數中建立了NetlinkHandler對象,並把建立的socket作為參數)

  (2)class NetlinkHandler: public NetlinkListener(實現了onEvent)

  (3) class NetlinkListener : public SocketListener(實現了onDataAvailable)

  (4) class SocketListener(實現了runListener,在一個線程中通過select查看哪些socket有資料,通過調用onDataAvailable來讀取資料)。

總結:此貼主要分析了Vold的main()函數和NetlinkManager對象的源碼,通過源碼瞭解對象的建立時機和函數調用流程,下一貼會繼續從NetlinkHandler的start()方法深入分析,繼續源碼的學習,很快會與大家見面,歡迎大家批評指正,我們互相學習。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.