本文主要分析chrome.dll中的ChromeMain函数。
DLLEXPORT int __cdecl ChromeMain(HINSTANCE instance,
sandbox::SandboxInterfaceInfo* sandbox_info,
TCHAR* command_line) {
#elif defined(OS_POSIX)
int ChromeMain(int argc, const char** argv) {
#endif
#if defined(OS_MACOSX)
// If Breakpad is not present then turn off os crash dumps so we don't have
// to wait eons for Apple's Crash Reporter to generate a dump.
if (IsCrashReporterDisabled()) {
DebugUtil::DisableOSCrashDumps();
}
#endif
RegisterInvalidParamHandler();
// The exit manager is in charge of calling the dtors of singleton objects.
base::AtExitManager exit_manager;
// We need this pool for all the objects created before we get to the
// event loop, but we don't want to leave them hanging around until the
// app quits. Each "main" needs to flush this pool right before it goes into
// its main event loop to get rid of the cruft.
base::ScopedNSAutoreleasePool autorelease_pool;
#if defined(OS_POSIX)
base::GlobalDescriptors* g_fds = Singleton<base::GlobalDescriptors>::get();
g_fds->Set(kPrimaryIPCChannel,
kPrimaryIPCChannel + base::GlobalDescriptors::kBaseDescriptor);
#if defined(OS_LINUX)
g_fds->Set(kCrashDumpSignal,
kCrashDumpSignal + base::GlobalDescriptors::kBaseDescriptor);
#endif
#endif
// Initialize the command line.
#if defined(OS_WIN)
CommandLine::Init(0, NULL);
#else
CommandLine::Init(argc, argv);
#endif
#if defined(OS_MACOSX)
// Needs to be called after CommandLine::Init().
InitCrashProcessInfo();
#endif
const CommandLine& parsed_command_line = *CommandLine::ForCurrentProcess();
#if defined(OS_WIN)
// Must do this before any other usage of command line!
if (HasDeprecatedArguments(parsed_command_line.command_line_string()))
return 1;
#endif
#if defined(OS_POSIX)
// Always ignore SIGPIPE. We check the return value of write().
CHECK(signal(SIGPIPE, SIG_IGN) != SIG_ERR);
#endif // OS_POSIX
int browser_pid;
std::wstring process_type =
parsed_command_line.GetSwitchValue(switches::kProcessType);
if (process_type.empty()) {
browser_pid = base::GetCurrentProcId();
} else {
#if defined(OS_WIN)
std::wstring channel_name =
parsed_command_line.GetSwitchValue(switches::kProcessChannelID);
browser_pid = StringToInt(WideToASCII(channel_name));
DCHECK(browser_pid != 0);
#else
browser_pid = base::GetCurrentProcId();
#endif
#if defined(OS_POSIX)
// When you hit Ctrl-C in a terminal running the browser
// process, a SIGINT is delivered to the entire process group.
// When debugging the browser process via gdb, gdb catches the
// SIGINT for the browser process (and dumps you back to the gdb
// console) but doesn't for the child processes, killing them.
// The fix is to have child processes ignore SIGINT; they'll die
// on their own when the browser process goes away.
// Note that we *can't* rely on DebugUtil::BeingDebugged to catch this
// case because we are the child process, which is not being debugged.
if (!DebugUtil::BeingDebugged())
signal(SIGINT, SIG_IGN);
#endif
}
SetupCRT(parsed_command_line);
// Initialize the Chrome path provider.
app::RegisterPathProvider();
chrome::RegisterPathProvider();
// Initialize the Stats Counters table. With this initialized,
// the StatsViewer can be utilized to read counters outside of
// Chrome. These lines can be commented out to effectively turn
// counters 'off'. The table is created and exists for the life
// of the process. It is not cleaned up.
// TODO(port): we probably need to shut this down correctly to avoid
// leaking shared memory regions on posix platforms.
if (parsed_command_line.HasSwitch(switches::kEnableStatsTable)) {
std::string statsfile =
StringPrintf("%s-%d", chrome::kStatsFilename, browser_pid);
StatsTable *stats_table = new StatsTable(statsfile,
chrome::kStatsMaxThreads, chrome::kStatsMaxCounters);
StatsTable::set_current(stats_table);
}
StatsScope<StatsCounterTimer>
startup_timer(chrome::Counters::chrome_main());
// Enable the heap profiler as early as possible!
EnableHeapProfiler(parsed_command_line);
// Enable Message Loop related state asap.
if (parsed_command_line.HasSwitch(switches::kMessageLoopHistogrammer))
MessageLoop::EnableHistogrammer(true);
// Checks if the sandbox is enabled in this process and initializes it if this
// is the case. The crash handler depends on this so it has to be done before
// its initialization.
SandboxInitWrapper sandbox_wrapper;
#if defined(OS_WIN)
sandbox_wrapper.SetServices(sandbox_info);
#endif
sandbox_wrapper.InitializeSandbox(parsed_command_line, process_type);
#if defined(OS_WIN)
_Module.Init(NULL, instance);
#endif
// Notice a user da
const std::wstring user_da
parsed_command_line.GetSwitchValue(switches::kUserDataDir);
if (!user_da
CHECK(PathService::Override(chrome::DIR_USER_DA
bool single_process =
#if defined (GOOGLE_CHROME_BUILD)
// This is an unsupported and not fully tested mode, so don't enable it for
// official Chrome builds.
false;
#else
parsed_command_line.HasSwitch(switches::kSingleProcess);
#endif
if (single_process)
RenderProcessHost::set_run_renderer_in_process(true);
#if defined(OS_MACOSX)
// TODO(port-mac): This is from renderer_main_platform_delegate.cc.
// shess tried to refactor things appropriately, but it sprawled out
// of control because different platforms needed different styles of
// initialization. Try again on
// architecture needed and where it should live.
if (single_process)
InitWebCoreSystemInterface();
#endif
bool icu_result = icu_util::Initialize();
CHECK(icu_result);
logging::OldFileDeletionState file_state =
logging::APPEND_TO_OLD_LOG_FILE;
if (process_type.empty()) {
file_state = logging::DELETE_OLD_LOG_FILE;
}
logging::InitChromeLogging(parsed_command_line, file_state);
#ifdef NDEBUG
if (parsed_command_line.HasSwitch(switches::kSilentDumpOnDCHECK) &&
parsed_command_line.HasSwitch(switches::kEnableDCHECK)) {
#if defined(OS_WIN)
logging::SetLogReportHandler(ChromeAssert);
#endif
}
#endif // NDEBUG
if (!process_type.empty())
CommonSubprocessInit();
startup_timer.Stop(); // End of Startup Time Measurement.
MainFunctionParams main_params(parsed_command_line, sandbox_wrapper,
&autorelease_pool);
// TODO(port): turn on these main() functions as they've been de-winified.
int rv = -1;
if (process_type == switches::kRendererProcess) {
rv = RendererMain(main_params);
} else if (process_type == switches::kPluginProcess) {
rv = PluginMain(main_params);
} else if (process_type == switches::kUtilityProcess) {
rv = UtilityMain(main_params);
} else if (process_type == switches::kWorkerProcess) {
#if defined(OS_WIN)
rv = WorkerMain(main_params);
#else
NOTIMPLEMENTED();
#endif
} else if (process_type == switches::kZygoteProcess) {
#if defined(OS_LINUX)
if (ZygoteMain(main_params)) {
// Zygote::HandleForkRequest may have reallocated the command
// line so update it here with the new version.
const CommandLine& parsed_command_line =
*CommandLine::ForCurrentProcess();
MainFunctionParams main_params(parsed_command_line, sandbox_wrapper,
&autorelease_pool);
RendererMain(main_params);
}
#else
NOTIMPLEMENTED();
#endif
} else if (process_type.empty()) {
#if defined(OS_LINUX)
// Glib type system initialization. Needed at least for gconf,
// used in net/proxy/proxy_config_service_linux.cc. Most likely
// this is superfluous as gtk_init() ought to do this. It's
// definitely harmless, so retained as a reminder of this
// requirement for gconf.
g_type_init();
// gtk_init() can change |argc| and |argv|, but nobody else uses them.
gtk_init(&argc, const_cast<char***>(&argv));
SetUpGLibLogHandler();
#endif
ScopedOleInitializer ole_initializer;
rv = BrowserMain(main_params);
} else {
NOTREACHED() << "Unknown process type";
}
if (!process_type.empty()) {
ResourceBundle::CleanupSharedInstance();
}
#if defined(OS_WIN)
#ifdef _CRTDBG_MAP_ALLOC
_CrtDumpMemoryLeaks();
#endif // _CRTDBG_MAP_ALLOC
_Module.Term();
#endif
logging::CleanupChromeLogging();
return rv;
}
Line 15 RegisterInvalidParamHandler();
主要是注册一些回调函数,用于调试和定位(后续采用在代码中增加一些中文注释的方法来解释)
void RegisterInvalidParamHandler() {
#if defined(OS_WIN)
//当调用CRT函数时,参数不合法时,将调用InvalidParameter函数
//InvalidParameter函数也就是产生中断,触发CrashReport服务
_set_invalid_parameter_handler(InvalidParameter);
//当系统调用纯虚函数时,将调用PureCall函数,用于调试
_set_purecall_handler(PureCall);
// Gather allocation failure.
//当内存分配失败时,将调用On
std::set_new_handler(&On
// Also enable the new handler for malloc() based failures.
//支持Malloc模式
_set_new_mode(1);
#endif
}
Line 50 -- Line54可以不用关注,主要是为了规避早期Chrome的一个BUG而已。
LIne61 -- Line 75主要是获取当前Browser进程的ID。因为当前启动的是Browser进程,所以获取的肯定是Browser ID。
Line 91 设置CRT参数,比较简单。
Line 94 -- Line 95 主要初始化各种路径辅助类PathService参数。该类主要提供各种路径服务,比如获取当前目录,用户数据存储目录等服务。
Line 103 -- Line110 当启动参数中包含了 --enable-stats-table时,将初始化状态统计表辅助类,用于统计线程数量。
Line 112 -- Line 114 初始化状态统机辅助类StatsCounterTimer,该类将会启动一个计数器,在这里主要统计本函数所花时间。
Line 116 EnableHeapProfiler(parsed_command_line); 加载memory_watcher.dll,Chrome中的一个辅助类,用于统计chrome的内存占用情况。在Chrome中按下Shift + Esc可以查看内存情况,在后面就是memory_watch.dll起作用。
Line 119 -- Line120 当Chrome启动模式指定了message-loop-histogrammer模式时,用于启动线程消息频率统计功能,当在浏览器地址栏输入about:histograms/Loop时,可以查看到效果(前提是以message-loop-histogrammer模式启动,缺省情况下是不会启动的)。
Line 125 -- Line 133 主要是初始化SandBox服务。Chrome的Crash Report服务依赖于SandBox业务,所以这个服务需要尽早启动,保证Crash Report功能有效。
Line 135 -- Line 139 如果启动时参数中用户指定了用户数据目录,则在PathService类中替换用户数据目录为用户制定的目录。
Line 141 -- Line 159 检测启动参数是否包含了--single-process参数,如果包含了该参数,则采用单进程模式,Renderer也将包含在Browser进程中。下面这两幅图可以明显的看出在两种进程模式下的进程情况。相关的进程模式可以参考另外一篇文章(尚未发出),也可参考Chrome的官方网站说明。
单进程模式下的进程模式(所有页面都在同一进程中,与FireFox,IE一样模式)
缺省模式下的进程模式(每一个网站实例一个进程)
Line 161 -- Line 162 初始化Unicode语言库。IBM提供的一个多语言支持库,比较大。
Line 164 -- Line 169 初始化LOG库,涉及到一个重新启动Chrome时是否删除旧的LOG选项。
process_type这个参数,在缺省情况下,都是为brower进程,但是在启动时也可以指定当前进程类型为Renderer、Plugin、Utility、Worker。这个主要通过启动参数--type=XXX来指定(这里还不是很清楚,后续搞清楚后再更新)。
Line 180 -- Line 245 主要根据不同的进程类型(process_type),调用下一步的初始化过程。在缺省情况下(不指定type参数),将会执行下一个函数BrowserMain,那将是一个更复杂一些的函数。
总结一下,在本函数中,主要也是初始化一些辅助库、全局参数等,相对起来比较好理解。
到目前为止,应该说还没有进入正题,Chrome的两个核心进程Browser和Renderer的初始化工作还没有开始。
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/xingtian713/archive/2009/07/19/4362319.aspx
评论