网络编程学习——守护进程和inetd超级服务器
网络编程学习——守护进程和inetd超级服务器
thanatos_y 发表于2年前
网络编程学习——守护进程和inetd超级服务器
  • 发表于 2年前
  • 阅读 19
  • 收藏 0
  • 点赞 1
  • 评论 0

腾讯云 新注册用户 域名抢购1元起>>>   

摘要: 通过《UNIX网络编程卷1:套接字联网API》学习网络编程

1 概述

  守护进程(daemon)是在后台运行且不与任何控制终端关联的进程。Unix系统通常有很多守护进程在后运行(约在20到50个的量级),执行不同的管理任务。

  守护进程没有控制终端控制通常源于它们由系统初始化脚本启动。然而守护进程也可能从某个终端由用户在shell提示符下键入命令行启动,这样的守护进程必须亲自脱离与控制终端的关联,从而避免与作业控制、终端会话管理、终端产生信号等发生任何不期望的交互,也可以避免在后台运行的守护进程非预期地输出到终端。

  守护进程有多种方法可以启动。

  1. 在系统启动阶段,许多守护进程由系统初始化脚本启动。这些脚本通常位于/etc目录或以/etc/rc开头的某个目录中,它们的具体位置和内容却是现实相关的。由这些脚本启动的守护进程一开始拥有超级用户特权。

    有若干个网络服务器通常从这些脚本启动:inetd超级服务器、Web服务器、邮件服务器(经常是sendmail)。

  2. 许多网络服务器由inetd超级服务器启动。inetd自身由上一条中的某个脚本启动。inetd自身由上一条中的某个脚本启动。inetd监听网络请求(Telnet、TFP等),每当有一个请求到达时,启动相应实际服务器(Telnet服务器、FTP服务器等)。

  3. cron守护进程按照规则定期执行一些程序,而由它启动执行的程序同样作为守护进程运行。cron自身由第1条启动方法中的某个脚本启动。

  4. at命令用于指定将来某个时刻的程序执行。这些程序的执行时刻到来时,通常由cron守护进程启动执行它们,因此这些程序同样作为守护进程。

  5. 守护进程还可以从用户终端或在前台或在后台启动。这么做往往是为了测试守护程序或重启因某种原因而终止的某个守护进程。

      因为守护进程没有控制终端,所以当有事发生时它们得有输出消息的某种方法可用,而这些消息既可能是普通的通告性消息,也可能是需由系统管理员处理的紧急事件消息。syslog函数是输出这些消息的标准方法,它把这些消息发送给syslog守护进程。

     

2 syslog守护进程

  Unix系统中的syslogd守护进程通常由某个系统初始化脚本启动,而且在系统工作期间一直运行。源自Berkeley的syslogd实现在启动时执行以下步骤。

  1. 读取配置文件。通常为/etc/syslog.conf的配置文件指定本守护进程可能收取的各种日志消息(log message)应该如何处理。这些消息可能被添加到一个文件(/dev/console文件是一个特例,它把消息写到控制台上),或被写到到指定用户的登录窗口(若该用户已登录到本守护进程所在系统中),或被转发给另一个主机上的syslogd进程。

  2. 创建一个Unix域数据报套接字,给它捆绑路径名/var/run/log(在某些系统上是/dev/log)。

  3. 创建一个UDP套接字,给它捆绑端口514(syslog服务使用的端口)。

  4. 打开路径名/dev/klog。来自内核中的任何出错消息看着像是这个设备的输入。

  此后syslogd守护进程在一个无线循环中运行:调用select以等待它的3个描述符(分别来自上述2,3和4步)之一变为可读,读入日志信息,并按照配置文件进行处理。如果守护进程收到SIGUP信号,那就重新读取配置文件。通过创建一个Unix域数据报套接字,我们就可以从自己的守护进程中通过往syslog绑定的路径名发送我们的消息达到发送日志消息的目的。另外,我们也可以创建一个UDP套接字,通过往环回地址和端口514发送我们的消息达到发送日志消息的目的。

3 syslog函数

  既然守护进程没有控制终端,它们就不能把消息fprintf到stderr上。从守护进程中登记消息的常用技巧就是调用syslog函数。

#include <syslog.h>
/* Generate a log message using FMT string and option arguments.

   This function is a possible cancellation point and therefore not
   marked with __THROW.  */
extern void syslog (int __pri, const char *__fmt, ...)
     __attribute__ ((__format__ (__printf__, 2, 3)));

  本函数的__pri参数是级别(level)和设施(facility)两者的组合,分别如图1-1和图1-2。

  如图1-1所示,日志消息的level可从0到7,它们是按从高到低的顺序排序的。如果发送者未指定level值,那就默认为LOG_NOTICE。

图1-1 日志消息的level

  日志消息还包含一个用于标识消息发送进程类型的facility。图1-2列出了facility的各种值。如果发送者未指定facility值,那就默认为LOG_USER。

图1-2 日志消息的facility

  举例来说,当rename函数调用意外失败时,守护进程可以执行以下调用:

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

  facility和level的目的在于,允许在/etc/syslog.conf文件中统一配置来自同一给定设施的所有消息,或者统一配置具有相同级别的所有信息。举例来说,该配置文件可能含有以下两行:

kern.*  /dev/console
loacl7.debug  /var/log/cisco.log

  这两行指定所有内核消息登记到控制台,来自local7设施的所有debug消息添加到文件/var/log/cisco.log的末尾。

  当syslog被应用进程首次调用时,它创建一个Unix域数据报套接字,然后调用connect连接到由syslog守护进程创建的Unix域数据报套接字的众所周知路径名(譬如/var/run/log)。这个套接字一直保持打开。直到进程终止为止。作为替换,进程也可以调用openlog和closelog。

#include <syslog.h>
/* Open connection to system logger.

   This function is a possible cancellation point and therefore not
   marked with __THROW.  */
extern void openlog (const char *__ident, int __option, int __facility);

/* Close descriptor used to write to system logger.

   This function is a possible cancellation point and therefore not
   marked with __THROW.  */
extern void closelog (void);

  openlog可以在首次调试调用syslog前调用,closelog可以在应用进程不再需要发送日志消息时调用。
 

 

 

共有 人打赏支持
粉丝 7
博文 90
码字总数 314854
×
thanatos_y
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
* 金额(元)
¥1 ¥5 ¥10 ¥20 其他金额
打赏人
留言
* 支付类型
微信扫码支付
打赏金额:
已支付成功
打赏金额: