Chromium Mojo(IPC)进程通信演示 c++(1)

   网上搜索关于mojo教程 多数都是理论 加上翻译谷歌mojo文档的,但是如何自定义两个进程使用mojo通信呢?看下面的完整例子介绍:(本人也是参考谷歌代码例子改编而成)

本文演示了client.exe和service.exe 通过mojo::IncomingInvitation模式进行通信使用例子。

废话不多说直接上代码:

一、目录结构如下图:

按照如图所示目录结构添加文件即可。 

二、定义sample.mojom接口

1、demo\logger\public\mojom\sample.mojom

module sample.mojom;

interface Logger {
  Log(string message);
  GetTail() => (string message);
};

2、demo\logger\public\mojom\BUILD.gn

import("//mojo/public/tools/bindings/mojom.gni")

mojom("mojom") {
  sources = [
    "sample.mojom",
  ]
}

3、gn gen out/debug 自动生成代码如下:

out\Debug\gen\demo\logger\public\mojom\sample.mojom.h

out\Debug\gen\demo\logger\public\mojom\sample.mojom.cc 

其他更多参考out\Debug\gen\demo\logger\目录下

三、client.exe端代码: 

1、demo\client\client.cc  //client.exe main函数实现文件:

#include<iostream>
#include <stdarg.h>
#include <stddef.h>
#include <stdint.h>

#include "base/at_exit.h"
#include "base/command_line.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/files/memory_mapped_file.h"
#include "base/logging.h"
#include "base/process/launch.h"
#include "base/run_loop.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/threading/thread.h"
#include "build/build_config.h"
#include "demo/logger/public/mojom/sample.mojom.h"
#include "demo/client/logger_test.h"
#include "demo/process_bootstrapper_helper.h"
#include "mojo/core/embedder/configuration.h"
#include "mojo/core/embedder/embedder.h"
#include "mojo/core/embedder/scoped_ipc_support.h"
#include "mojo/public/cpp/bindings/associated_remote.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "mojo/public/cpp/platform/platform_channel.h"
#include "mojo/public/cpp/system/invitation.h"
#include "mojo/public/cpp/system/message_pipe.h"

mojo::ScopedMessagePipeHandle LaunchAndConnect() {
  // Under the hood, this is essentially always an OS pipe (domain socket pair,
  // Windows named pipe, Fuchsia channel, etc).
  mojo::PlatformChannel channel;

  mojo::OutgoingInvitation invitation;

  // Attach a message pipe to be extracted by the receiver. The other end of the
  // pipe is returned for us to use locally. We choose the arbitrary name "pipe"
  // here, which is the same name that the receiver will have to use when
  // plucking this pipe off of the invitation it receives to join our process
  // network.
  mojo::ScopedMessagePipeHandle pipe = invitation.AttachMessagePipe("pipe");

  base::LaunchOptions options;
  // This is the relative path to the mock "renderer process" binary. We pass it
  // into `base::LaunchProcess` to run the binary in a new process.
  static const base::CommandLine::CharType* argv[] = {
      FILE_PATH_LITERAL("./service")};
  base::CommandLine command_line(1, argv);

  // Delegating to Mojo to "prepare" the command line will append the
  // `--mojo-platform-channel-handle=N` command line argument, so that the
  // renderer knows which file descriptor name to recover, in order to establish
  // the primordial connection with this process. We log the full command line
  // next, to show what mojo information the renderer will be initiated with.
  channel.PrepareToPassRemoteEndpoint(&options, &command_line);
  LOG(INFO) << "Browser: " << command_line.GetCommandLineString();
  base::Process child_process = base::LaunchProcess(command_line, options);
  channel.RemoteProcessLaunchAttempted();

  mojo::OutgoingInvitation::Send(std::move(invitation), child_process.Handle(),
                                 channel.TakeLocalEndpoint());
  return pipe;
}

logger_test *g_logger_test = nullptr;

void CreateProcessRemote(mojo::ScopedMessagePipeHandle pipe,
                         const std::string& msg) {
  mojo::PendingRemote<sample::mojom::Logger> pending_remote(std::move(pipe),
                                                            0u);
  mojo::Remote<sample::mojom::Logger> remote(std::move(pending_remote));
  g_logger_test = new logger_test(std::move(remote));
  LOG(INFO) << "Browser invoking SayHello() on remote pointing to renderer";
  g_logger_test->sendLoggerMsg(msg);
  g_logger_test->sendLoggerExt();
}

