1.daemon特征
	1.它的生命周期很长,通常,一个daemon会在系统启动的时候被创建并一直运行直至系统被关闭
	2.它在后台运行并且不拥有控制终端。控制终端的缺失,确保了内核永远不会为daemon自动生成
	  任何控制信号以及终端相关的信号(SIGINT,SIGTSTP和SIGHUP)


2.创建一个daemon
	要变成一个daemon,一个程序需要完成如下步骤:
	1.执行一个 fork(), 关闭父进程,子进程继续执行。原因如下:
		1.假设daemon是从命令行启动,父进程的终止会被shell发现,shell发现之后会显示出另一个shell
		  提示符并让子进程继续在后台运行。
		2.子进程被确保不会成为进程组的首进程,因为它从父进程那里继承了进程组ID并且拥有了自己唯一的进程ID,
		  而这个进程ID与继承而来的进程组ID是不同的,这样才能成功执行下面的步骤
	2.子进程调用 setsid()开启一个新的会话并释放它与控制终端之间的所有关联。
	3.如果daemon从来没有打开过终端设备,那么久无需担心daemon会重新请求一个控制终端了。如果daemon后面可能会打开
	  一个控制终端,那么必须要采取措施来确保这个设备不会成为控制终端。可以通过下面2种方式实现:
	  	1.在所欲可能应用到的一个终端设备上的open()调用指定O_NOCTTY标记
	  	2.或者更简单的说,在 setsid() 调用之后执行第二个 fork(),然后再次让父进程退出,并让孙子进程继续。这样就确保了
	  	  子进程不会成为会话组长。
	4.清除进程的umask以确保daemon创建文件和目录时拥有所需的权限
	5.修改进程的当前工作目录,通常会修改为根目录(/)。这样做是必要的,因为daemon通常会一直运行直到系统关闭。如果daemon的当前工作
      目录为不包含/的文件系统,那么久无法卸载该文件系统。或者daemon可以将工作目录修改为完成任务时所在的目录后者配置文件中定义的一个
      目录,只要包含这个目录的文件系统永远不会被卸载即可。
    6.关闭daemon从父进程继承而来的所有打开的文件描述符。
    	由于daemon失去了控制终端并且是在后台运行的,因此让daemon保持文件描述符0,1,2的打开状态毫无意义,因为它们就是指向终端。
      此外,由于无法卸载长期运行的daemon打开的文件所在的文件系统,因此,通常的做法是关闭所有无用的打开着的文件描述符,因为文件
      描述符是一种有限的资源。
    7.在关闭了文件描述符0,1,2之后,daemon 通常会打开 /dev/null 并使用dup2()使这些描述符指向这个设备。之所以这么做原因如下:
    	1.它确保了daemon调用了在这些文件描述符上执行IO的库函数时,不会出现意外的失败
    	2.它防止了daemon后面使用描述符1或者2打开一个文件的情况,因为库函数会将这些诶描述符当作标准输入和标准错误来写数据。

    ? 表示没有控制终端


3.编写daemon指南
	一个daemon通常只有在系统关闭时才会终止。很多标准的daemon是通过在系统关闭时执行特定的应用程序的脚本来停止的。而不以这种方式
  终止的daemon会收到一个 SIGTERM 信号,因为在系统关闭时 init 进程会向所有的子进程发送这个信号。在默认情况下,SIGTERM 会终止
  一个进程,如果daemon在终止之前需要做清理工作,那么就需要为这个信号建立一个处理器。这个处理器必须能够快速的完成清理工作,因为init
  会在发完 SIGTERM 信号的 5 秒后,发送一个 SIGKILL 信号。
  	由于 daemon 是长期运行的,因此要特别小心内存泄漏问题和文件描述符泄漏(即应用程序没有关闭打开的文件描述符)。
  	很多deamon需要确保同一时刻只要一个实例处于活跃状态(文件锁?)。


4.使用 SIGHUP 重新初始化一个 daemon
	由于很多daemon需要持续运行,因此在设计daemon程序时需要克服一些障碍:
		1.通常daemon会在启动时从相关的配置文件中读取操作参数,但有些时候需要在不重启daemon的情况下快速修改这些参数(重新读取配置)
		2.一些daemon会产生日志。如果daemon永远不关闭日志的话,那么日志文件就会无限的增长,最终会阻塞文件系统(即使删除了一个文件的文件名,
		  只要有进程还打开这个文件,那么这个文件就会一直存在下去)。这里需要有一个机制来告诉daemon关闭其日志并打开一个新文件,这样就能够在需要的
		  时候轮转日志文件了。(日志切割)
	在解决这2个问题的方案是让 daemon 为 SIGHUP 建立一个处理器,并且在收到这个信号的时候采取所需的措施。当控制进程与控制终端断开连接之后会生成 SIGHUP信号。
  由于 daemon没有控制终端,因此内核永远不会向 daemon 发送这个信号。这样 daemon 就可以使用 SIGHUP 信号来达到目的了。


