[APUE chapter 13] 守护进程

作者:isshe
日期:2016.10.30
邮箱:[email protected]
github: https://github.com/isshe

1. 相关概念

  • 系统进程以赖于操作系统实现。
  • 父进程ID为0的各进程通常是内核进程,它们作为系统引导装入过程的一部分而启动。
  • 内核守护进程以无控制终端方式启动,用户层守护进程缺少控制终端可能是守护进程调用了setsid的结果。
  • 大多数用户层守护进程都是进程组的组长进程以及会话的首进程,而且是这些进程组和会话中的唯一进程。(rsyslogd例外,linux中)
  • 用户层守护进程的父进程是init进程(linux系统中)。
  • 守护进程常作服务器进程。

2. 编写规则

编写守护进程程序时需遵循一些基本规则,以防产生不必要的交互。

  • 1.调用umask将文件模式创建屏蔽字设置为一个已知值(通常是0)(不理解)
  • 2.调用fork,然后父进程exit。这样可以:

    如果该守护进程是为一条简单的shell命令启动的,那么父进程终止会让shell认为这条命令已经执行完毕。
    子进程继承父进程的进程组ID,但获得新的进程ID,保证了子进程不是一个进程组的组长进程。

  • 3.调用setsid创建一个新会话。 会发生:(因为前面保证了此进程不是进程组的组长,所以可以创建新会话,否则,setsid会返回出错)

    1). 该进程编程新会话的会话首进程(session leader),此时此进程是会话中唯一进程。
    2). 该进程成为新进程组的组长进程。(新进程组ID就是调用进程ID)
    3). 进程没有控制终端。

  • 4.将当前工作目录更改为根目录。

  • 5.关闭不需要的文件描述符。(可以使用open_max函数或getrlimit函数获取最大文件描述符值)
  • 6.某些进程打开/dev/null使其具有文件描述符0、1、2。

3. 出错记录

  • 由于没有控制终端,不能简单地输出到标准错误上。
  • 每个守护进程的出错信息写到一个文件也不好,管理起来会十分麻烦。

3.1 syslog

  • syslog设施的详细组织结构:
    [APUE chapter 13] 守护进程_第1张图片

  • 三种产生日志消息的方法:

    • 内核例程可以调用log函数。任何一个用户进程可以通过打开(open)并读取(read)/dev/klog设备来读取这些信息。
    • 调用syslog函数产生日志消息。
    • 无论用户进程是在此主机上,还是通过TCP/IP网络连接到此主机的其他主机上,都可以将日志消息发向UDP端口514。
  • 原型:

       #include 

       void openlog(const char *ident, int option, int facility);
       void syslog(int priority, const char *format, ...);
       void closelog(void);
       int setlogmask(int mask);
  • 功能:(日志消息通过syslogd守护进程读取)
    • openlog:打开该进程的日志。(调用是可选的。如不调用,则在第一次调用syslog时自动调用。)
    • closelog:关闭用于与syslogd守护进程进行通信的描述符。(也是可选的。)
    • syslog:产生一个日志消息。
    • setlogmask:用于设置进程的记录优先级屏蔽字。
  • 参数:

    • ident:可以被加到每则日志中的标识。一般是程序名称。
    • open:(以下表格不完全完整,完整见APUE p378)

      option XSI 说明
      LOG_CONS * 若日志消息不能通过UNIX域数据表送至syslogd,则将该消息写至控制台。
      LOG_NDELAY * 立即打开至syslogd守护进程的UNIX域数据报套接字,不要等到第一条消息已经被记录时再打开。(通常,在记录第一条消息之前,不打开该套接字)
      LOG_NOWAIT * 不要等待在将消息记入日志过程中可能已创建的子进程。
      LOG_ODELAY * 在第一条消息被记录之前延迟打开至syslogd守护进程的连接。
      LOG_PERROR 将日志消息发送给syslogd外,还将它写到标准错误。
      LOG_PID * 记录每条消息都要包含进程ID
    • facility:设置facility参数的目的是可以让配置文件说明,来自不同设施的消息将以不同的方式处理。(中文表格见APUE p378)
      [APUE chapter 13] 守护进程_第2张图片

    • priority:是facility和level的组合,以下是level的表格:
      [APUE chapter 13] 守护进程_第3张图片
    • format:format参数以及其他所有format后的参数,都传至vsprintf函数一遍进行格式化。format中每个%m字符都先被替换成与errno值对应的strerror。
    • mask:记录优先级屏蔽字。
  • 返回值:
    • setlogmask:返回调用setlogmask之前的屏蔽字。

3.2 实例

openlog("lpd", LOG_PID, LOG_LPR);
syslog(LOG_ERR, "open error for %s: %m", filename);
或
syslog(LOG_ERR|LOG_LPR, "open error for %s: %m", filename);

4. 守护进程的惯例

  • 在UNIX系统中,守护进程通常遵循下列通用惯例:
    • 若守护进程使用锁文件,那么该文件通常存储在/var/run目录中。(需要特权才能创建文件,锁的名字通常是name.pid,其中name是该守护进程或服务的名字)
    • 若守护进程支持配置选项,那么配置文件通常存放在/etc目录中。(配置文件名字通常是namd.conf,name同上)
    • 守护进程可用命令行启动,但通常它们是系统初始化脚本之一启动的(脚本如:/etc/rc* 或 /etc/init.d/*)。(如要终止后自动重启,则在/etc/inittab中为该守护进程宝货respawn记录项)
    • 若一个守护进程有一个配置文件,那么当该守护进程启动时会读该文,但此后一般不会再查看它。

5. 参考资料

  • 《unix环境高级编程》第13章

你可能感兴趣的:(【初探】操作系统)