歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux基礎 >> Linux教程 >> Squid的main函數源碼分析

Squid的main函數源碼分析

日期:2017/2/28 15:56:51   编辑:Linux教程

要分析一款開源的軟件除了要弄清楚一些基本的使用和配置之外,其次最重要的就是對源代碼進行分析。對源代碼進行分析首先應從其main函數分析入手,了解他在啟動時的涉及的哪方面的功能,並勾勒出他的運行流程圖,現在squid已經支持windows平台了,並且支持以服務的方式啟動。其代碼如下:

  1. #if USE_WIN32_SERVICE
  2. /* When USE_WIN32_SERVICE is defined, the main function is placed in win32.c */
  3. void WINAPI
  4. SquidWinSvcMain(int argc, char **argv)
  5. {
  6. SquidMain(argc, argv);
  7. }
  8. int
  9. SquidMain(int argc, char **argv)
  10. #else
  11. int
  12. main(int argc, char **argv)
  13. #endif
  14. {
  15. int errcount = 0;
  16. int loop_delay;
  17. #ifdef _SQUID_WIN32_
  18. int WIN32_init_err;
  19. #endif
  20. #if HAVE_SBRK
  21. /*
  22. * HAVE_SBRK - 這個宏的產生我說明一下,這個是用configure產生的,在autoconf.h中能看到,這個是configure做系統
  23. * 函數fun功能性檢查的時候,如果該操作系統支持其系統調用,則在autoconf.h中定義宏HAVE_FUN,FUN是其函數名字的大寫
  24. * sbrk - 是從堆中分配空間,本質是移動一個位置,向後移就是分配空間,向前移就是釋放空間,返回以頁為單位
  25. * 的虛擬內存使用情況,squid用它來計算整個進程的內存使用情況。
  26. */
  27. sbrk_start = sbrk(0);
  28. #endif
  29. debug_log = stderr;
  30. #ifdef _SQUID_WIN32_
  31. if ((WIN32_init_err = WIN32_Subsystem_Init(&argc, &argv)))
  32. return WIN32_init_err;
  33. #endif
  34. /* call mallopt() before anything else */
  35. #if HAVE_MALLOPT
  36. #ifdef M_GRAIN
  37. /* Round up all sizes to a multiple of this */
  38. mallopt(M_GRAIN, 16);
  39. #endif
  40. #ifdef M_MXFAST
  41. /* biggest size that is considered a small block */
  42. mallopt(M_MXFAST, 256);
  43. #endif
  44. #ifdef M_NBLKS
  45. /* allocate this many small blocks at once */
  46. mallopt(M_NLBLKS, 32);
  47. #endif
  48. #endif /* HAVE_MALLOPT */
  49. /* 初始化本地地址local_addr,默認地址any_addr和廣播地址no_addr */
  50. memset(&local_addr, '\0', sizeof(struct in_addr));
  51. safe_inet_addr(localhost, &local_addr);
  52. memset(&any_addr, '\0', sizeof(struct in_addr));
  53. safe_inet_addr("0.0.0.0", &any_addr);
  54. memset(&no_addr, '\0', sizeof(struct in_addr));
  55. safe_inet_addr("255.255.255.255", &no_addr);
  56. /* 用當前時間生成隨機種子 */
  57. squid_srandom(time(NULL));
  58. /* 初始化當前時間 */
  59. getCurrentTime();
  60. squid_start = current_time;
  61. failure_notify = fatal_dump; /* 設置失敗或者出現重大錯誤時候退出的回調函數指針 */
  62. #if defined(USE_WIN32_SERVICE) && defined(_SQUID_WIN32_)
  63. WIN32_svcstatusupdate(SERVICE_START_PENDING, 10000);
  64. #endif
  65. /* 解析命令行參數,如./squid -D -N -d3 之類的 */
  66. mainParseOptions(argc, argv);
  67. #if HAVE_SYSLOG && defined(LOG_LOCAL4)
  68. /* 打開系統日志,將日志寫入系統日志吧 */
  69. openlog(appname, LOG_PID | LOG_NDELAY | LOG_CONS, syslog_facility);
  70. #endif
  71. #if defined(USE_WIN32_SERVICE) && defined(_SQUID_WIN32_)
  72. if (opt_install_service) {
  73. WIN32_InstallService();
  74. return 0;
  75. }
  76. if (opt_remove_service) {
  77. WIN32_RemoveService();
  78. return 0;
  79. }
  80. if (opt_command_line) {
  81. WIN32_SetServiceCommandLine();
  82. return 0;
  83. }
  84. #endif
  85. /* parse configuration file
  86. * note: in "normal" case this used to be called from mainInitialize() */
  87. {
  88. /* 配置文件名稱初始化,這個可也通過命令行的方式指定,默認是squid.conf */
  89. int parse_err;
  90. if (!ConfigFile)
  91. ConfigFile = xstrdup(DefaultConfigFile);
  92. assert(!configured_once);
  93. #if USE_LEAKFINDER
  94. /*
  95. * 內存洩漏檢測功能初始化,通過--enable-leakfinder打開。創建一個哈希表htable,緩存動態內存分配
  96. * 情況,cachemgrRegister注冊獲取內存洩漏跟蹤統計數據的action 。
  97. * 但是奇怪的事,我就沒看到哪些地方在調用leakAdd leakTouch leakFree之類的接口。
  98. */
  99. leakInit();
  100. #endif
  101. /*
  102. * squid提供的內存池功能,這裡主要是對預定義的對象內存分配器初始化,以後這些對象就用這些定義好了的內存分配器來
  103. * 分配內存了!cachemgrRegister注冊獲取內存使用跟蹤統計數據的action 。squid實現的內存池功能比apache簡單多了!
  104. */
  105. memInit();
  106. /*
  107. * squid提供的專用於回調函數參數對象內存分配器初始化,用這個種分配器分配的內存保存了一些其他的信息用於識別和驗證。
  108. * cachemgrRegister注冊獲取回調參數對象跟蹤統計數據的action 。
  109. */
  110. cbdataInit();
  111. /*
  112. * Squid的事件機制的作用是,提供一種觸發機制,可以定時地執行某些操作. Squid任何一個功能模塊中的代碼可以靈活地指定
  113. * “在x秒鐘之後,我要做某操作”,而到了x秒鐘之後,該操作就可以自動地執行。
  114. * 這裡主要是對event的對象內存分配器初始化, cachemgrRegister注冊獲取event對象跟蹤統計數據的action 。
  115. */
  116. eventInit(); /* eventInit() is required for config parsing */
  117. /*
  118. * storeReplSetup()和storeFsSetup(),替換策略模塊和存儲策略模塊選擇的初始化,這些模塊的選擇是通過
  119. * ./configure --enable-storeio=afus,diskd,ufs和 ./configure --enable-removal-policies=heap,lru來確定的!
  120. * 替換和存儲模塊都提供了一個兼容層,這些兼容層只是一個管理功能接口的函數指針對象,初始化就是用用戶
  121. * configure配置的接口來初始化函數指針管理對象。
  122. */
  123. storeFsInit(); /* required for config parsing */
  124. /*
  125. * authSchemeSetup(),squid配置的驗證機制初始化,這個是squid提供給用戶的代理認證,可以通過
  126. * ./configure --enable-auth=basic,digest,ntlm來配置,默認支持basic認證方式。並且需要配置一種
  127. * 對應的外部認證程序,通過--enable-basic-auth-helpers=ncsa完成,這裡只是配置了認證機制basic
  128. * 使用ncsa外部程序來完成認證,這些外部程序都是通過pipe方式來進行通信完成認證的!
  129. */
  130. authenticateSchemeInit(); /* required for config parsing */
  131. /*
  132. * 這個沒什麼的,看起來就像是解析配置文件,默認的配置文件是squid.conf,cachemgrRegister注冊獲取配置數據的action
  133. * 處理過程先設置部分默認值,然後解析配置文件覆蓋或者初始化一些配置值,然後看哪些沒值的就設置默認值,最後配置信息
  134. * 合法化檢查,如果配置信息不合理就退出吧!!
  135. */
  136. parse_err = parseConfigFile(ConfigFile);
  137. if (opt_parse_cfg_only)
  138. return parse_err;
  139. }
  140. setUmask(Config.umask);
  141. /*
  142. * 重復啟動運行監測,如果不是像squid發送進程信號的話,就提示不能重復啟動運行的錯誤。squid進程啟動的時候會向squid.pid
  143. * 寫入當前運行進程的pid,checkRunningPid()就是檢查的這個文件來確認squid是不是已經啟動了!當squid退出的時候會刪除
  144. * squid.pid的這個文件。
  145. */
  146. if (-1 == opt_send_signal)
  147. if (checkRunningPid())
  148. exit(1);
  149. /* Make sure the OS allows core dumps if enabled in squid.conf */
  150. /*
  151. * 這個只是設置os系統參數,允許squid在crash的時候生成coredump文件。
  152. */
  153. enableCoredumps();
  154. /*
  155. * 這個看樣子是測試access方面宏,如果定義了該宏,會#include "test_access.c"這個文件,
  156. * 不過哥哥沒找到這個文件。我想其他版本有吧,先跳過這個不管算��!
  157. */
  158. #if TEST_ACCESS
  159. comm_init();
  160. comm_select_init();
  161. mainInitialize();
  162. test_access();
  163. return 0;
  164. #endif
  165. /*
  166. * squid進程除了可以作為啟動進程外,還可以通過一些命令參數作為管理進程,來完成一些基本的管理工作,
  167. * 如opt_send_signal選項,如果該選項設置了就可以向正在運行的squid進程發送信號,我看了就發送了kill信號!
  168. * 如opt_create_swap_dirs選項,如果該選項設置了就可以創建cache目錄,根據cache_dir配置指令來完成創建。
  169. */
  170. /* send signal to running copy and exit */
  171. if (opt_send_signal != -1) {
  172. /* chroot if configured to run inside chroot */
  173. if (Config.chroot_dir) {
  174. if (chroot(Config.chroot_dir))
  175. fatal("failed to chroot");
  176. no_suid();
  177. } else {
  178. leave_suid();
  179. }
  180. sendSignal();
  181. /* NOTREACHED */
  182. }
  183. if (opt_create_swap_dirs) {
  184. /* chroot if configured to run inside chroot */
  185. if (Config.chroot_dir && chroot(Config.chroot_dir)) {
  186. fatal("failed to chroot");
  187. }
  188. setEffectiveUser();
  189. debug(0, 0) ("Creating Swap Directories\n");
  190. storeCreateSwapDirectories();
  191. return 0;
  192. }
  193. /*
  194. * 這裡squid以後台服務的方式來啟動運行。
  195. */
  196. if (!opt_no_daemon)
  197. watch_child(argv);
  198. setMaxFD();
  199. /* init comm module */
  200. /*
  201. * 現在squid網絡模塊支持devpoll,poll,epoll,kqueue,select和select_win32模式。
  202. * 網絡初始化,這裡包括client-side和server-side套接字fd,pipe,以及文件fd的管理結構fde,內存分配器和套接字狀態管理結構初始化。
  203. */
  204. comm_init();
  205. comm_select_init();
  206. if (opt_no_daemon) {
  207. /* we have to init fdstat here. */
  208. if (!opt_stdin_overrides_http_port)
  209. fd_open(0, FD_LOG, "stdin");
  210. fd_open(1, FD_LOG, "stdout");
  211. fd_open(2, FD_LOG, "stderr");
  212. }
  213. #if defined(USE_WIN32_SERVICE) && defined(_SQUID_WIN32_)
  214. WIN32_svcstatusupdate(SERVICE_START_PENDING, 10000);
  215. #endif
  216. /*
  217. * squid主要信息初始化,這個會將在mainInitialize()功能做詳細的分析。
  218. */
  219. mainInitialize();
  220. #if defined(USE_WIN32_SERVICE) && defined(_SQUID_WIN32_)
  221. WIN32_svcstatusupdate(SERVICE_RUNNING, 0);
  222. #endif
  223. /* main loop */
  224. /*
  225. * 這個應該就是squid的心跳系統,這裡除了處理squid管理發過來的信號之類外,就只處理event事件和讀寫處理。
  226. * 這裡應該就只包括套接字和文件的讀寫吧,整個框架就3點功能:
  227. * - 處理squid管理發過來的信號,do_reconfigure表示是重新加載配置信息,這個處理起來還不簡單啊,要關閉所
  228. * 有端口,所有連接,所有文件讀寫等,然後切換到root用戶,解析配置文件,在然後切換回來運行用戶,然後啟動
  229. * 之前關閉的端口,連接等等信息,太多了!
  230. * - eventRun(),運行event,遍歷event管理列表tasks,如果event->when中滿足當前運行條件,就執行event->func
  231. * 中的函數功能,運行完後從tasks中刪除之,並釋放資源吧。靈活地指定“在x秒鐘之後,我要做某操作”,這個可以做
  232. * 任何事情,不錯。。。
  233. * - 接下來就是網絡套接字和文件io的讀寫!loop_delay = eventNextTime()這個是取得下一個最快將要執行的event
  234. * 時間,loop_delay不能超過1000就是1秒,通過這個時間來在一些端口上設置等待超時時間,comm_select(loop_delay)
  235. * 就是在網絡套接字和文件FD上等待預先設置好了的操作,等成功返回後就用預先設置好了的函數作回調執行處理得到
  236. * 的數據。比如listen FD監聽到來的請求,receive FD接收到來的request和response data,預先設置好了數據發出去
  237. * 去的FD,寫入disk的FD,等等!!!
  238. */
  239. for (;;) {
  240. if (do_reconfigure) {
  241. mainReconfigure();
  242. do_reconfigure = 0;
  243. } else if (do_rotate) {
  244. mainRotate();
  245. do_rotate = 0;
  246. } else if (do_shutdown) {
  247. time_t wait = do_shutdown > 0 ? (int) Config.shutdownLifetime : 0;
  248. debug(1, 1) ("Preparing for shutdown after %d requests\n",
  249. statCounter.client_http.requests);
  250. debug(1, 1) ("Waiting %d seconds for active connections to finish\n",
  251. (int) wait);
  252. do_shutdown = 0;
  253. shutting_down = 1;
  254. #if defined(USE_WIN32_SERVICE) && defined(_SQUID_WIN32_)
  255. WIN32_svcstatusupdate(SERVICE_STOP_PENDING, (wait + 1) * 1000);
  256. #endif
  257. serverConnectionsClose();
  258. eventAdd("SquidShutdown", SquidShutdown, NULL, (double) (wait + 1), 1);
  259. }
  260. eventRun();
  261. if ((loop_delay = eventNextTime()) < 0)
  262. loop_delay = 0;
  263. if (debug_log_flush() && loop_delay > 1000)
  264. loop_delay = 1000;
  265. switch (comm_select(loop_delay)) {
  266. case COMM_OK:
  267. errcount = 0; /* reset if successful */
  268. break;
  269. case COMM_ERROR:
  270. errcount++;
  271. debug(1, 0) ("Select loop Error. Retry %d\n", errcount);
  272. if (errcount == 10)
  273. fatal_dump("Select Loop failed!");
  274. break;
  275. case COMM_TIMEOUT:
  276. break;
  277. case COMM_SHUTDOWN:
  278. SquidShutdown(NULL);
  279. break;
  280. default:
  281. fatal_dump("MAIN: Internal error -- this should never happen.");
  282. break;
  283. }
  284. }
  285. /* NOTREACHED */
  286. return 0;
  287. }
Copyright © Linux教程網 All Rights Reserved