1. 守护进程的启动方法

(1)系统初始化脚本启动,在系统启动阶段,按照如/etc目录或/etc/rc开头的目录中的某些脚本启动,这些守护进程一开始就有超级用户权限。如inetd,cron,Web服务器

(2)由inetd超级服务器启动。inetd监听网络请求(FTP,Telnet..),每当一个请求到达时,启动相应实际服务器。

(3)cron守护进程启动。cron按照规则定期执行一些程序。

(4)at命令。at命令指定某个时刻启动程序,这些程序由cron启动。

(5)用户终端启动,这需要守护进程亲自脱离与控制终端的关联。

2.1 syslogd守护进程

  由于守护进程没有控制终端,所以无法向stderr输出消息,因此使用syslogd记录消息。

  syslogd由系统初始化脚本启动,syslogd启动时完成以下步骤:

  (1)读取配置文件,如/etc/syslog.conf以指定可能收取的消息应该如何处理。

  (2)创建一个Unix域套接字,给它绑定到/var/run/log 或 /var/log

  (3)创建一个UDP套接字,绑定514端口

  (4)打开/dev/klog,从该设备获得内核的任何出错信息。

  之后进行循环:调用select监听3个文件描述符(上面2,3,4步骤获得),描述符可读,则读之,并将消息写入日志。

  如果收到SIGHUP则重新读取配置文件。

  

2.2 向syslogd发消息

  (1)应用创建Unix套接字,绑定与syslogd相同的路径。

  (2)创建UDP套接字,向514端口发信息(新的syslogd禁止了UDP套接字,原因是由于UDP套接字缓冲被恶意写满,导致拒绝服务攻击)

  (3)调用syslog函数,该函数封装了使用Unix域套接字的方法。

2.3 syslog函数

void syslog(int priority, const char *format, ...);

  priority由 level 和 facility 两者组合,format 是格式化串,增加了 %m(它被替换成 errno 对应的错误消息)

  level 默认为LOG_NOTICE

  facility 指定发送消息的进程类型

  举例进程可以调用

syslog(LOG_INFO | LOG_LOCAL2, "rename (%s, %s) : %m", file1, file2);

  /etc/syslog.conf可以这样指定

kern.*      /dev/console
local2.info /var/log/cisco.log

  这样来自 local2 设施的 info 消息就会记录到 /var/log/cisco.log

  syslog 首次调用时创建Unix域套接字,后调用connect连接路径(/var/run/log),套接字一直打开,直到进程终止。

2.4 openlog 和 closelog

void openlog(const char *ident, int options, int facility);
void closelog(void);

  openlog 在首次调用syslog前调用,closelog在不再发送日志消息时调用。

  ident 指定 syslog每个日志消息首部的字符串,通常用 程序名

  options 参数有以下组合

  facility 为没有指定设施的syslog调用设置一个默认的值,这样之后的syslog只需要指定level。

  openlog 调用时,通常不会创建Unix域套接字,套接字直到首次调用syslog才打开。

2. daemon_init

#define MAXFD   64

extern int      daemon_proc;    /* defined in error.c */

int
daemon_init(const char *pname, int facility)
{
int i;
pid_t pid; if ( (pid = Fork()) < 0)
return (-1);
else if (pid)
_exit(0); /* parent terminates */ /* child 1 continues... */ if (setsid() < 0) /* become session leader */
return (-1); Signal(SIGHUP, SIG_IGN);
if ( (pid = Fork()) < 0)
return (-1);
else if (pid)
_exit(0); /* child 1 terminates */ /* child 2 continues... */ daemon_proc = 1; /* for err_XXX() functions */ chdir("/"); /* change working directory */ /* close off file descriptors */
for (i = 0; i < MAXFD; i++)
close(i); /* redirect stdin, stdout, and stderr to /dev/null */
open("/dev/null", O_RDONLY);
open("/dev/null", O_RDWR);
open("/dev/null", O_RDWR); openlog(pname, LOG_PID, facility); return (0); /* success */
}

(1)fork

  调用fork,并终止父进程,子进程在后台运行,是为了shell认为命令已经执行完成,从而命令交出控制台。

(2)setsid

  创建新会话,保证子进程为会话头进程和进程组头进程,从而不再有控制终端。

(3)忽略SIGHUP,并再次fork

  为了确定程序不会再获得控制终端,所以需要进程不能是会话进程的头进程。

  因为如果将来进程打开控制终端,该终端会自动成为会话头进程的控制终端。

  当会话头进程终止时,会向会话的所有子进程发送SIGHUP,所以要忽略SIGHUP。

(4)改变工作目录

  守护进程需要改变工作目录到其真正的工作的地方。

  原因是,守护进程可能在文件系统任何地方被启动,如果仍然在其中,那么该文件系统就无法卸载。

(5)关闭所有打开的文件描述符

  关闭守护进程从执行的它的进程(通常是shell)继承来的所有打开的描述符

(6)将stdin,stdout,stderr重定向到/dev/null

  这有两个好处,

    保证这些常用描述符是打开的,针对他们的系统调用read返回EOF,write则由内核丢弃所有数据,因此守护进程不会因为调用这些程序而失败。

    避免打开其他描述符从0,1,2开始,否则perror会将数据发到错误的地方。

(7)syslogd处理错误

   守护进程与信号

  守护进程没有控制终端,所以它不会收到SIGHUP,可以将SIGHUP作为通知信号,比如通知配置文件已经修改。

  同样守护进程也不会收到SIGINT 和 SIGWINCH 信号,也可以安全的将这些信号作为通知信号。

最新文章

  1. Struts2:上传下载
  2. 第 27 章 CSS 传统布局[下]
  3. .net 使用ffmpeg.exe进行音频转码
  4. Hbase0.98.4/Hadoop2.4.1整合小结【原创】
  5. 一个异常与Android Studio系列教程参考
  6. ASP.NET MVC 4应用程序文件夹
  7. uva 11300 - Spreading the Wealth(数论)
  8. Linux中输入命令按tab提示后会自动转义解决方案(xjl456852原创)
  9. 关于文件上传的ajax交互
  10. BZOJ 1116: [POI2008]CLO [连通分量]
  11. 异常-----springmvc + ajaxfileupload解决ajax不能异步上传图片的问题。java.lang.ClassCastException: org.apache.catalina.connector.RequestFacade cannot be cast to org.springframework.web.multipart.
  12. MongoDB学习笔记(四)
  13. React react-fastclick-alt 移动端点击
  14. bootstrap使用之多个弹窗和拖动效果[开发篇]
  15. easyui datagrid加载数据的三种方式
  16. android6.0系统Healthd分析及低电量自动关机流程
  17. hibernate基本配置show_sql、sql_format
  18. laravel的中间件demo
  19. 认识CSS中css背景样式设置
  20. Liquibase 快速开始

热门文章

  1. centos8平台使用journalctl管理systemd-journald日志
  2. 使用OLEDB方式 读取excel和csv文件
  3. 第二章 rsync服务原理
  4. hdu6115 Factory (LCA + 倍增)
  5. git学习(七) git的标签
  6. java基础第一章
  7. tf-tensorboard的一些注意事项
  8. uart接口介绍和认识
  9. ABAP CA CO CS CP 等操作符
  10. 【16】进大厂必须掌握的面试题-100个python面试