squid的main函数源码分析
来源:互联网 发布:淘宝怎么买动作片 编辑:程序博客网 时间:2024/04/30 13:22
要分析一款开源的软件除了要弄清楚一些基本的使用和配置之外,其次最重要的就是对源代码进行分析。对源代码进行分析首先应从其main函数分析入手,了解他在启动时的涉及的哪方面的功能,并勾勒出他的运行流程图,现在squid已经支持windows平台了,并且支持以服务的方式启动。其代码如下:
#if USE_WIN32_SERVICE/* When USE_WIN32_SERVICE is defined, the main function is placed in win32.c */void WINAPISquidWinSvcMain(int argc, char **argv){ SquidMain(argc, argv);}intSquidMain(int argc, char **argv)#elseintmain(int argc, char **argv)#endif{ int errcount = 0; int loop_delay;#ifdef _SQUID_WIN32_ int WIN32_init_err;#endif#if HAVE_SBRK /* * HAVE_SBRK- 这个宏的产生我说明一下,这个是用configure产生的,在autoconf.h中能看到,这个是configure做系统 * 函数fun功能性检查的时候,如果该操作系统支持其系统调用,则在autoconf.h中定义宏HAVE_FUN,FUN是其函数名字的大写 * sbrk- 是从堆中分配空间,本质是移动一个位置,向后移就是分配空间,向前移就是释放空间,返回以页为单位 * 的虚拟内存使用情况,squid用它来计算整个进程的内存使用情况。 */ sbrk_start = sbrk(0);#endif debug_log = stderr;#ifdef _SQUID_WIN32_ if ((WIN32_init_err = WIN32_Subsystem_Init(&argc, &argv)))return WIN32_init_err;#endif /* call mallopt() before anything else */#if HAVE_MALLOPT#ifdef M_GRAIN /* Round up all sizes to a multiple of this */ mallopt(M_GRAIN, 16);#endif#ifdef M_MXFAST /* biggest size that is considered a small block */ mallopt(M_MXFAST, 256);#endif#ifdef M_NBLKS /* allocate this many small blocks at once */ mallopt(M_NLBLKS, 32);#endif#endif /* HAVE_MALLOPT */ /* 初始化本地地址local_addr,默认地址any_addr和广播地址no_addr */ memset(&local_addr, '\0', sizeof(struct in_addr)); safe_inet_addr(localhost, &local_addr); memset(&any_addr, '\0', sizeof(struct in_addr)); safe_inet_addr("0.0.0.0", &any_addr); memset(&no_addr, '\0', sizeof(struct in_addr)); safe_inet_addr("255.255.255.255", &no_addr); /* 用当前时间生成随机种子 */ squid_srandom(time(NULL)); /* 初始化当前时间 */ getCurrentTime(); squid_start = current_time; failure_notify = fatal_dump;/* 设置失败或者出现重大错误时候退出的回调函数指针 */#if defined(USE_WIN32_SERVICE) && defined(_SQUID_WIN32_) WIN32_svcstatusupdate(SERVICE_START_PENDING, 10000);#endif /* 解析命令行参数,如./squid -D -N -d3 之类的 */ mainParseOptions(argc, argv);#if HAVE_SYSLOG && defined(LOG_LOCAL4) /* 打开系统日志,将日志写入系统日志吧 */ openlog(appname, LOG_PID | LOG_NDELAY | LOG_CONS, syslog_facility);#endif#if defined(USE_WIN32_SERVICE) && defined(_SQUID_WIN32_) if (opt_install_service) {WIN32_InstallService();return 0; } if (opt_remove_service) {WIN32_RemoveService();return 0; } if (opt_command_line) {WIN32_SetServiceCommandLine();return 0; }#endif /* parse configuration file * note: in "normal" case this used to be called from mainInitialize() */ {/* 配置文件名称初始化,这个可也通过命令行的方式指定,默认是squid.conf */ int parse_err;if (!ConfigFile) ConfigFile = xstrdup(DefaultConfigFile);assert(!configured_once);#if USE_LEAKFINDER/* * 内存泄漏检测功能初始化,通过--enable-leakfinder打开。创建一个哈希表htable,缓存动态内存分配* 情况,cachemgrRegister注册获取内存泄漏跟踪统计数据的action 。* 但是奇怪的事,我就没看到哪些地方在调用leakAdd leakTouch leakFree之类的接口。*/ leakInit();#endif/* * squid提供的内存池功能,这里主要是对预定义的对象内存分配器初始化,以后这些对象就用这些定义好了的内存分配器来* 分配内存了!cachemgrRegister注册获取内存使用跟踪统计数据的action 。squid实现的内存池功能比apache简单多了!*/memInit();/* * squid提供的专用于回调函数参数对象内存分配器初始化,用这个种分配器分配的内存保存了一些其他的信息用于识别和验证。* cachemgrRegister注册获取回调参数对象跟踪统计数据的action 。*/cbdataInit();/* * Squid的事件机制的作用是,提供一种触发机制,可以定时地执行某些操作. Squid任何一个功能模块中的代码可以灵活地指定* “在x秒钟之后,我要做某操作”,而到了x秒钟之后,该操作就可以自动地执行。* 这里主要是对event的对象内存分配器初始化, cachemgrRegister注册获取event对象跟踪统计数据的action 。*/eventInit();/* eventInit() is required for config parsing *//** storeReplSetup()和storeFsSetup(),替换策略模块和存储策略模块选择的初始化,这些模块的选择是通过* ./configure --enable-storeio=afus,diskd,ufs和 ./configure --enable-removal-policies=heap,lru来确定的!* 替换和存储模块都提供了一个兼容层,这些兼容层只是一个管理功能接口的函数指针对象,初始化就是用用户* configure配置的接口来初始化函数指针管理对象。*/storeFsInit();/* required for config parsing *//** authSchemeSetup(),squid配置的验证机制初始化,这个是squid提供给用户的代理认证,可以通过* ./configure --enable-auth=basic,digest,ntlm来配置,默认支持basic认证方式。并且需要配置一种* 对应的外部认证程序,通过--enable-basic-auth-helpers=ncsa完成,这里只是配置了认证机制basic* 使用ncsa外部程序来完成认证,这些外部程序都是通过pipe方式来进行通信完成认证的!*/authenticateSchemeInit();/* required for config parsing *//** 这个没什么的,看起来就像是解析配置文件,默认的配置文件是squid.conf,cachemgrRegister注册获取配置数据的action * 处理过程先设置部分默认值,然后解析配置文件覆盖或者初始化一些配置值,然后看哪些没值的就设置默认值,最后配置信息* 合法化检查,如果配置信息不合理就退出吧!!*/parse_err = parseConfigFile(ConfigFile);if (opt_parse_cfg_only) return parse_err; } setUmask(Config.umask); /* * 重复启动运行监测,如果不是像squid发送进程信号的话,就提示不能重复启动运行的错误。squid进程启动的时候会向squid.pid * 写入当前运行进程的pid,checkRunningPid()就是检查的这个文件来确认squid是不是已经启动了!当squid退出的时候会删除 * squid.pid的这个文件。 */ if (-1 == opt_send_signal)if (checkRunningPid()) exit(1); /* Make sure the OS allows core dumps if enabled in squid.conf */ /* * 这个只是设置os系统参数,允许squid在crash的时候生成coredump文件。 */ enableCoredumps();/** 这个看样子是测试access方面宏,如果定义了该宏,会#include "test_access.c"这个文件,* 不过哥哥没找到这个文件。我想其他版本有吧,先跳过这个不管算了!*/#if TEST_ACCESS comm_init(); comm_select_init(); mainInitialize(); test_access(); return 0;#endif /* * squid进程除了可以作为启动进程外,还可以通过一些命令参数作为管理进程,来完成一些基本的管理工作, * 如opt_send_signal选项,如果该选项设置了就可以向正在运行的squid进程发送信号,我看了就发送了kill信号! * 如opt_create_swap_dirs选项,如果该选项设置了就可以创建cache目录,根据cache_dir配置指令来完成创建。 */ /* send signal to running copy and exit */ if (opt_send_signal != -1) {/* chroot if configured to run inside chroot */if (Config.chroot_dir) { if (chroot(Config.chroot_dir))fatal("failed to chroot"); no_suid();} else { leave_suid();}sendSignal();/* NOTREACHED */ } if (opt_create_swap_dirs) {/* chroot if configured to run inside chroot */if (Config.chroot_dir && chroot(Config.chroot_dir)) { fatal("failed to chroot");}setEffectiveUser();debug(0, 0) ("Creating Swap Directories\n");storeCreateSwapDirectories();return 0; } /* * 这里squid以后台服务的方式来启动运行。 */ if (!opt_no_daemon)watch_child(argv); setMaxFD(); /* init comm module */ /* * 现在squid网络模块支持devpoll,poll,epoll,kqueue,select和select_win32模式。 * 网络初始化,这里包括client-side和server-side套接字fd,pipe,以及文件fd的管理结构fde,内存分配器和套接字状态管理结构初始化。 */ comm_init(); comm_select_init(); if (opt_no_daemon) {/* we have to init fdstat here. */if (!opt_stdin_overrides_http_port) fd_open(0, FD_LOG, "stdin");fd_open(1, FD_LOG, "stdout");fd_open(2, FD_LOG, "stderr"); }#if defined(USE_WIN32_SERVICE) && defined(_SQUID_WIN32_) WIN32_svcstatusupdate(SERVICE_START_PENDING, 10000);#endif /* * squid主要信息初始化,这个会将在mainInitialize()功能做详细的分析。 */ mainInitialize();#if defined(USE_WIN32_SERVICE) && defined(_SQUID_WIN32_) WIN32_svcstatusupdate(SERVICE_RUNNING, 0);#endif /* main loop */ /* * 这个应该就是squid的心跳系统,这里除了处理squid管理发过来的信号之类外,就只处理event事件和读写处理。 * 这里应该就只包括套接字和文件的读写吧,整个框架就3点功能: *- 处理squid管理发过来的信号,do_reconfigure表示是重新加载配置信息,这个处理起来还不简单啊,要关闭所 * 有端口,所有连接,所有文件读写等,然后切换到root用户,解析配置文件,在然后切换回来运行用户,然后启动 * 之前关闭的端口,连接等等信息,太多了! *- eventRun(),运行event,遍历event管理列表tasks,如果event->when中满足当前运行条件,就执行event->func * 中的函数功能,运行完后从tasks中删除之,并释放资源吧。灵活地指定“在x秒钟之后,我要做某操作”,这个可以做 * 任何事情,不错。。。 *- 接下来就是网络套接字和文件io的读写!loop_delay = eventNextTime()这个是取得下一个最快将要执行的event * 时间,loop_delay不能超过1000就是1秒,通过这个时间来在一些端口上设置等待超时时间,comm_select(loop_delay) * 就是在网络套接字和文件FD上等待预先设置好了的操作,等成功返回后就用预先设置好了的函数作回调执行处理得到 * 的数据。比如listen FD监听到来的请求,receive FD接收到来的request和response data,预先设置好了数据发出去 * 去的FD,写入disk的FD,等等!!! */ for (;;) {if (do_reconfigure) { mainReconfigure(); do_reconfigure = 0;} else if (do_rotate) { mainRotate(); do_rotate = 0;} else if (do_shutdown) { time_t wait = do_shutdown > 0 ? (int) Config.shutdownLifetime : 0; debug(1, 1) ("Preparing for shutdown after %d requests\n",statCounter.client_http.requests); debug(1, 1) ("Waiting %d seconds for active connections to finish\n",(int) wait); do_shutdown = 0; shutting_down = 1;#if defined(USE_WIN32_SERVICE) && defined(_SQUID_WIN32_) WIN32_svcstatusupdate(SERVICE_STOP_PENDING, (wait + 1) * 1000);#endif serverConnectionsClose(); eventAdd("SquidShutdown", SquidShutdown, NULL, (double) (wait + 1), 1);}eventRun();if ((loop_delay = eventNextTime()) < 0) loop_delay = 0;if (debug_log_flush() && loop_delay > 1000) loop_delay = 1000;switch (comm_select(loop_delay)) {case COMM_OK: errcount = 0;/* reset if successful */ break;case COMM_ERROR: errcount++; debug(1, 0) ("Select loop Error. Retry %d\n", errcount); if (errcount == 10)fatal_dump("Select Loop failed!"); break;case COMM_TIMEOUT: break;case COMM_SHUTDOWN: SquidShutdown(NULL); break;default: fatal_dump("MAIN: Internal error -- this should never happen."); break;} } /* NOTREACHED */ return 0;}
- squid的main函数源码分析
- Squid的main函数源码分析
- squid main函数剖析
- redis源码分析----main函数
- Appium源码分析(2)-main函数
- RTMPDump源码分析-main函数(1)
- webbench源码分析之main函数
- FreeSWITCH源码分析之主函数main()
- Squid mainInitialize()函数分析
- squid源码分析1 ----EventLoop
- x264源码分析一:main函数和encode函数
- ffmpeg源码分析二:main函数和transcode函数
- Android源码阅读笔记1 - init.c的main函数分析
- 《第一篇 从linux 0.11系统初始化main.c的fork()函数调用分析内核源码》
- squid源码方面的资料太少,想写一系列squid源码分析方面的文章,支持的进!
- Memcached 源码分析——从 main 函数说起
- 文章1:Nginx源码分析—main函数
- nginx源码解析一(main函数分析)
- 申请GoogleMap apikey
- virtualbox设置
- 第一天,基本DOS命令*
- qt 设置中文编码
- SUSE11下编译Subversion客户端
- squid的main函数源码分析
- 如何提升网站排名pr,pv,ip
- Content的startActivity方法需添加FLAG_ACTIVITY_NEW_TASK flag
- 傅立叶变换网文精粹:从光学的物理意义看傅立叶变换
- SDRAM
- cout和printf的区别
- A标签触发onclick事件而不跳转
- poj 2109 注意double 范围
- 基类的构造函数不会被子类继承!!!