chrome设计时采用的一种方法是多进程技术(不仅限于此,也有其他方式),其中涉及到一个重要的问题就是进程间通信。
可以从操作系统任务管理器以及CHROME自带的任务管理器可以看出,确实每个tab页,一个进程。
浏览器进程负责进程管理以及进程通信。在浏览器进程中,有其他所有进程的标记,每个标记对应一个线程。浏览器对相关标记的操作,会被封装成消息,并发送给对应的Process来处理。
渲染进程嵌入WebKit来解析, 渲染和处理网页及网络应用。
在ipc_channel.cc代码中有如下注释(Channels are implemented using named pipes on Windows)
服务器:
管道创建:CreateNamedPipe 等待链接:ConnectNamedPipe(类似于SOCKET中的LISTEN) 数据发送:WriteFile 数据接收:ReadFile客户端
管道连接:CreateFile或者CallNamedPipe 数据发送:WriteFile 数据接收:ReadFile
chrome中对进程间通信进行封装实现:CHANEL。
相关代码:ipc_channel.h ipc_sender.h ipc_reader.h ipc_listener.h ipc_channel_win.h及其CPP文件。
bool Channel::ChannelImpl::CreatePipe(const IPC::ChannelHandle &channel_handle, Mode mode);
若FLAG为MODE_SERVER_FLAG,有如下代码:命名管道的创建
const DWORD open_mode = PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED | FILE_FLAG_FIRST_PIPE_INSTANCE; pipe_name = PipeName(channel_handle.name, &client_secret_); pipe_ = CreateNamedPipeW(pipe_name.c_str(), open_mode, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE, 1, Channel::kReadBufferSize, Channel::kReadBufferSize, 5000, NULL);
若FLAG为MODE_CLIENT_FLAG,则为管道连接
pipe_name = PipeName(channel_handle.name, &client_secret_); pipe_ = CreateFileW(pipe_name.c_str(), GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, SECURITY_SQOS_PRESENT | SECURITY_IDENTIFICATION | FILE_FLAG_OVERLAPPED, NULL);
消息发送:
bool Channel::ChannelImpl::Send(Message* message) { };
从管道中读取消息:根据管道句柄,设置数据缓冲区以及数据大小,直接读取即可。
Channel::ChannelImpl::ReadState Channel::ChannelImpl::ReadData( char* buffer, int buffer_len, DWORD bytes_read = 0; BOOL ok = ReadFile(pipe_, buffer, buffer_len, &bytes_read, &input_state_.context.overlapped); }
总结:
常用的IPC方式5. 消息队列:进程间可以通过消息队列进行通信。将消息发送到对方进程的消息队列中。
注:参考
1.《Google Chrome 浏览器架构解析及相关特性分析》
2. http://lihuan623.blog.163.com/blog/static/1385958452010449734597/