根据chromium官方说法是为了防止某一个页面渲染崩溃而影响到其他页面的正常渲染。所以它们采用了多进程形式。将每一个页面都放在一个独立的渲染进程中,然后主进程主要是提供窗口(画布)给渲染进程显示以及捕获用户操作等。渲染进程顾名思义就是对html文件进行渲染。
先来一张整体架构图,来源于chromium官网。
虽然这张图是webkit年代的图,现在已经是blink,但是据我所知,还是依然适应的。为了更清晰的表达各个模块之间的对应关系,我画了下面的图:
由于采用了多进程结构,每个页面在用户进程(Browser进程)和渲染进程中都应该有相应的表示。渲染进程是每个页面都直接有一个进程,而只有一个主进程。在这个主进程中对渲染进程的管理以及连接都是通过和渲染进程一一对应的RenderProcessHost进行的。大家是不是觉得上面的图有点像tcp/ip的协议栈,呵呵,我在第一阶段就是这么理解的。
IPC
进程之间是采用的IPC通信,具体而言windows采用了命名管道,unix平台采用了socket(这个我看代码理解的,不一定对),主要用到了以下几个类。
IPC::ChannelProxy:标准代理模式,
一个辅佐类,在其一个线程中运行着一个IPC channel。它提供了处理IPC两种方式:可以在后台线程处理,也可以发送给主线程处理。主线程创建了IPC::ChannelProxy。
IPC::ChannelProxy的接口和IPC::Channel的接口非常相似。消息先发送到 IPC::ChannelProxy中,然后它通过后台线程转发给IPC::Channel. 这意味着消息的发送不会被阻塞。因为IPC::Channel忙碌时会把消息排队,只有当调用线程从消息循环中返回才会flush消息队列。
IPC::ChannelProxy关联一个MessageFilter 用于通知IPC::Channel线程中消息的到来。从来允许 IPC::ChannelProxy在其他线程处理进来的消息。
IPC::ChannelProxy控制IPC::Channel的创建和操作。
IPC::ChannelProxy::MessageFilter
用于在IPC::Channel运行线程中接受消息的类,他可以阻止IPC消息的默认行为。实际上就是将能在IO线程中处理的消息先过滤掉,在IO线程中处理
IPC::Listener:
接收消息者需要实现的接口。
virtual bool OnMessageReceived(const Message& message) = 0;
virtual void OnChannelConnected(int32 peer_pid) {}
virtual void OnChannelError() {}
IPC::ChannelProxy::Context:
用于维护IPC线程的上下文状态。它本身is-a IPC::Listener
IPC::Channel:
在windows平台上通过命名管道通信,unix是用socket。在windows上不同的进程可以通过管道名字获取到管道。在Posix系统中可以将socket的文件描述符给子进程。并赋予一个名字存储到查找列表中。ChannelImpl是不同的平台有不同的实现。
以上对象在双方进程中应该都有。下面分不同的进程介绍重要类的作用及其主要接口。
渲染进程
每个渲染进程都会有一个RenderProcess全局实体,每个Re