int main(int argc, const char* argv[]) {
  base::AtExitManager at_exit_manager;
  base::CommandLine::Init(argc, argv);
  ProcessBootstrapperHelp bootstrapper;
  bootstrapper.InitMainThread(base::MessagePumpType::IO);
  bootstrapper.InitMojo(/*as_browser_process=*/true);

  mojo::ScopedMessagePipeHandle pipe = LaunchAndConnect();
  std::string msg("jd test");
  base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
      FROM_HERE, base::BindOnce(&CreateProcessRemote, std::move(pipe),msg));

  base::RunLoop run_loop;
  // Delay shutdown of the browser process for visual effects, as well as to
  // ensure the browser process doesn't die while the IPC message is still being
  // sent to the target process asynchronously, which would prevent its
  // delivery.
  base::SequencedTaskRunner::GetCurrentDefault()->PostDelayedTask(
      FROM_HERE,
      base::BindOnce(
          [](base::OnceClosure quit_closure) {
            LOG(INFO) << "'Browser process' shutting down";
            std::move(quit_closure).Run();
          },
          run_loop.QuitClosure()),
      base::Seconds(2));
  run_loop.Run();
  delete g_logger_test;
  g_logger_test = nullptr;

  return 0;
}

2、demo\client\logger_test.cc

#include "demo/client/logger_test.h"
#include <stdarg.h>
#include <stddef.h>
#include <stdint.h>
#include <iostream>
#include "base/functional/bind.h"

logger_test::logger_test(mojo::Remote<sample::mojom::Logger> rc)
    : logger_client_(std::move(rc)) {}

logger_test::~logger_test() {
  std::cout << "~logger_test()\n";
}

void logger_test::sendLoggerMsg(const std::string& msg) {
  logger_client_->Log(msg);
}

void logger_test::GetTailCallbackTest(const std::string& msg){
    LOG(ERROR) << "GetTail callback " << msg;

}
void logger_test::sendLoggerExt(){
    logger_client_->GetTail(base::BindOnce(&logger_test::GetTailCallbackTest,
                                           base::Unretained(this)));
}

3、demo\client\logger_test.h


#ifndef CHROME_BROWSER_LOGGER_TEST_H_
#define CHROME_BROWSER_LOGGER_TEST_H_
#include <string>
#include <vector>
#include "base/logging.h"
#include "demo/logger/public/mojom/sample.mojom.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/receiver.h"
#include "mojo/public/cpp/bindings/remote.h"

class logger_test {
 public:
  logger_test(mojo::Remote<sample::mojom::Logger> rc);
  ~logger_test();

  void sendLoggerMsg(const std::string& msg);
  void sendLoggerExt();

 private:
  void GetTailCallbackTest(const std::string& msg);
  /* data */
  mojo::Remote<sample::mojom::Logger> logger_client_;
};

#endif  // CHROME_BROWSER_LOGGER_TEST_H_

四、service.exe端代码: 

1、demo\service\service.cc  //service.exe main函数实现文件:

#include <stdarg.h>
#include <stddef.h>
#include <stdint.h>
#include <iostream>

#include <initializer_list>
#include <memory>
#include <string>
#include <tuple>
#include <vector>

#include "base/at_exit.h"
#include "base/command_line.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/files/memory_mapped_file.h"
#include "base/logging.h"
#include "base/process/launch.h"
#include "base/run_loop.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/threading/thread.h"
#include "build/build_config.h"
#include "demo/process_bootstrapper_helper.h"
#include "demo/service/LoggerImpl.h"
#include "mojo/core/embedder/configuration.h"
#include "mojo/core/embedder/embedder.h"
#include "mojo/core/embedder/scoped_ipc_support.h"
#include "mojo/public/cpp/bindings/associated_receiver.h"
#include "mojo/public/cpp/bindings/associated_remote.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/receiver.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "mojo/public/cpp/platform/platform_channel.h"
#include "mojo/public/cpp/system/invitation.h"
#include "mojo/public/cpp/system/message_pipe.h"

