1.keepalived的启动过程:
启动健康检查子进程和vrrp子进程。其中_WITH_LVS_,_WITH_VRRP_在configure和configure.in文件中定义。
源码如下:
/* Daemon init sequence */ static void start_keepalived(void) { #ifdef _WITH_LVS_ /* start healthchecker child */ if (daemon_mode & 2 || !daemon_mode) start_check_child(); #endif #ifdef _WITH_VRRP_ /* start vrrp child */ if (daemon_mode & 1 || !daemon_mode) start_vrrp_child(); #endif }
2. 启动健康检查子进程。
/* Register CHECK thread */ int start_check_child(void) { #ifndef _DEBUG_ pid_t pid; int ret; /* Initialize child process */ pid = fork(); if (pid < 0) { log_message(LOG_INFO, "Healthcheck child process: fork error(%s)" , strerror(errno)); return -1; } else if (pid) { checkers_child = pid; log_message(LOG_INFO, "Starting Healthcheck child process, pid=%d" , pid); /* Start respawning thread */ thread_add_child(master, check_respawn_thread, NULL, pid, RESPAWN_TIMER); return 0; } /* Opening local CHECK syslog channel */ openlog(PROG_CHECK, LOG_PID | ((debug & 1) ? LOG_CONS : 0), (log_facility==LOG_DAEMON) ? LOG_LOCAL2 : log_facility); /* Child process part, write pidfile */ if (!pidfile_write(checkers_pidfile, getpid())) { log_message(LOG_INFO, "Healthcheck child process: cannot write pidfile"); exit(0); } /* Create the new master thread */ signal_handler_destroy(); thread_destroy_master(master); master = thread_make_master(); /* change to / dir */ ret = chdir("/"); if (ret < 0) { log_message(LOG_INFO, "Healthcheck child process: error chdir"); } /* Set mask */ umask(0); #endif /* If last process died during a reload, we can get there and we * don't want to loop again, because we're not reloading anymore. */ UNSET_RELOAD; /* Signal handling initialization */ check_signal_init(); /* Start Healthcheck daemon */ start_check(); /* Launch the scheduling I/O multiplexer */ launch_scheduler(); /* Finish healthchecker daemon process */ stop_check(); exit(0); }
debug模式暂且不考虑。
2.1 健康检查信号初始化
/* CHECK Child signal handling */ void check_signal_init(void) { signal_handler_init(); signal_set(SIGHUP, sighup_check, NULL); signal_set(SIGINT, sigend_check, NULL); signal_set(SIGTERM, sigend_check, NULL); signal_ignore(SIGPIPE); } /* Handlers intialization */ void signal_handler_init(void) { int n = pipe(signal_pipe); assert(!n); fcntl(signal_pipe[0], F_SETFL, O_NONBLOCK | fcntl(signal_pipe[0], F_GETFL)); fcntl(signal_pipe[1], F_SETFL, O_NONBLOCK | fcntl(signal_pipe[1], F_GETFL)); signal_SIGHUP_handler = NULL; signal_SIGINT_handler = NULL; signal_SIGTERM_handler = NULL; signal_SIGCHLD_handler = NULL; }
2.2 启动健康检查后台程序
/* Daemon init sequence */ static void start_check(void) { /* Initialize sub-system */ ipvs_start(); init_checkers_queue(); #ifdef _WITH_VRRP_ init_interface_queue(); kernel_netlink_init(); #endif #ifdef _WITH_SNMP_ if (!reload && snmp) check_snmp_agent_init(); #endif /* Parse configuration file */ global_data = alloc_global_data(); check_data = alloc_check_data(); init_data(conf_file, check_init_keywords); if (!check_data) { stop_check(); return; } /* Post initializations */ log_message(LOG_INFO, "Configuration is using : %lu Bytes", mem_allocated); /* SSL load static data & initialize common ctx context */ if (!init_ssl_ctx()) { stop_check(); return; } /* Processing differential configuration parsing */ if (reload) { clear_diff_services(); copy_srv_states(); } /* Initialize IPVS topology */ if (!init_services()) { stop_check(); return; } /* Dump configuration */ if (debug & 4) { dump_global_data(global_data); dump_check_data(check_data); } #ifdef _WITH_VRRP_ /* Initialize linkbeat */ init_interface_linkbeat(); #endif /* Register checkers thread */ register_checkers_thread(); }
2.3 启动I/O复用分发调度器
/* Our infinite scheduling loop */ void launch_scheduler(void) { thread_t thread; signal_set(SIGCHLD, thread_child_handler, master); /* * Processing the master thread queues, * return and execute one ready thread. */ while (thread_fetch(master, &thread)) { /* Run until error, used for debuging only */ #ifdef _DEBUG_ if ((debug & 520) == 520) { debug &= ~520; thread_add_terminate_event(master); } #endif thread_call(&thread); } }