標籤:
在mysql的原始碼目錄中,sql目錄是mysql原始碼中經常變化的目錄之一,也是MySQL伺服器核心最為核心和重要的目錄。
sql目錄除了包含mysqld.cc這一MySQL main函數所在檔案外,還包括了各類SQL語句的解析/實現。
在sql目錄下的main.cc裡面就調用了一個mysqld_main(),但是mysql裡面好像有一個win_main()和mysqld_main(),
當時我就比較奇怪,剛好一個對應於windows一個對應於linux下的呀。當時想了半天,沒搞明白。後來又看了一遍mysqld_main.cc,才有點看明白了。
實際上在windows下和linuxmysql伺服器啟動的環境和方式是不一樣的,但是mysql為了偷懶只搞了一套原始碼,這樣發布項目的時候是方便了,尼瑪windows和linux只要一套原始碼就行了,但是讀起來錯綜複雜的,各種條件編譯命令眼花繚亂,讓你看不清真相。
mysql在windows和linux上啟動服務的過程有一部分代碼是相似的,這一部分代碼就根據是否定義了_WIN32來決定是命名為win_main()還是mysqld_main();如果是命名為win_main()那麼我們在後面還要有一個mysqld_main()來調用這個win_main(),而如果是mysqld_main(),那麼後面另外一個mysqld_main()就不需要再定義了。
#ifdef _WIN32// 如果定義了_WIN32,則會編譯win_main()int win_main(int argc, char **argv)#elseint mysqld_main(int argc, char **argv)// 如果沒有定義了_WIN32,則會編譯mysqld_main(){// 這個是windows上和linux伺服器啟動時代碼相同的部分// 當然裡面也有很多的編譯預先處理命令}#endif#if defined(_WIN32)int mysqld_main(int argc, char **argv){// 這裡是用於windows上的mysqld_main();}#endif // _WIN32 這個endif對應於 5021行的if defined(_WIN32)
就是這幾個編譯命令決定了是走向windows還是linux,下面我們再來看看mysqld_main()是如何調用win_main()的,
如果你在mysqld_main()直接找win_main()那是找不到滴,這裡呢在有個函數叫mysql_service(void *p):
#if defined(_WIN32)// 如果定義了_WIN32 int mysql_service(void *p)// 居然是在這兒調用了win_main(){ if (my_thread_init()) { flush_error_log_messages(); return 1; } if (use_opt_args) win_main(opt_argc, opt_argv);// 對於win_main()的調用 else win_main(Service.my_argc, Service.my_argv);// 對於win_main()的調用 my_thread_end(); return 0;}
哈哈,找到了對win_main()的調用,所以可以肯定mysqld_main()裡面也調用了mysql_service(void *p):
找找看,果真有
if (Service.GetOS()) /* true NT family */// 也就是說這個是用於NT上的{char file_path[FN_REFLEN]; my_path(file_path, argv[0], ""); /* Find name in path */ fn_format(file_path,argv[0],file_path,"", MY_REPLACE_DIR | MY_UNPACK_FILENAME | MY_RESOLVE_SYMLINKS); if (argc == 2) {if (!default_service_handling(argv, MYSQL_SERVICENAME, MYSQL_SERVICENAME, file_path, "", NULL))return 0;if (Service.IsService(argv[1])) /* Start an optional service */{/*Only add the service name to the groups read from the config fileif it‘s not "MySQL". (The default service name should be ‘mysqld‘but we started a bad tradition by calling it MySQL from the startand we are now stuck with it.*/if (my_strcasecmp(system_charset_info, argv[1],"mysql"))load_default_groups[load_default_groups_sz-2]= argv[1];windows_service= true;Service.Init(argv[1], mysql_service);// 這個裡面調用了mysql_service,也就是說會間接的調用到win_main()return 0;} } else if (argc == 3) /* install or remove any optional service */ {if (!default_service_handling(argv, argv[2], argv[2], file_path, "", NULL))return 0;if (Service.IsService(argv[2])){/*mysqld was started asmysqld --defaults-file=my_path\my.ini service-name*/use_opt_args=1;opt_argc= 2; // Skip service-nameopt_argv=argv;windows_service= true;if (my_strcasecmp(system_charset_info, argv[2],"mysql"))load_default_groups[load_default_groups_sz-2]= argv[2];Service.Init(argv[2], mysql_service);// 這個裡面調用了mysql_service,也就是說會間接的調用到win_main()return 0;} } else if (argc == 4 || argc == 5) {/*This may seem strange, because we handle --local-service whilepreserving 4.1‘s behavior of allowing any one other argument that ispassed to the service on startup. (The assumption is that this is--defaults-file=file, but that was not enforced in 4.1, so we don‘tenforce it here.)*/const char *extra_opt= NullS;const char *account_name = NullS;int index;for (index = 3; index < argc; index++){if (!strcmp(argv[index], "--local-service"))account_name= "NT AUTHORITY\\LocalService";elseextra_opt= argv[index];}if (argc == 4 || account_name)if (!default_service_handling(argv, argv[2], argv[2], file_path, extra_opt, account_name))return 0;} else if (argc == 1 && Service.IsService(MYSQL_SERVICENAME)) {/* start the default service */windows_service= true;Service.Init(MYSQL_SERVICENAME, mysql_service);// 這個裡面調用了mysql_service,也就是說會間接的調用到win_main()return 0; }}
就看了這一點先寫這麼多?
初看mysql原始碼之mysql.cc