LoggerImpl* g_process_impl = nullptr;

void BindProcessImpl(mojo::ScopedMessagePipeHandle pipe) {
  // Create a receiver
  mojo::PendingReceiver<sample::mojom::Logger> pending_receiver(
      std::move(pipe));
  g_process_impl = new LoggerImpl(std::move(pending_receiver));
}

int main(int argc, const char* argv[]) {
  base::AtExitManager at_exit_manager;
  base::CommandLine::Init(argc, argv);
  const base::CommandLine& command_line =
      *base::CommandLine::ForCurrentProcess();

  std::wcout << command_line.GetCommandLineString().c_str()<<"\n";

  ProcessBootstrapperHelp bootstrapper;
  bootstrapper.InitMainThread(base::MessagePumpType::IO);
  bootstrapper.InitMojo(/*as_browser_process=*/false);

  // Accept an invitation.
  //
  // `RecoverPassedEndpointFromCommandLine()` is what makes use of the mojo
  // platform channel handle that gets printed in the above `LOG()`; this is the
  // file descriptor of the first connection that this process shares with the
  // browser.
  mojo::IncomingInvitation invitation = mojo::IncomingInvitation::Accept(
      mojo::PlatformChannel::RecoverPassedEndpointFromCommandLine(
          *base::CommandLine::ForCurrentProcess()));
  // Extract one end of the first pipe by the name that the browser process
  // added this pipe to the invitation by.
  mojo::ScopedMessagePipeHandle pipe = invitation.ExtractMessagePipe("pipe");

  base::RunLoop run_loop;
  base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
      FROM_HERE, base::BindOnce(&BindProcessImpl, std::move(pipe)));
  run_loop.Run();

  std::cout << "service\n";

  return 0;
}

LoggerImpl.h 和LoggerImpl.cc 是sample::mojom::Logger 实现类:

2、demo\service\LoggerImpl.h

#ifndef CHROME_BROWSER_LOGGERIMPL_H_
#define CHROME_BROWSER_LOGGERIMPL_H_

#include <string>
#include <vector>
#include "base/logging.h"
#include "demo/logger/public/mojom/sample.mojom.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/receiver.h"

class LoggerImpl : public sample::mojom::Logger {
 public:
  // NOTE: A common pattern for interface implementations which have one
  // instance per client is to take a PendingReceiver in the constructor.

  explicit LoggerImpl(mojo::PendingReceiver<sample::mojom::Logger> pending_receiver);
  ~LoggerImpl() override;

  // sample::mojom::Logger:
  void Log(const std::string& message) override;
  void GetTail(GetTailCallback callback) override;
  void OnError();

 private:
  mojo::Receiver<sample::mojom::Logger> receiver_;
  std::vector<std::string> lines_;
  LoggerImpl(const LoggerImpl&) = delete;
  LoggerImpl& operator=(const LoggerImpl&) = delete;
};

#endif  // CHROME_BROWSER_LOGGERIMPL_H_

3、demo\service\LoggerImpl.cc


#include "demo/service/LoggerImpl.h"
#include "base/functional/bind.h"

LoggerImpl::LoggerImpl(
    mojo::PendingReceiver<sample::mojom::Logger> pending_receiver)
    : receiver_(this, std::move(pending_receiver)) {
  // receiver_.Bind(std::move(pending_receiver));
  receiver_.set_disconnect_handler(
      base::BindOnce(&LoggerImpl::OnError, base::Unretained(this)));
}

LoggerImpl::~LoggerImpl() {}

// sample::mojom::Logger:
void LoggerImpl::Log(const std::string& message) {
  LOG(ERROR) << "[Logger] " << message;
  lines_.push_back(message);
}

void LoggerImpl::GetTail(GetTailCallback callback) {
  std::move(callback).Run(lines_.back());
}

void LoggerImpl::OnError() {
  LOG(ERROR) << "Client disconnected! Purging log lines.";
  lines_.clear();
}

五、初始化mojo和线程辅助类: 

demo\process_bootstrapper_helper.h

// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CODELABS_MOJO_EXAMPLES_PROCESS_BOOTSTRAPPER_HELPER_H_
#define CODELABS_MOJO_EXAMPLES_PROCESS_BOOTSTRAPPER_HELPER_H_

#include "base/message_loop/message_pump.h"
#include "base/run_loop.h"
#include "base/task/sequence_manager/sequence_manager.h"
#include "base/threading/thread.h"
#include "mojo/core/embedder/embedder.h"
#include "mojo/core/embedder/scoped_ipc_support.h"

class ProcessBootstrapperHelp {
 public:
  ProcessBootstrapperHelp();
  ~ProcessBootstrapperHelp();

  // This sets up the main thread with a message pump of `type`, and optionally
  // a dedicated IO thread if `type` is *not* `base::MessagePumpType::IO`.
  void InitMainThread(base::MessagePumpType type) {
    // Creates a sequence manager bound to the main thread with a message pump
    // of some specified type. The message pump determines exactly what the
    // event loop on its thread is capable of (i.e., what *kind* of messages it
    // can "pump"). For example, a `DEFAULT` message pump is capable of
    // processing simple events, like async timers and posted tasks. The `IO`
    // message pump type — which is used in every example in this codelab — is
    // capable of asynchronously processing IO over IPC primitives like file
    // descriptors, used by Mojo. A thread with *that* kind of message pump is
    // required for any process using Mojo for IPC.
    std::unique_ptr<base::MessagePump> pump = base::MessagePump::Create(type);
    sequence_manager =
        base::sequence_manager::CreateSequenceManagerOnCurrentThreadWithPump(
            std::move(pump),
            base::sequence_manager::SequenceManager::Settings::Builder()
                .SetMessagePumpType(type)
                .Build());
    default_tq = std::make_unique<base::sequence_manager::TaskQueue::Handle>(
        sequence_manager->CreateTaskQueue(
            base::sequence_manager::TaskQueue::Spec(
                base::sequence_manager::QueueName::DEFAULT_TQ)));
    sequence_manager->SetDefaultTaskRunner((*default_tq)->task_runner());

    if (type == base::MessagePumpType::DEFAULT) {
      InitDedicatedIOThread();
    }
  }

  // Must be called after `InitMainThread()`.
  void InitMojo(bool as_browser_process) {
    CHECK(default_tq) << "Must call `InitMainThread()` before `InitMojo()`";
    // Basic Mojo initialization for a new process.
    mojo::core::Configuration config;
    // For mojo, one process must be the broker process which is responsible for
    // trusted cross-process introductions etc. Traditionally this is the
    // "browser" process.
    config.is_broker_process = as_browser_process;
    mojo::core::Init(config);

    // The effects of `ScopedIPCSupport` are mostly irrelevant for our simple
    // examples, but this class is used to determine how the IPC system shuts
    // down. The two shutdown options are "CLEAN" and "FAST", and each of these
    // may determine how other processes behave if *this* process has a message
    // pipe that is in the middle of proxying messages to another process where
    // the other end of the message pipe lives.
    //
    // In real Chrome, both the browser and renderer processes can safely use
    // `FAST` mode, because the side effects of quickly terminating the IPC
    // system in the middle of cross-process IPC message proxying is not
    // important. See this class's documentation for more information on
    // shutdown.
    //
    // We initialize `ipc_support` with a task runner for whatever thread should
    // be the IO thread. This means preferring `io_task_runner` when it is
    // non-null, and the default task runner otherwise.
    mojo::core::ScopedIPCSupport ipc_support(
        io_task_runner ? io_task_runner : (*default_tq)->task_runner(),
        mojo::core::ScopedIPCSupport::ShutdownPolicy::FAST);
  }

  std::unique_ptr<base::sequence_manager::TaskQueue::Handle> default_tq;
  std::unique_ptr<base::sequence_manager::SequenceManager> sequence_manager;
  scoped_refptr<base::SingleThreadTaskRunner> io_task_runner;

 private:
  // Note that you cannot call this if you've ever called
  // `InitMainThread(base::MessagePumpType::IO)` since that means the main
  // thread *itself* the IO thread.
  void InitDedicatedIOThread() {
    io_thread_ = std::make_unique<base::Thread>("ipc!");
    io_thread_->StartWithOptions(
        base::Thread::Options(base::MessagePumpType::IO, 0));
    io_task_runner = io_thread_->task_runner();
  }

