如果debug 状态下运行 pgpool-II, 会发现它生成了很多的子进程。
这些子进程是如何生成和利用的?
看源代码中的作法:
pgpool.conf 配置文件中有如下选项:num_init_children
在main.c程序中,有如下的代码部分(去掉了一部分无关代码):
/* * pgpool main program */ int main(int argc, char **argv) { …… /* fork the children */ for (i=0;i<pool_config->num_init_children;i++) { process_info[i].pid = fork_a_child(unix_fd, inet_fd, i); process_info[i].start_time = time(NULL); } /* set up signal handlers */ pool_signal(SIGTERM, exit_handler); pool_signal(SIGINT, exit_handler); pool_signal(SIGQUIT, exit_handler); pool_signal(SIGCHLD, reap_handler); pool_signal(SIGUSR1, failover_handler); pool_signal(SIGUSR2, wakeup_handler); pool_signal(SIGHUP, reload_config_handler); /* create pipe for delivering event */ if (pipe(pipe_fds) < 0) { pool_error("failed to create pipe"); myexit(1); } pool_log("%s successfully started. version %s (%s)",
PACKAGE, VERSION, PGPOOLVERSION); /* * This is the main loop */ for (;;) { …… } pool_shmem_exit(0); }
也就是说,有多少个num_init_children, 就要fork()多少次。
再看具体的 fork_a_child 函数:
/* * fork a child */ pid_t fork_a_child(int unix_fd, int inet_fd, int id) { pid_t pid; pid = fork(); if (pid == 0) { …… /* call child main */ POOL_SETMASK(&UnBlockSig); reload_config_request = 0; my_proc_id = id; run_as_pcp_child = false; do_child(unix_fd, inet_fd); } else if (pid == -1) { pool_error("fork() failed. reason: %s", strerror(errno)); myexit(1); } return pid; }
从上面可以看出来,每fork一个进程,就会执行 do_child函数,也就是说各个子进程就开始工作工作了。
do_child函数的具体内容如下:
/* * child main loop */ void do_child(int unix_fd, int inet_fd) { …… for (;;) { …… /* perform accept() */ frontend = do_accept(unix_fd, inet_fd, &timeout); if (frontend == NULL)/* connection request from frontend timed out */ { …… } …… /* query process loop */ for (;;) { …… } …… } child_exit(0); }
do_child函数里面调用 do_accept函数,如果客户端有请求近来,就会开始响应客户端,开始工作。