5.使用syslog记录消息和错误
	在编写daemon时碰到一个问题是如何显示错误消息。由于daemon是在后台运行的,因此无法像其他应用程序一样将消息输出到关联终端。
	syslog 主要有2个组件:syslogd daemon 和 syslog(3)库函数
	System Log daemon syslogd 从2个不同的源接收日志消息:
		1.UNIX domain socket /dev/log, 它保存本地产生的日志
		2.Internet domain socket ,它保存通过 TCP/IP 网络发送的消息

	每条由 syslogd 处理的消息都具备几个特性,其中包括一个 facility ,它指定了产生消息的程序类型;还有一个是 level,它指定了日志的严重程度。
  syslogd daemon 会检查每个消息的 facility 和 level,然后根据一个相关的配置文件 /etc/syslog.conf 中的指令将消息传递到计划人可能的目的地之一。
  可能的目的地包括终端或者虚拟控制台,磁盘文件,FIFO,一个或者多个登录过的用户以及另外一个系统上的通过 TCP/IP 网络连接的进程(将消息发送到另外一个系统
  的进程有助于将多个系统中的日志集中到一个位置以降低管理负担)。一条消息可能被发送到多个目的地,具备不同的 facility 和 level 组合的消息可以被发送到不同
  的目的地或者不同的目的地实例。
    发送到另外一个系统,还有助于发现系统非法入侵。攻击者会删除日志,就意味着也要攻破另外一个系统。
    通常任意进程都可以使用 syslog(3)库函数来记录消息。这个函数会将传入的参数以标准的格式构建一条消息,然后将这条消息写入 /dev/log socket 以供 syslogd读取。


6.syslog API
	openlog(); // 可选的
	syslog();
	closelog();
	setlogmask();


7./etc/syslog.conf
	格式:
	facility.level action
	facility 和 level 组合在一起被称为选择器,因为它们选择了需应用规则的消息。action指定了与选择器匹配的消息被发送到何处。例如:
	*.err /dev/tty10
	auth.notice root




37.Linux/Unix 系统编程手册(下) -- DAEMON-LMLPHP

37.Linux/Unix 系统编程手册(下) -- DAEMON-LMLPHP

37.Linux/Unix 系统编程手册(下) -- DAEMON-LMLPHP

37.Linux/Unix 系统编程手册(下) -- DAEMON-LMLPHP

37.Linux/Unix 系统编程手册(下) -- DAEMON-LMLPHP

37.Linux/Unix 系统编程手册(下) -- DAEMON-LMLPHP

37.Linux/Unix 系统编程手册(下) -- DAEMON-LMLPHP

37.Linux/Unix 系统编程手册(下) -- DAEMON-LMLPHP

37.Linux/Unix 系统编程手册(下) -- DAEMON-LMLPHP

37.Linux/Unix 系统编程手册(下) -- DAEMON-LMLPHP

37.Linux/Unix 系统编程手册(下) -- DAEMON-LMLPHP

37.Linux/Unix 系统编程手册(下) -- DAEMON-LMLPHP

37.Linux/Unix 系统编程手册(下) -- DAEMON-LMLPHP

37.Linux/Unix 系统编程手册(下) -- DAEMON-LMLPHP

37.Linux/Unix 系统编程手册(下) -- DAEMON-LMLPHP

37.Linux/Unix 系统编程手册(下) -- DAEMON-LMLPHP

37.Linux/Unix 系统编程手册(下) -- DAEMON-LMLPHP

37.Linux/Unix 系统编程手册(下) -- DAEMON-LMLPHP

37.Linux/Unix 系统编程手册(下) -- DAEMON-LMLPHP

37.Linux/Unix 系统编程手册(下) -- DAEMON-LMLPHP

37.Linux/Unix 系统编程手册(下) -- DAEMON-LMLPHP

37.Linux/Unix 系统编程手册(下) -- DAEMON-LMLPHP

37.Linux/Unix 系统编程手册(下) -- DAEMON-LMLPHP

37.Linux/Unix 系统编程手册(下) -- DAEMON-LMLPHP

37.Linux/Unix 系统编程手册(下) -- DAEMON-LMLPHP

37.Linux/Unix 系统编程手册(下) -- DAEMON-LMLPHP

 

 

 

 

10-05 18:02