源代码版本和系统
mysql5.7.27
带boost的基于linux系统的源代码
mysqld的启动
尝试源码阅读
入口函数:sql\main.cc
extern int mysqld_main(int argc, char **argv); //告诉编译器,下面是C语言的函数。经常在C++混编的程序中看到
int main(int argc, char **argv)
{
return mysqld_main(argc, argv); //调用的mysqld函数
}
查看mysqld函数定义:
文件sql\mysqld.cc
发现有三个位置存在mysqld_main方法,其中中间一行是注释
win_main in mysqld.cc (D:\vmshare\mysql-5.7.27\sql) : int mysqld_main(int argc, char **argv)
win_main in mysqld.cc (D:\vmshare\mysql-5.7.27\sql) : // For windows, my_init() is called from the win specific mysqld_main
mysqld.cc (D:\vmshare\mysql-5.7.27\sql) line 5315 : int mysqld_main(int argc, char **argv)
这个是什么原因?
继续分析源代码:
5315行的部分,可以看到从5312行至5426行,在这个中间部分的mysqld_main函数是条件编译的部分
基本结构为:
#if defined(_WIN32)
中间定义了一部分的函数
int mysqld_main() .....
//也就是说,如若有定义的 _WIN32的部分,则会才会编译这个部分的代码。如果不是windows平台,则是使用的这个部分的代码
#endif //_WIN32
如若有定义的 _WIN32的部分,则会才会编译这个部分的代码。如果不是windows平台,则是使用的这个部分的代码
具体的这一部分代码结构如下 :
#if defined(_WIN32)
int mysql_service(void *p)
{
if (my_thread_init())
{
flush_error_log_messages();
return 1;
}
if (use_opt_args)
win_main(opt_argc, opt_argv); //编译的时候,如windows平台,则调用win_main的方法
else
win_main(Service.my_argc, Service.my_argv);
my_thread_end();
return 0;
}
/* Quote string if it contains space, else copy */
static char *add_quoted_string(char *to, const char *from, char *to_end)
{
uint length= (uint) (to_end-to);
if (!strchr(from, ' '))
return strmake(to, from, length-1);
return strxnmov(to, length-1, "\"", from, "\"", NullS);
}
/**
Handle basic handling of services, like installation and removal.
@param argv Pointer to argument list
@param servicename Internal name of service
@param displayname Display name of service (in taskbar ?)
@param file_path Path to this program
@param startup_option Startup option to mysqld
@retval
0 option handled
@retval
1 Could not handle option
*/
static bool
default_service_handling(char **argv,
const char *servicename,
const char *displayname,
const char *file_path,
const char *extra_opt,
const char *account_name)
{
省略具体的代码
}
int mysqld_main(int argc, char **argv)
{
/*
When several instances are running on the same machine, we
need to have an unique named hEventShudown through the
application PID e.g.: MySQLShutdown1890; MySQLShutdown2342
*/
int10_to_str((int) GetCurrentProcessId(),my_stpcpy(shutdown_event_name,
"MySQLShutdown"), 10);
/* Must be initialized early for comparison of service name */
system_charset_info= &my_charset_utf8_general_ci;
这中间省略了一部分的代码
/* Start as standalone server */
Service.my_argc=argc;
Service.my_argv=argv;
mysql_service(NULL);
return 0;
}
#endif // _WIN32
查看第一个搜索结果的部分
从4420到4432函数开开始
#ifdef _WIN32
int win_main(int argc, char **argv) 如果是windows,则编译成win_main。
#else
int mysqld_main(int argc, char **argv) 如果不是windows,则直接编译成mysqld_main函数
#endif
{
//一些具体的操作
}
通过如上分析,我们采用linux调试的话,其实其源代码编译的过程为:
main.cc(main方法调用mysqld_main) > mysqld.cc(第一个部分4423行左右的mysqld_main) > 执行具体的启动流程
windows的启动流程:
main.cc(main方法调用mysqld_main) > mysqld.cc(通过_WIN32定义,调用的是5315行左右的mysqld_main方法) > mysqld.cc(5315行左右的mysqld_main方法调用mysql_service(NULL)方法 > mysqld.cc(mysql_service方法又调用了win_main方法)> win_main方法,有4420行左右通过_WIN32的宏定义可以条件编译出来 ,从而最终和linux系统的版本进入到一个{}的方法体内部
原理总结
Mysql为了实现可以在win32平台与类Uninx平台代码共用,将一些公用的函数抽象出来,最终程序进入统一的方法体 {},但是win32和类unix平台启动方式不一样。
遗留问题:
条件编译的这个 _WIN32宏是在哪里定义的?需要进一步学习的。