Chromium中跨程式檔案控制程式碼傳遞

Horky發表於2015-11-02

實現說明

在Chromium跨程式架構下,也會有Browser/Renderer兩個程式對相同檔案進行操作的需求。比如Browser的某個任務依賴於Renderer端對指定檔案的輸出。而在POXIS下,允許不同程式間傳遞檔案描述符(File Descriptor))的, 比如傳遞socket,或者普通檔案,進而可以達到不需要重新開啟檔案,而對相同檔案讀寫的效果(並不是分享檔案控制程式碼)。Chromium對這個特性做了封裝,也包括了Windows下的實現(也包括了Windows下的實現)。涉及的基本結構如下:
structure

其中dbus::FileDescriptor,定義在dbus/file_descriptor.h中。因為安全原因不能傳遞目錄的FD。
base::File是對不同平臺檔案控制程式碼的封裝,定義在base/file.h中。
PlatformFile是一組函式,定義在base/ipc_platform_file.h,其中兩個重要的API是:

IPC_EXPORT PlatformFileForTransit GetFileHandleForProcess(
    base::PlatformFile file,
    base::ProcessHandle process, 
    bool close_source_handle);  

引數解釋:
base::PlatformFile file, // 當前程式開啟的檔案控制程式碼
base::ProcessHandle process, // 目標process
bool close_source_handle); // 是否會關閉當前的檔案控制程式碼,如果不會,就需要多建立當前檔案控制程式碼的副本,以避免IPC傳遞時出現異常。否則就複用當前的檔案描述符(File descriptor,Windows下為Handle)。

IPC_EXPORT PlatformFileForTransit TakeFileHandleForProcess(
    base::File file,
    base::ProcessHandle process);

這個版本就是GetFileHandleForProcess第三個引數(close_source_handle)為true的情況,這時當前程式不需要再持有這個檔案控制程式碼,看起來像是將所有權也轉移到目標程式。

使用示例

// MHTMLGenerationManager (Browser)
void MHTMLGenerationManager::StreamMHTML(
    WebContents* web_contents,
    base::File browser_file, // 傳入一個檔案控制程式碼browser_file
    const GenerateMHTMLCallback& callback) {

   // 轉換到跨程式的FD, 並不釋放所有權,所以第三個引數傳遞的是false。
   PC::PlatformFileForTransit renderer_file =
       IPC::GetFileHandleForProcess(browser_file.GetPlatformFile(),
                                  renderer_process, false);

   // 隨後在FileAvailable函式將renderer_file傳遞出去。
   rvh->Send(new ViewMsg_SavePageAsMHTML(rvh->GetRoutingID(), job_id,
                                        renderer_file));
}

經過IPC,傳遞到Renderer程式。

// MHTMLGenerator (Renderer)
void MHTMLGenerator::OnSavePageAsMHTML(int job_id, IPC::PlatformFileForTransit file_for_transit) {
  // 從訊息中的FD,轉換到base::File, 可以進行相關的檔案操作了。
  base::File file_ = IPC::PlatformFileForTransitToFile(file_for_transit);
  int bytes_written = file_.Write(total_bytes_written,
                                    data + total_bytes_written, copy_size);

  file_.Close();

注意多程式下,只是共享了檔案描述符,可以理解共享了對相同的讀寫操作,但不是共享檔案控制程式碼,所以各個程式仍然要獨立地進行半閉的操作 (開啟時是在發起程式完成的。)

相關文章