  std::unique_ptr<base::Thread> io_thread_;
};

ProcessBootstrapperHelp::ProcessBootstrapperHelp() = default;
ProcessBootstrapperHelp::~ProcessBootstrapperHelp() = default;

#endif  // CODELABS_MOJO_EXAMPLES_PROCESS_BOOTSTRAPPER_HELPER_H_

六、添加demo\build.gn文件:

   1、  dem\BUILD.gn

# Copyright 2014 The Chromium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
 
import("//build/config/compiler/compiler.gni")

group("jdcode_mojo_examples") {
  testonly = true
  if (is_win) {
    deps = [
      ":client",
      ":service",
    ]
  }
}

executable("client") {
    sources = [
        "client/client.cc",
        "client/logger_test.cc",
        "client/logger_test.h",
        "process_bootstrapper_helper.h",
    ]
 
    if (is_win) {
      ldflags = [ "/LARGEADDRESSAWARE" ]
    }
 
    deps = [
      "//base",
      "//build/win:default_exe_manifest",
      "//demo/logger/public/mojom",
      "//ipc",
      "//mojo/core/embedder",
      "//mojo/public/cpp/platform",
      "//mojo/public/mojom/base",
    ]
}

executable("service") {
    sources = [
         "service/service.cc",
         "service/LoggerImpl.h",
         "service/LoggerImpl.cc",
         "process_bootstrapper_helper.h",
    ]
 
    if (is_win) {
      ldflags = [ "/LARGEADDRESSAWARE" ]
    }
 
    deps = [
      "//base",
      "//build/win:default_exe_manifest",
      "//demo/logger/public/mojom",
      "//ipc",
      "//mojo/core/embedder",
      "//mojo/public/cpp/platform",
      "//mojo/public/mojom/base",
    ]
}

2、src\BUILD.gn 追加如下:

    if (is_win) {
      deps += [
        "//demo/logger/public/mojom",
        "//demo:jdcode_mojo_examples",
      ]
    }

七、开始编译和调试:

1、gn gen out/debug

   自动生成mojo文件:   

2、ninja -C out/debug client

编译client.exe

3、ninja -C out/debug service

编译service.exe

 4、最终生成文件如图:

八、看下调试堆栈效果: 

  8.1)、 client.exe主要流程:

1、初始化线程和mojo // mojo::core::Init(config);

  ProcessBootstrapperHelp bootstrapper;

  bootstrapper.InitMainThread(base::MessagePumpType::IO);

  bootstrapper.InitMojo(/*as_browser_process=*/true); 

2、LaunchAndConnect();

 2.1)、mojo::OutgoingInvitation建立并且启动service.exe[通过base::LaunchProcess],

2.2)将./service --mojo-platform-channel-handle=508传递给service.exe

3、CreateProcessRemote调用Log和GetTail接口函数

8.2)、service.exe主要流程:

1、初始化线程和mojo // mojo::core::Init(config);

  ProcessBootstrapperHelp bootstrapper;

  bootstrapper.InitMainThread(base::MessagePumpType::IO);

  bootstrapper.InitMojo(/*as_browser_process=*/false);

2、与client.exe建立链接:

  mojo::IncomingInvitation invitation = mojo::IncomingInvitation::Accept(

      mojo::PlatformChannel::RecoverPassedEndpointFromCommandLine(

          *base::CommandLine::ForCurrentProcess()));

  // Extract one end of the first pipe by the name that the browser process

  // added this pipe to the invitation by.

  mojo::ScopedMessagePipeHandle pipe = invitation.ExtractMessagePipe("pipe");

3、BindProcessImpl(mojo::ScopedMessagePipeHandle pipe)处理客户端client.exe发出的函数请求Log和GetTail

8.3)、看下最终效果图:

总结: 

本文演示了通过mojo::IncomingInvitation进行通信的完整例子,仅供参考,mojo基础和原理参考官网介绍。

