Chromium中跨进程文件句柄传递

简介: 实现说明在Chromium跨进程架构下,也会有Browser/Renderer两个进程对相同文件进行操作的需求。

实现说明

在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();

注意多进程下,只是共享了文件描述符,可以理解共享了对相同的读写操作,但不是共享文件句柄,所以各个进程仍然要独立地进行半闭的操作 (打开时是在发起进程完成的。)

目录
相关文章
|
存储 消息中间件 设计模式
进程通信常见方式
进程通信常见方式
进程通信常见方式
|
前端开发 Android开发
Electron 中 webview 如何与主进程渲染进程进行事件监听通信
Electron 中 webview 如何与主进程渲染进程进行事件监听通信
|
2月前
|
存储
系统调用处理程序在内核栈中保存了哪些上下文信息?
【10月更文挑战第29天】系统调用处理程序在内核栈中保存的这些上下文信息对于保证系统调用的正确执行和用户程序的正常恢复至关重要。通过准确地保存和恢复这些信息,操作系统能够实现用户模式和内核模式之间的无缝切换,为用户程序提供稳定、可靠的系统服务。
56 4
|
8月前
|
Linux Shell 程序员
【进程控制】进程程序替换的原理以及exec函数族
【进程控制】进程程序替换的原理以及exec函数族
|
存储 API Windows
驱动开发:内核中进程与句柄互转
在内核开发中,经常需要进行进程和句柄之间的互相转换。进程通常由一个唯一的进程标识符(PID)来标识,而句柄是指对内核对象的引用。在Windows内核中,`EProcess`结构表示一个进程,而HANDLE是一个句柄。为了实现进程与句柄之间的转换,我们需要使用一些内核函数。对于进程PID和句柄的互相转换,可以使用函数如`OpenProcess`和`GetProcessId`。OpenProcess函数接受一个PID作为参数,并返回一个句柄。GetProcessId函数接受一个句柄作为参数,并返回该进程的PID。
|
Web App开发 iOS开发
事件当做参数传递导致浏览器崩溃
事件当做参数传递导致浏览器崩溃
MAC:一个数据缓冲区,作为参数传递到另外一个函数就崩溃
MAC:一个数据缓冲区,作为参数传递到另外一个函数就崩溃
79 0
|
设计模式 Java Android开发
跨进程单例 | Andorid进程通信AIDL原理及应用
设计模式中的单例模式在多进程场景下会演变成多例,存在线程安全问题。本文通过跨进程通信机制让多进程共享单例。
451 0
|
Linux
Linux系统编程-进程创建(fork)、外部程序调用(exec)
在linux中fork函数是非常重要的函数,它可以从已存在进程中创建一个新进程。新进程为子进程,而原进程为父进程。
529 0
|
Android开发
【Binder 机制】进程通信-正常情况 | 进程通信- mmap 内存映射 | Binder 机制重要组件
【Binder 机制】进程通信-正常情况 | 进程通信- mmap 内存映射 | Binder 机制重要组件
194 0
【Binder 机制】进程通信-正常情况 | 进程通信- mmap 内存映射 | Binder 机制重要组件