创建
子进程的主线程创建的时候会创建一个通信管道,用于和主进程进行通信。
void ChildThreadImpl::Init(const Options& options) {
......
channel_ =
IPC::SyncChannel::Create(this, ChildProcess::current()->io_task_runner(),
ChildProcess::current()->GetShutDownEvent());
......
这里创建的是一个SyncChannel的支持同步的channel。传递的是this,为当前线程指针,
然后又传递了IO线程的任务运行runner,最后传递的时候关闭事件的通知。
// static
scoped_ptr<SyncChannel> SyncChannel::Create(
Listener* listener,
const scoped_refptr<base::SingleThreadTaskRunner>& ipc_task_runner,
WaitableEvent* shutdown_event) {
return make_scoped_ptr(
new SyncChannel(listener, ipc_task_runner, shutdown_event));
}
SyncChannel::SyncChannel(
Listener* listener,
const scoped_refptr<base::SingleThreadTaskRunner>& ipc_task_runner,
WaitableEvent* shutdown_event)
: ChannelProxy(new SyncContext(listener, ipc_task_runner, shutdown_event)) {
// The current (listener) thread must be distinct from the IPC thread, or else
// sending synchronous messages will deadlock.
DCHECK_NE(ipc_task_runner.get(), base::ThreadTaskRunnerHandle::Get().get());
StartWatching();
}
SyncChannel实现的是同步机制,而内部继承自ChannelProxy,后者实现后台线程机制,也就是说将listenner线程即主线程,ipc_task_runner线程即IO线程分开。
换句话说,SyncChannel负责进行同步异步的发送消息,如果是同步发送,那么在发送之后堵塞当前线程等待结果,如果是异步发送,那么使用ChannelProxy来发送消息后立即返回。
发送
如下是一个发送与接收的过程,这是一个GPU进程从IO线程上接收到GpuMsg_Initialize_Meta,经过处理,然后发送给IO线程的流程栈
3:030> kL
# Child-SP RetAddr Call Site
00 00000000`001fcfa8 000007fe`e69cde7e chrome_child!IPC::ChannelProxy::Context::Send
01 00000000`001fcfb0 000007fe`e69cab28 chrome_child!IPC::ChannelProxy::Send+0x12
02 00000000`001fcfe0 000007fe`e70397d0 chrome_child!IPC::SyncChannel::Send+0x13c
03 00000000`001fd0e0 000007fe`e772a7c2 chrome_child!content::ChildThreadImpl::Send+0x38
04 00000000`001fd110 000007fe`e772a27e chrome_child!content::GpuChildThread::OnInitialize+0xa2
05 (Inline Function) --------`-------- chrome_child!IPC::MessageT<GpuMsg_Initialize_Meta,std::tuple<>,void>::Dispatch+0x3a
06 00000000`001fd290 000007fe`e703916d chrome_child!content::GpuChildThread::OnControlMessageReceived+0x426
07 00000000`001fd430 000007fe`e772a9fe chrome_child!content::ChildThreadImpl::OnMessageReceived+0xd9
08 00000000`001fd590 000007fe`e69cda94 chrome_child!content::GpuChildThread::OnMessageReceived+0x22
09 00000000`001fd6b0 000007fe`e55042a9 chrome_child!IPC::ChannelProxy::Context::OnDispatchMessage+0x134
0a (Inline Function) --------`-------- chrome_child!base::Callback<void __cdecl(void)>::Run+0x8
0b 00000000`001fd7b0 000007fe`e54bfadc chrome_child!base::debug::TaskAnnotator::RunTask+0x189
0c 00000000`001fd8a0 000007fe`e54c0624 chrome_child!base::MessageLoop::RunTask+0x3fc
0d (Inline Function) --------`-------- chrome_child!base::MessageLoop::DeferOrRunPendingTask+0x147
0e 00000000`001fe980 000007fe`e5502e48 chrome_child!base::MessageLoop::DoWork+0x484
0f 00000000`001feb50 000007fe`e5502ad2 chrome_child!base::MessagePumpForUI::DoRunLoop+0x78
10 00000000`001febc0 000007fe`e55029cf chrome_child!base::MessagePumpWin::Run+0x42
11 (Inline Function) --------`-------- chrome_child!base::MessageLoop::RunHandler+0x15
12 00000000`001fec00 000007fe`e54bee21 chrome_child!base::RunLoop::Run+0xdf
13 00000000`001fec50 000007fe`e7728257 chrome_child!base::MessageLoop::Run+0x41
14 00000000`001fecb0 000007fe`e68d0432 chrome_child!content::GpuMain+0x8bf
15 00000000`001ff6c0 000007fe`e68d026f chrome_child!content::RunNamedProcessTypeMain+0x18e
16 00000000`001ff830 000007fe`e68cd6c9 chrome_child!content::ContentMainRunnerImpl::Run+0x93
17 00000000`001ff8c0 000007fe`e6842162 chrome_child!content::ContentMain+0x35
18 00000000`001ff8f0 00000001`3f9e0f6f chrome_child!ChromeMain+0x82
19 00000000`001ff980 00000001`3f9e01b0 chrome!MainDllLoader::Launch+0x317
1a 00000000`001ffaa0 00000001`3fa1e018 chrome!wWinMain+0x234
1b 00000000`001ffcc0 00000000`7778652d chrome!__tmainCRTStartup+0x148
1c 00000000`001ffd00 00000000`779bc541 kernel32!BaseThreadInitThunk+0xd
1d 00000000`001ffd30 00000000`00000000 ntdll!RtlUserThreadStart+0x1d
在最后,通过IO将消息发送出去
void ChannelProxy::Context::Send(Message* message) {
if (channel_send_thread_safe_) {
SendFromThisThread(message);
return;
}
ipc_task_runner()->PostTask(
FROM_HERE, base::Bind(&ChannelProxy::Context::OnSendMessage, this,
base::Passed(scoped_ptr<Message>(message))));
}
那么IO线程又是如何将消息发送的呢,也就是说当把消息派发给了IO线程后,IO线程又做了什么,我们在ChannelProxy::Context::OnSendMessage上下断,看看后续它怎么执行的。
3:036> kL
# Child-SP RetAddr Call Site
00 00000000`04e4e1d0 000007fe`e69d0ac5 kernel32!WriteFileImplementation+0x6
01 00000000`04e4e210 000007fe`e69d08b1 chrome_child!IPC::ChannelWin::ProcessOutgoingMessages+0x1bd
02 00000000`04e4e360 000007fe`e69d0cfa chrome_child!IPC::ChannelWin::ProcessMessageForDelivery+0x275
03 00000000`04e4e470 000007fe`e69cdd36 chrome_child!IPC::ChannelWin::Send+0x62
04 00000000`04e4e4a0 000007fe`e710eef8 chrome_child!IPC::ChannelProxy::Context::OnSendMessage+0x72
05 (Inline Function) --------`-------- chrome_child!base::internal::RunnableAdapter<void (__cdecl content::RTCPeerConnectionHandler::Observer::*)(scoped_ptr<content::RtcDataChannelHandler,std::default_delete<content::RtcDataChannelHandler> >)>::Run+0x2b
06 (Inline Function) --------`-------- chrome_child!base::internal::InvokeHelper<0,void,base::internal::RunnableAdapter<void (__cdecl content::RTCPeerConnectionHandler::Observer::*)(scoped_ptr<content::RtcDataChannelHandler,std::default_delete<content::RtcDataChannelHandler> >)> >::MakeItSo+0x2b
07 00000000`04e4e530 000007fe`e55042a9 chrome_child!base::internal::Invoker<base::IndexSequence<0,1>,base::internal::BindState<base::internal::RunnableAdapter<void (__cdecl content::RTCPeerConnectionHandler::Observer::*)(scoped_ptr<content::RtcDataChannelHandler,std::default_delete<content::RtcDataChannelHandler> >) __ptr64>,void __cdecl(content::RTCPeerConnectionHandler::Observer * __ptr64,scoped_ptr<content::RtcDataChannelHandler,std::default_delete<content::RtcDataChannelHandler> >),content::RTCPeerConnectionHandler::Observer * __ptr64 const,base::internal::PassedWrapper<scoped_ptr<content::RtcDataChannelHandler,std::default_delete<content::RtcDataChannelHandler> > > >,base::internal::InvokeHelper<0,void,base::internal::RunnableAdapter<void (__cdecl content::RTCPeerConnectionHandler::Observer::*)(scoped_ptr<content::RtcDataChannelHandler,std::default_delete<content::RtcDataChannelHandler> >) __ptr64> >,void __cdecl(void)>::Run+0x4c
08 (Inline Function) --------`-------- chrome_child!base::Callback<void __cdecl(void)>::Run+0x8
09 00000000`04e4e570 000007fe`e54bfadc chrome_child!base::debug::TaskAnnotator::RunTask+0x189
0a 00000000`04e4e660 000007fe`e54c0624 chrome_child!base::MessageLoop::RunTask+0x3fc
0b (Inline Function) --------`-------- chrome_child!base::MessageLoop::DeferOrRunPendingTask+0x147
0c 00000000`04e4f740 000007fe`e550360a chrome_child!base::MessageLoop::DoWork+0x484
0d 00000000`04e4f910 000007fe`e5502ad2 chrome_child!base::MessagePumpForIO::DoRunLoop+0xaa
0e 00000000`04e4f940 000007fe`e55029cf chrome_child!base::MessagePumpWin::Run+0x42
0f (Inline Function) --------`-------- chrome_child!base::MessageLoop::RunHandler+0x15
10 00000000`04e4f980 000007fe`e54e1ad1 chrome_child!base::RunLoop::Run+0xdf
11 (Inline Function) --------`-------- chrome_child!base::MessageLoop::Run+0x35
12 00000000`04e4f9d0 000007fe`e54e1e28 chrome_child!base::Thread::Run+0x41
13 00000000`04e4fa30 000007fe`e54eb6ed chrome_child!base::Thread::ThreadMain+0x338
14 00000000`04e4faa0 00000000`7778652d chrome_child!base::`anonymous namespace'::ThreadFunc+0x15d
15 00000000`04e4fb10 00000000`779bc541 kernel32!BaseThreadInitThunk+0xd
16 00000000`04e4fb40 00000000`00000000 ntdll!RtlUserThreadStart+0x1d
windows 上通过写文件将数据传递到命名管道上。
接收
我们在发送的时候,就已经看到部分接收的堆栈了。当IPC线程接收到消息的时候。堆栈如下
3:040> kL
# Child-SP RetAddr Call Site
00 00000000`04f1f8c8 000007fe`e3bba3f5 chrome_child!IPC::ChannelProxy::Context::OnMessageReceivedNoFilter
01 00000000`04f1f8d0 000007fe`e3bc1eed chrome_child!IPC::SyncChannel::SyncContext::OnMessageReceived+0x71
02 00000000`04f1f900 000007fe`e3bc2406 chrome_child!IPC::internal::ChannelReader::DispatchMessageW+0x21
03 00000000`04f1f930 000007fe`e3bc255d chrome_child!IPC::internal::ChannelReader::HandleExternalMessage+0x9a
04 00000000`04f1f980 000007fe`e3bc2818 chrome_child!IPC::internal::ChannelReader::HandleTranslatedMessage+0x99
05 00000000`04f1f9b0 000007fe`e3bc1d8d chrome_child!IPC::internal::ChannelReader::TranslateInputData+0xc4
06 00000000`04f1fa80 000007fe`e3bc035c chrome_child!IPC::internal::ChannelReader::AsyncReadComplete+0x15
07 00000000`04f1fab0 000007fe`e26f37b6 chrome_child!IPC::ChannelWin::OnIOCompleted+0xac
08 00000000`04f1fae0 000007fe`e26f35a0 chrome_child!base::MessagePumpForIO::WaitForIOCompletion+0x186
09 00000000`04f1fb50 000007fe`e26f2ad2 chrome_child!base::MessagePumpForIO::DoRunLoop+0x40
0a 00000000`04f1fb80 000007fe`e26f29cf chrome_child!base::MessagePumpWin::Run+0x42
0b (Inline Function) --------`-------- chrome_child!base::MessageLoop::RunHandler+0x15
0c 00000000`04f1fbc0 000007fe`e26d1ad1 chrome_child!base::RunLoop::Run+0xdf
0d (Inline Function) --------`-------- chrome_child!base::MessageLoop::Run+0x35
0e 00000000`04f1fc10 000007fe`e26d1e28 chrome_child!base::Thread::Run+0x41
0f 00000000`04f1fc70 000007fe`e26db6ed chrome_child!base::Thread::ThreadMain+0x338
10 00000000`04f1fce0 00000000`7740652d chrome_child!base::`anonymous namespace'::ThreadFunc+0x15d
11 00000000`04f1fd50 00000000`7763c541 kernel32!BaseThreadInitThunk+0xd
12 00000000`04f1fd80 00000000`00000000 ntdll!RtlUserThreadStart+0x1d
IO 线程中收到一个IO完成的通知,然后派发和处理这个消息,接着如下这样,将消息派发到Listener线程即主线程中。
// Called on the IPC::Channel thread
bool ChannelProxy::Context::OnMessageReceivedNoFilter(const Message& message) {
listener_task_runner_->PostTask(
FROM_HERE, base::Bind(&Context::OnDispatchMessage, this, message));
return true;
}
之后的堆栈就如上面的发送中的堆栈所示,收到了一个GpuMsg_Initialize_Meta消息,将这个消息进行处理之后在发送给IO线程。