<think>好的,我需要回答用户关于Chromium项目中IPC(进程间通信)的机制和实现的问题。首先,我需要回顾自己已有的知识,并参考用户提供的引用内容。用户提到两个引用:一个是关于ChromiumIPC消息处理宏,另一个是UNIX Domain Socket在IPC中的应用。 首先,ChromiumIPC机制主要用于不同进程之间的通信,比如浏览器进程和渲染进程。根据引用[^1],Chromium使用宏来定义和处理IPC消息。例如,IPC_MESSAGE_ROUTED0用于定义不带参数的路由消息,而IPC_MESSAGE_DECL则用于声明消息类型。这些宏帮助生成消息的序列化和反序列化代码,简化了开发流程。 接下来,进程间通信需要高效的数据传输方式。引用[^2]提到UNIX Domain Socket相比网络socket更高效,因为它不需要经过网络协议栈。不过,Chromium可能不直接使用UNIX Domain Socket,而是采用其他机制,比如命名管道(Named Pipes)或共享内存,特别是在跨平台支持上。需要确认Chromium在不同操作系统上的具体实现,比如Windows可能使用命名管道,而Linux使用socketpair或类似的机制。 另外,IPC消息的序列化和反序列化是关键步骤。Chromium使用Mojo作为现代IPC库,它提供了更灵活的消息传递方式,支持接口定义语言(IDL),允许生成强类型的消息处理代码。Mojo不仅处理消息的传输,还管理进程间的接口和代理,使得多进程架构更易维护。 安全性方面,IPC机制必须防止恶意消息或数据篡改。ChromiumIPC通道应该实施消息验证,确保只有拥有正确权限的进程可以发送和接收特定消息。沙箱机制也会限制渲染进程的能力,进一步保护系统安全。 还需要考虑消息的路由机制。引用[^1]中的路由消息可能涉及将消息发送到特定的渲染框架或工作线程。这需要进程间有明确的路由标识,比如Frame ID或Render Process ID,确保消息正确到达目标。 最后,性能优化方面,大块数据的传输可能使用共享内存来减少拷贝开销。例如,处理大型图像或视频时,通过共享内存传递数据指针,而不是复制数据本身,从而提高效率。 总结起来,回答需要涵盖Chromium IPC的基本架构、消息定义与处理、传输机制、序列化、安全性、路由以及性能优化等方面,并结合用户提供的引用内容,特别是宏的使用和UNIX Domain Socket的优势,尽管Chromium可能采用其他方法,但可以对比说明不同IPC机制的特点。</think>ChromiumIPC通信机制基于多进程架构设计,主要实现浏览器进程与渲染进程、插件进程等子进程间的安全高效通信。以下是核心实现要点: ### 一、消息通道架构 1. **通道类型**:采用命名管道(Windows)或UNIX Domain Socket(Linux/macOS)建立双向通信链路。UNIX Domain Socket相比网络socket减少协议栈开销,通过文件系统路径标识通信端点 2. **序列化机制**:使用Mojo IPC库进行结构化数据序列化,支持自动生成接口绑定代码。例如消息定义: ```cpp // 接口定义语言(IDL) interface Renderer { SubmitForm(FormData data) => (bool success); } ``` ### 二、消息路由机制 1. **路由标识符**:每个消息携带`routing_id`字段标识目标框架(frame),通过`IPC_MESSAGE_ROUTED`宏定义路由消息 2. **代理模式**:通过`ChannelProxy`实现线程间消息转发,主线程的IPC消息通过代理分发到IO线程 ### 三、安全控制 1. **权限校验**:渲染进程只能发送白名单内预定义的IPC消息类型 2. **沙箱过滤**:敏感操作(如文件访问)必须通过浏览器进程代理执行 3. **消息验证**:自动校验消息结构合法性,防止畸形数据攻击 ### 四、性能优化 1. **共享内存**:大块数据(如图像缓冲区)通过共享内存传递,减少拷贝开销 2. **批量处理**:多个IPC消息合并发送,降低上下文切换频率 3. **优先级队列**:输入事件等高优先级消息优先处理 ```cpp // 典型消息处理流程 IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateRect, OnUpdateRect) void RenderWidget::OnUpdateRect(const ViewHostMsg_UpdateRect_Params& params) { // 处理界面更新 } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值