天天看點

【大話QT之五】Windows與Linux下檔案操作監控的實作

一、需求分析:

        随着渲染業務的不斷進行,資料傳輸漸漸成為影響業務時間最大的因素。究其原因就是因為資料傳輸耗費較長的時間。于是,依托于渲染業務的網盤開發逐漸成為迫切需要解決的需求。該網盤的實作和目前市場上網盤實作有一些的不同,主要在用戶端與伺服器端的操作需要雙向進行,即:使用者在用戶端的操作需要及時同步到伺服器端;在伺服器端作業渲染生成的檔案要及時同步到用戶端。即:使用者不在需要單獨的下載下傳資料,而是在作業運作的同時,渲染就過就會自動同步到用戶端,大大縮短了等待時間。當然,無論是在用戶端還是在服務端都面臨着一個問題,即:實作對檔案操作的監控,這裡的檔案操作包括:檔案(夾)建立、檔案(夾)删除、檔案(夾)重命名、檔案(夾)移動等操作。除此之外還要能夠同步用戶端檔案的修改操作,即:當使用者退出網盤後,修改了原有同步目錄中的檔案,當使用者再次啟動網盤時通過一次掃描與md5值的比較能缺确定出哪些檔案發生了改動,并将改動後的操作及時同步到服務端。這裡,先将windows(用戶端實作需要)與linux(服務端實作需要)下檔案監控的實作方法簡要概述。

二、檔案監控實作方法分析

      1> windows下檔案監控的實作

            windows下實作檔案監控的原理是利用shchangenotifyregister把指定的視窗添加到系統的消息監視鍊中,進而注冊視窗就可以接收到來自檔案系統或shell的通知了。在繼續向下說明之前,需要解釋一下windows外殼名字空間(shell name space)的概念。

            外殼名字空間是windows下的标準檔案系統,它大大擴充了dos檔案系統,形成了以”桌面“為根的單一檔案系統樹,原有的c、d盤等目錄樹變成了“我的電腦”這一外殼名字控件子樹的下一級子樹,而像“控制台”、“資源回收筒”、“網路上的芳鄰”等應用程式以及“列印機”等裝置也被虛拟成了外殼名字空間中的節點。為了差別于dos中“目錄”的概念,windows引入了“檔案夾”的概念。“檔案夾”一般是指外殼名字空間樹中的非葉幾點,既可以是dos下的目錄,也可以是“控制台”、“資源回收筒”這類虛拟的目錄。

            新的“路徑”pidl:外殼對象辨別符清單。pidl是一個元素類型為itemidlist結構的數組,數組中元素的個數是未知的,但緊接着數組的末尾的必是一個雙位元組的零。每個數組元素代表了外殼名字空間樹中的一層(即一個檔案夾或檔案),數組中的前一進制素代表的是後一進制素的父檔案夾。由此可見,pidl實際上就是指向一塊由若幹個順序排列的itemidlist結構組成、并在最後有一個雙位元組零的空間的指針。是以pidl的類型就被windows定義為itemidlist結構的指針。

            dos中的路徑是一個字元串,但pidl是一種二進制結構,是以我們不能直接從pidl中獲知它所代表的到底是哪個檔案夾或檔案,而必須調用相應的函數把它轉換為代表路徑的字元串。如果某絕對pidl是檔案系統的一部分,則調用shgetpathfromidlist函數即可;但如不是,就無法獲得路徑字元串了,因為dos中根本就不存在這種路徑。

       總體來說:實作windows下檔案監控的基本流程如下:

【大話QT之五】Windows與Linux下檔案操作監控的實作

       上圖是在windows下利用c++實作檔案監控的一種方式(根據需要靈活改動),這裡簡要叙述一下:1) 利用dialogboxparam建立一個模态對話框,進入視窗過程函數,在該視窗函數中根據各種消息來完成我們的操作。這裡模态對話框與非模态對話框的差別之一是因為它有一套自己的消息泵機制,不需要我們再手動寫消息的接收了(非模态對話框要自己接收消息)。攔截使用者消息,根據各個不同的階段可以加入我們自己的操作,比如初始化等。2) 擷取指定路徑的pidl:即目标路徑的外殼對象辨別符,有了它才能繼續後續的處理,這裡的擷取有兩種方式,一種是利用ifiledialog打開對話框讓使用者選擇(ifiledialog

*pfd),進而通過getresult(ishellitem *psi ; pfs->getresult(&psi))擷取ishellitem對象;然後利用queryinterface(ishellitem2 *_psidrop ; psi->queryinterface(&_psidrop))擷取ishellitem2對象;最後利用它就可以獲得pidl了(利用shgetidlistfromobject)。3) 最後利用shchangenotifyregister完成最終目标窗體的挂載,進而将一個目錄加入到系統的消息鍊中,進而可以擷取檔案系統或shell中關于檔案操作的相關資訊。最後将資訊解析出來就可以了。

       還有一種方式即直接提供目标檔案夾的絕對路徑,由該路徑擷取到pidl,進而将窗體挂載到系統消息鍊中,注意:如果是在qt中實作的話,可以很輕松的擷取到qwidget的視窗句柄。關鍵代碼如下:

parsepidfrompath 的具體實作如下:

      2> linux下檔案監控的實作

        linux下主要是通過inotify實作檔案監控。它是一個核心使用者通知使用者空間程式檔案系統變化的機制。在使用者狀,inotify通過三個系統調用和在傳回的檔案描述符上的檔案i/o操作來使用.

        1) 使用inotify的第一步是建立inotify的執行個體:int fd = inotify_init() ; 每一個inotify執行個體對應一個獨立的排序的隊列。

        2) int wd = inotify_add_watch(fd , file_dir_path , mask);添加一個目錄的監控。

        3) 删除一個監控:inotify_rm_watch(fd , wd);

       關鍵代碼如下:

createwatcherforeachdir的實作:

createwatcher的實作:

總結:

        以上就是windows以及linux下檔案監控系統實作的相關思路及代碼,僅僅作為一個引入,利用這種方式均可以實作對應的功能。

繼續閱讀