Chinaunix首页 | 论坛 | 博客
  • 博客访问: 165725
  • 博文数量: 43
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 675
  • 用 户 组: 普通用户
  • 注册时间: 2013-01-26 00:58
文章分类
文章存档

2014年(2)

2013年(41)

我的朋友

分类: C/C++

2013-07-29 11:06:02

lighttpd版本:1.4.32
参考资料:lighttpd源码分析  by高群凯
首先分析它的main函数,弄清程序的流程。
这部分内容在server.c和server.h里面

分为两部分:监控进程或若干个工作进程(可以再配置文件中设置,仅有一个进程)
工作进程是监控进程的子进程,所以很多初始化工作在监控进程工完成,这样工作进程可以很好的继承。

下面就分两部分简单介绍下。
监控进程流程:
1.server结构体初始化


2.读取参数 


3.读取配置文件 (根据参数,如果程序运行的目的是打印配置文件或和检测配置文件,那么现在退出程序)

4.将标准输入和输出重定向到/dev/null,因为该程序用不到


5.安全性设置(不允许setuid-root用户,检查document root)  它的安全性主要体现在三个方面:

chroot(),setUID,setGID

protecting doc root

strict HTTP-header parsing
6.加载插件
7.是否使用pidfile(pidfile主要是用来控制保证只有一个deamon进程运行的)
注解:

pidfile一般用于daemon程序,主要作用是保证在系统中只存在该daemon的一个进程,同时也便于系统统一管理这些daemon程序。

start过程需要处理的问题:

· 1.1 确保系统中没有该daemon的进程。如果有,则不能启动程序。 

· 1.2 在daemon化之后,创建pidfile,写入pid。 

· 1.3 注册atexit(),确保在程序退出时清除pidfile文件。 

stop过程做的处理:

· 2.1 如果pidfile不存在,无需其它动作。 

· 2.2 如果pidfile存在,kill原有进程,并确认进程不存在。在旧进程异常退出时,比如直接用_exit(2)退出程序时,可能pidfile不会被删除,所以在kill进程之后还要确认pidfile文件已被删除。 

restart动作:

· 3.1 stop 

· 3.2 start 


8.如果使用select模型,设置最大fd数
9.各种最大资源数的设置,因为涉及很多结构体,不详述
10.网络部分初始化 network_init
11.插件调用的初始化
12.进程守护化
13.写入pidfile
14打开log文件,之前都是设置写入STDERR。因为转化为daemon了,没有终端关联,必须有输出文件
15配置插件
16丢弃没有使用的配置项
17信号处理函数绑定
18产生子进程(工作进程)
    由监控进程产生工作进程并wait
    (这里将SIGHUP解释为Reset,Recongfig,重新读取配置文件而不重启。

    forwarded_sig_hup在kill后变为1,保证kill只调用一次


    如果受到信号导致SIGTERM或者SIGINT信号

    case SIGTERM: srv_shutdown = 1; break;


    case SIGINT:


     if (graceful_shutdown) srv_shutdown = 1;


     else graceful_shutdown = 1;

    监控进程跳出循环,结束所有子进程,然后回收资源)
这里拷一副图,来自《lighttpd源码分析》


工作进程流程:

1.多路复用初始化 fdevent_init

2.事件注册network_register_fdevents

3.stat_cache_init    //缓存初始化

4.关于FAM的设定//   需要有usr/include/fam.h    在中声明了   base.h:# include 

注解:
FAM(文件变更监视模块)

FAM就是文件变更监视模块,它向应用程序提供了一组API,当指定的文件或目录发生变化时,由其向应用程序发出通知。 

  FAM由两部分组成:后台守护程序fam,它负责接收请求和发送通知;库文件libfam,客户端应用程序用它来与FAM通信。

  若远程主机打开了受监视的文件,本地的fam会与远程主机的fam联系,将请求发送给远程fam。

  Fam也可以在某个文件开始或停止运行时通知它的客户端。(比如:在IRIX交互桌面中,如果一个程序正在运行那么它的图标就会不会闪烁)。 


5.Socket赋值(前面多路复用模块已经初始化了)

6.大循环

{

    if(接到SIGHUP信号)

    {

    调用插件处理HUP信号的函数plugins_call_handle_sighup(srv)

    重新打开log日志文件,并写入收到HUP信号的记录。

l    og_error_cycle

    }

    if(收到时钟信号)

{

    重置handle_sig_alarm

    比较当前时间和服务器上次记录时间,如果不相等则进行下面处理:

    plugins_call_handle_trigger;

    设置服务器记录时间为当前时间;

    stat_cache_trigger_cleanup(srv);

    处理超时连接

    (这里好多结构体对应的函数没见过,先跳过。大体流程就这样)…..

}

根据上面的大体流程,有下面的子模块需要阅读和研究(不够的话补充

server结构体

配置文件结构体

安全性研究

日志系统

复用技术模型

插件链、基本插件模块

网络请求服务相应和流程network部分

文件状态缓存器 stat_cache

其他常用结构体





下面是我阅读这部分代码总结的知识点:

知识点一:SIGINT和SIGTERM的区别(这部分是转载的)

首在这三个信号中,sigkill是不能被捕获的,程序收到这个信号后,一定会退出。这就是kill -9一定能保证将程序杀死的原因。

信号

产生方式

对进程的影响

sigint

通过ctrl+c将会对当进程发送此信号

信号被当前进程树接收到,也就是说,不仅当前进程会收到信号,它的子进程也会收到

sigterm

kill命令不加参数就是发送这个信号

只有当前进程收到信号,子进程不会收到。如果当前进程被kill了,那么它的子进程的父进程将会是init,也就是pid为1的进程

信号收到不一定立即处理,如果在内核态会存在安全隐患

知识点二:sig_atomic_t使得变量的操作具有原子性,比如服务器状态设定,不被其他中断打断

volatile是一个类型(type specifier)。它是被设计用来修饰被不同线程访问和修改的。如果没有volatile,基本上会导致这样的结果:要么无法编写多线程程序,要么失去大量优化的机会。

知识点三:进程的权限问题:涉及到安全性   http://blog.chinaunix.net/uid-27105712-id-3349522.html
知识点四:

sigaction函数的使用

该函数根据参数signum指定的信号编号来设置该信号的处理函数
知识点五:
定时器的使用
http://www.cnblogs.com/wanghetao/archive/2011/12/01/2270628.html

阅读(2668) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~