深入学习keepalived之一 keepalived的启动

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);
    }
}

你可能感兴趣的:(深入学习keepalived之一 keepalived的启动)