fuchsia devfs分析

devfs設備文件系統,主要負責fuchsia中管理的設備在本地文件系統中文件節點的呈現。其文件路徑爲“/dev”。
1.devfs目錄構建

devfs隨着devmgr進程的啓動而初始化。通過“devmgr::devfs_init”函數,初始化一個devfs目錄,主要兩點:
  1.class目錄樹的創建(包含所有ddk/protodefs.h文件中定義的不帶“PF_NOPUB”flag的協議);
  2.devfs的rpc“基礎設施”搭建(創建一對channel,在其中一端等待,另一端保存在全局變量g_devfs_root中,並按需傳遞給需要訪問devfs的進程)

devmgr中還會直接發佈(devfs_publish)misc、sys和test三個目錄到dev目錄下。
devfs_publish函數在發佈設備到相應目錄下之後還會通過ipc通知該目錄的watcher。

接着,devmgr通過調用devmgr_vfs_init函數,安裝/dev、/svc和/system目錄到devmgr進程的namespace中。

最後,在驅動程序的循環加載中發佈設備到相應目錄。

2.devfs的rpc處理

DcIostate繼承自AsyncLoopOwnedRpcHandler類,用於devfs的rpc請求處理。
在devmgr::devfs_init中會調用DcIostate::Create方法,實例化DcIostate類,並設置爲在devfs的本地端channel上等待。
當其他進程通過獲取的devfs遠端channel向devfs發送message時,DcIostate::HandleRpc會被調用,進而會調用DcIostate::DevfsFidlHandler對message進行處理。
目前支持的操作碼包括:
fuchsia_io_NodeCloneOrdinal :克隆指定patch的node節點;msg中會傳入一個client的handle,devfs會在此handle上等待後續消息處理
fuchsia_io_NodeDescribeOrdinal :獲取node info
fuchsia_io_DirectoryOpenOrdinal :open node節點,最終會調用ddk框架中設備的open方法
fuchsia_io_NodeGetAttrOrdinal : 獲取node的attr
fuchsia_io_DirectoryRewindOrdinal :Rewind,讀取的目錄路徑回到根目錄
fuchsia_io_DirectoryReadDirentsOrdinal :讀
fuchsia_io_DirectoryWatchOrdinal :添加監控(watcher)
fuchsia_io_DirectoryAdminQueryFilesystemOrdinal :獲取文件系統信息(返回“devfs”)
fuchsia_io_NodeIoctlOrdinal :遺留,不支持

需要注意的是,devfs只是提供設備句柄的clone、open以及其他一些屬性的獲取,而真正跟驅動設備的交互則是在設備的devhost中(open的時候會將client端的handle傳給設備devhost以建立數據通道)。也就是devfs只是管理與設備控制面的東西,而真正與設備驅動的數據面交互,則在devhost中

3.部分源碼註釋::
devmgr的main函數{
devmgr::devfs_init //入口;根據傳入的device,初始化一個devfs目錄(主要兩點:class目錄樹的創建;devfs的rpc基礎設施搭建)
    root_devnode = std::make_unique<Devnode>("");
    root_devnode->ino = 1;
    prepopulate_protocol_dirs
        devfs_mkdir(root_devnode.get(), "class") //創建class目錄(目錄關聯的device爲null),ino爲2
        【devfs_mkdir(class_devnode.get(), info.name)】//循環在class目錄下創建所有不帶“PF_NOPUB”flag的protocol節點;TODO:爲什麼只看到幾個?!
    zx::channel::create //兩個channel句柄:h0、h1
    DcIostate::Create(root_devnode.get(), dispatcher, &h0) //DcIostate類繼承自AsyncLoopOwnedRpcHandler,實現devfs的rpc處理
        std::make_unique<DcIostate>(dn)
        ios->set_channel(std::move(*ipc)); //設置等待對象爲channel——h0
        DcIostate::BeginWait //開始在channel上等待
    g_devfs_root = std::move(h1); //全局變量保存devfs的通信句柄
    
devfs_publish //調用三次,分別發佈misc、sys、test
    devfs_mknode
   【proto_dir //獲取設備對應的protocolID(代表設備發佈的協議,並在class目錄下創建相應文件節點)
    devfs_lookup //這裏查找、並從“000”~“999”中選出一個唯一的子node名字
    devfs_mknode //創建子node節點,並將原設備的link屬性設置爲此class子node節點
    】//如果是misc、sys及test的根設備會跳過這段
    devfs_advertise 
        devfs_notify //向watcher發送fuchsia_io_WATCH_EVENT_ADDED,通知其已經添加了設備節點(class和dev節點) //TODO:watcher在哪裏添加?

devmgr_vfs_init
    fdio_ns_get_installed //獲取安裝的根目錄“/”
    fdio_ns_bind //安裝/dev、/svc和/system目錄

}

發佈了79 篇原創文章 · 獲贊 28 · 訪問量 8萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章