As previously analyzed, a renderprocess corresponds to the renerprocesshost in a master process. When is renderprocess created? The answer is to create it during renerprocesshos initialization. The corresponding process is implemented in the browserrenderprocesshost: init function. Let's take a look at this function. The file corresponding to the function is:
SRC \ chrome \ browser \ renderer_host \ browser_render_process_host.cc
Init starts some preparation work, such as getting the pointer to the IO thread object: Base: thread * io_thread = g_browser_process-> io_thread ();
Initialize the communication message filtering objects between processes:
Scoped_refptr <resourcemessagefilter> resource_message_filter (
New resourcemessagefilter (g_browser_process-> resource_dispatcher_host (),
ID (),
Audio_renderer_host _. Get (),
Pluginservice: getinstance (),
G_browser_process-> print_job_manager (),
Profile (),
Widget_helper _));
It is important to create an IPC object. First, initialize a channelid, which identifies a unique named pipeline name belonging to the renerprocesshost, and then create an IPC object with this ID:
Channel _. Reset (
New IPC: syncchannel (channel_id, IPC: Channel: mode_server, this,
Resource_message_filter,
Io_thread-> message_loop (), true,
G_browser_process-> shutdown_event ()));
Next, we will make a judgment on the current running mode. If it is a single process mode, no process will be created, but an renderermainthread will be created in the main process, if it is not in process mode, a new renderprocess is created. The called function is:
Static bool run_renderer_in_process (){
Return run_renderer_in_process _;
}
This is a static member function of the parent class of browserrenderprocesshost. run_renderer_in_process _ is also a static variable. Review the initialization process of the main process. The third parameter tchar * command_lineof chromemain is the parameter passed when chrome.exe is started, as described in the previous chapter, if command_line is -- single-process, it will run in single-process mode. Then, the following code is called to set the value of run_renderer_in_process:
If (single_process)
Renderprocesshost: set_run_renderer_in_process (true );
Return to the previous Code. For a single-process model:
In_process_renderer _. Reset (New renderermainthread (channel_id ));
Base: thread: Options options;
# If! Defined (toolkit_uses_gtk)
// In-process plugins require this to be a UI message loop.
Options. message_loop_type = messageloop: type_ui;
# Else
// We can't have multiple UI loops on GTK, so we don't support
// In-process plugins.
Options. message_loop_type = messageloop: type_default;
# Endif
In_process_renderer _-> startwitexceptions (options );
Onprocesslaunched (); // fake a callback that the process is ready.
First, create the renderermainthread object, and then set the thread type to type_ui. That is to say, this thread is a thread that can receive and process messages from Windows systems, which is completely different from the multi-process model.
Finally, call n_process_renderer _-> startwitexceptions (options) to start the message loop of this thread.
For the standard multi-process model:
CommandLine * cmd_line = new CommandLine (renderer_path );
If (! Renderer_prefix.empty ())
Performance_line-> prependwrapper (renderer_prefix );
Appendrenderercommandline (cmd_line );
Cmd_line-> appendswitchascii (switches: kprocesschannelid, channel_id );
// Spawn the child process asynchronously to avoid blocking the UI thread.
// As long as there's no Renderer prefix, we can use the zygote Process
// At this stage.
Child_process _. Reset (New childprocesslauncher (
# If defined (OS _win)
Filepath (),
# Elif defined (POSIX)
Renderer_prefix.empty (),
Base: environment_vector (),
Channel _-> getclientfiledescriptor (),
# Endif
Performance_line,
This ));
Fast_shutdown_started _ = false;
The main work done above is to create a new renderprocess and pass the channelid to this new process through cmd_line. In this way, the renderprocess and renerprocesshost can establish a one-to-one relationship, to complete normal inter-process communication tasks.
Next, let's take a look at the specific implementation of the creation process. The code is located:
SRC \ chrome \ browser \ child_process_launcher.cc
The Code is as follows:
Childprocesslauncher: childprocesslauncher (
# If defined (OS _win)
Const filepath & exposed_dir,
# Elif defined (OS _posix)
Bool use_zygote,
Const base: environment_vector & environ,
Int ipcfd,
# Endif
CommandLine * cmd_line,
Client * client ){
Context _ = new context ();
Context _-> launch (
# If defined (OS _win)
Exposed_dir,
# Elif defined (OS _posix)
Use_zygote,
Environ,
Ipcfd,
# Endif
Performance_line,
Client );
}
The only task of context _-> launch and context _-> launch is to initiate a task to the browserthread thread and execute the launchinternal function. This function calls handle = sandbox: startprocesswithaccess (cmd_line, exposed_dir );
Startprocesswithaccess first determines the process type through the passed cmd_line. The enumerated type is defined in the childprocessinfo class, as follows:
Enum processtype {
Unknown_process = 1,
Browser_process,
Render_process,
Plugin_process,
Worker_process,
Nacl_loader_process,
Utility_process,
Profile_import_process,
Zygote_process,
Sandbox_helper_process,
Nacl_broker_process,
Gpu_process
};
After a series of judgments, if it is not a sandbox process, call: Base: launchapp (* pai_line, false, false, & process );
For a sandbox process, call result = g_broker_services-> spawntarget (
Performance_line-> getprogram (). Value (). c_str (),
Cmd_line-> command_line_string (). c_str (),
Policy, & target );