1.函数执行过程
server.c----->main------->rc = server_main(srv, argc, argv);---->
概述
Lighttpd采用多进程网络服务模型。
进程分两种:监控进程watcher 和 工作进程 workers。
监控进程:fork工作进程并监视工作进程的数目,一旦有工作进程退出,监控进程立即fork新的工作进程。
工作进程:接收客户端请求并做出服务响应。
一般情况下,存在一个监控进程和多个工作进程。
max-worker值默认为0时,没有监控进程,只有一个工作进程。
关于初始化:Lighttpd很多地方内存申请都是采用calloc,malloc()和calloc()的主要区别是前者不能初始化所分配的内存空间,而后者能。
主流程入口文件:server.c
2、如何转化为wachter和worker 转化代码
/* start watcher and workers */
num_childs = srv->srvconf.max_worker;/*存放最大的子进程的数目*/
if (num_childs > 0) {
pid_t pids[num_childs];
pid_t pid;
const int npids = num_childs;
int child = 0;/*child变量用于标记是否为子进程,0代表父进程,1代表子进程*/
unsigned int timer = 0;
for (int n = 0; n < npids; ++n) pids[n] = -1;
while (!child && !srv_shutdown && !graceful_shutdown) {
/*子进程不可进入,srv_shutdown=1 或 graceful_shutdown=1时父进程跳出*/
/*重点注释,child=1表示子进程的child值为1而父进程中的child仍然为0,所以子进程不会再执行此循环进入下一段程序,但是主进程watcher仍然停留在此循环中*/
if (num_childs > 0) {
switch ((pid = fork())) {/*创建子进程*/
case -1:
return -1;
case 0:
child = 1;/*重点注释,子进程标记 child=1表示子进程的child值为1而父进程中的child仍然为0*/
alarm(0);
break;
default:
num_childs--;/*父进程*/
for (int n = 0; n < npids; ++n) {
/*
- 在父进程中,fork返回新创建子进程的进程ID;
- 在子进程中,fork返回0;
- 如果出现错误,fork返回一个负值;
*/
if (-1 == pids[n]) {
pids[n] = pid;
break;
}
}
break;
}
} else {//子进程产生完毕
int status;//保存子进程退出状态
if (-1 != (pid = wait(&status))) {//阻塞等待子进程退出,收尸
srv->cur_ts = time(NULL);
if (plugins_call_handle_waitpid(srv, pid, status) != HANDLER_GO_ON) {
if (!timer) alarm((timer = 5));
continue;
}
switch (fdevent_reaped_logger_pipe(pid)) {
default: break;
case -1: if (!timer) alarm((timer = 5));
/* fall through */
case 1: continue;
}
/**
* check if one of our workers went away
*/
for (int n = 0; n < npids; ++n) {
if (pid == pids[n]) {
pids[n] = -1;
num_childs++;//表示可以再产生新的子进程
break;
}
}
} else {
switch (errno) {
case EINTR://发生中断
srv->cur_ts = time(NULL);
/**
* if we receive a SIGHUP we have to close our logs ourself as we don't
* have the mainloop who can help us here
*/
if (handle_sig_hup) {
handle_sig_hup = 0;
log_error_cycle(srv);//重新打开日志文件
/* forward SIGHUP to workers */
for (int n = 0; n < npids; ++n) {
if (pids[n] > 0) kill(pids[n], SIGHUP);
}
}
if (handle_sig_alarm) {
handle_sig_alarm = 0;
timer = 0;
plugins_call_handle_trigger(srv);//通知组内所有进程
fdevent_restart_logger_pipes(srv->cur_ts);
}
break;
default:
break;
}
}
}
}
/**
* for the parent this is the exit-point
*/
if (!child) { /*重点注释,child=1表示子进程的child值为1 而父进程中的child仍然为0,子进程不执行此程序,进入下一步*/
/** //父进程的退出点,关闭所以工作进程,做一些清理工作(关闭日志,连接的网络资源,插件,内存等)。
* kill all children too
*/
if (graceful_shutdown || graceful_restart) {
/* flag to ignore one SIGINT if graceful_restart */
if (graceful_restart) graceful_restart = 2;
kill(0, SIGINT);
server_graceful_state(srv);
} else if (srv_shutdown) {
kill(0, SIGTERM);
}
return 0;
}
后面的程序下期分享,后面的程序都是worker进程在执行
3、如何转化为wachter和worker 伪代码
4、如何转化为wachter和worker 流程图
5 Lighttpd工作进程处理模型
参考文档:Lighttpd源码分析_高群凯
下载地址:https://download.youkuaiyun.com/download/caofengtao1314/10576306
参考网站:https://blog.youkuaiyun.com/jiange_zh/article/details/50483099