博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Linux系统的守护进程(Daemon Process)
阅读量:3624 次
发布时间:2019-05-21

本文共 2927 字,大约阅读时间需要 9 分钟。

这篇文章介绍守护进程的概念, 结构, 编写守护进程以及报告进程错误状况. 

1. 概念:

守护进程又称为精灵进程(daemon), 是生存时间比较长的一种进程. 它们常常在系统自举时启动, 仅在系统关闭时才终止. 因为它们没有控制终端, 所以说它们是在后台运行的. 先来介绍一些Linux系统常见的守护进程:

  • init: 它的pid为1, 是系统守护进程, 负责启动系统服务, 这些服务通常自己也拥有守护进程.
  • keventd: 为在内核中运行计划执行的函数提供进程上下文.
  • kapmd: 对计算机系统中具有的高级电源管理提供支持.
  • kswapd: 页面调出守护进程(Pageout Daemon), 它通过将脏页面(Dirty Page)以低速写到磁盘上, 使这些页面在需要时仍然可以回收使用, 这种方式支持虚存子系统.
  • bdflush: 当可用内存达到下限时, 将脏缓冲区从缓冲池中冲洗到磁盘上.
  • kupdated: 将脏页面冲洗到磁盘上.
  • portmap: 提供将RPC(Remote Procedure Call, 远程过程调用)程序号映射到网络端口号的服务.
  • syslogd: 提供把系统消息记入日志的接口, 供需要的程序使用. 可以打印到termino也可以写到文件.
  • inetd: 侦听系统网络接口, 以便取得来自网络的各种网络服务请求.
  • crond: 在指定的日期和时间执行指定的命令. 使定期地执行相关程序得意实现.
  • cupsd: 打印假脱机进程, 它处理对系统提出的所有打印请求.
  • nfsd, lockd, rpciod: 提供对网络文件系统的支持(Network File System).

 

2. 编程规则:

  • 首先要调用umask将文件模式创建屏蔽字设置为0.
  • 调用fork, 然后使父进程退出. 这样做为了实现下面几点:
    • 如果该守护进程是作为一条简单shell命令启动的, 那么父进程终止使得shell认为这条命令已经执行完毕.
    • 子进程继承了父进程的进程组ID, 但具有一个新的进程ID, 这就保证了子进程不是一个进程组的组长进程. 这对于第三步的setsid调用是不要的前提.
  • 调用setsid以创建一个新会话, 使得调用进程:
    • 成为新会话的首进程.
    • 成为一个新进程组的组长进程.
    • 没有控制终端.
  • 将当前工作目录更改为根目录. 这是为了防止当前工作目录在mount的文件系统中.
  • 关闭不再需要的文件描述符.
  • 某些守护进程打开/dev/null适其具有filedes 0 1 2, 使标准输入, 输出, 出错的例程都不会产生任何效果.

 

3. 出错记录:

守护进程是没有控制终端的, 所以不能用简单的perror实现错误报告. 在Linux中, 有一个集中的守护进程出错记录设施, 它就是syslog.

有3种方法产生日志消息:

  • 内核例程可以调用log函数. 任何一个用户进程通过读取/dev/klog就可以获得这些信息, 当然你要先打开这个设备.
  • 大多数用户进程(守护进程)调用syslog函数产生日志消息.这使消息发送至UNIX域UDP Socket: /dev/log.
  • 在此主机上的一个用户进程, 或通过TCP/IP网络连接到此主机上的一个用户进程可将日志消息发向UDP端口514.
    • 注意, syslog并不产生这些UDP数据报, 而是要求产生此日志消息的进程进行显示的网络编程.

下面看一下syslog的函数:

  • 头文件: <syslog.h>
  • 原型:
    • void openlog(const char *ident, int option, int facility);
    • void syslog(int priority, const char *format, ...);
    • void closelog();
    • int setlogmask(int maskpri);
  • 返回值: 前日志记录优先级屏蔽值.
  • 说明:
    • openlog调用是可选择的, 如不调用, 在第一次调用syslog时会自动调用openlog
    • closelog调用也是可选择的, 它只关闭曾用于与syslogd守护进程通信的描述符.
  • 参数:
    • ident: log会把它加到每则日志消息中, 它一般是程序的名称(如inetd).
    • option: 指定位屏蔽选项.
      • LOG_CONS: 若日志消息不能通过UNIX域数据报送至syslogd, 则该消息写至控制台.
      • LOG_NDELAY: 立即打开至syslogd的UNIX域数据报socket, 而不等记录第一条消息.
      • LOG_NOWAIT: 不等待在将消息记入日志过程中可能创建的子进程. 阻塞了与捕捉SIGCHLD信号的应用程序冲突.
      • LOG_ODELAY: 在记录第一条消息之前延迟打开至syslogd的连接.
      • LOG_PERROR: 除了将日志消息发送给syslogd外, 还将它写到标准出错.
      • LOG_PID: 每条消息都包含进程ID.
    • facility: 让配置文件说明, 来自不同设施的消息将以不同的方式进程处理.
      • LOG_AUTH: 授权程序: login, su, getty等.
      • LOG_AUTHPRIV: 与LOG_AUTH相同, 但写日志文件时具有权限限制.
      • LOG_CRON: cron和at.
      • LOG_DAEMON: 系统守护进程: inetd, routed等.
      • LOG_FTP: FTP守护进程(ftpd).
      • LOG_KERN: 内核产生的消息.
      • LOG_LOCAL0-9: 保留由本地使用.
      • LOG_LPR: 行打印系统: lpd, lpc等.
      • LOG_MAIL: 邮件系统.
      • LOG_NEWS: Usenet网络新闻系统.
      • LOG_SYSLOG: syslogd守护进程.
      • LOG_USER: 来自其他用户进程的消息(默认).
      • LOG_UUCP: UUCP系统.
    • priority: 这个参数是facility和level的组合, 可以是(由高到低):
      • LOG_EMERG: 紧急状态(系统不可使用).
      • LOG_ALERT: 必须立即修复的状态.
      • LOG_CRIT: 严重状态.
      • LOG_ERR: 出错状态.
      • LOG_WARNING: 警告状态.
      • LOG_NOTICE: 正常, 但重要的状态.
      • LOG_INFO: 信息性消息.
      • LOG_DEBUG: 调试消息.

此外还有一个变体函数:

#include <syslog.h>

#include <stdarg.h>

void vsyslog(int priority, const char *format, va_list arg);

 

4. 简单实例:

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);

不过更推荐用第一种方式, 有open有close, 更规矩更清晰.

转载地址:http://kkuun.baihongyu.com/

你可能感兴趣的文章
封装核心基础
查看>>
springboot基础
查看>>
数据库访问中间件
查看>>
数据库事务
查看>>
模板引擎
查看>>
servlet的开发
查看>>
Java程序运行原理分析
查看>>
多线程核心
查看>>
性能测试
查看>>
JVM性能优化实战
查看>>
Tomcat容器优化
查看>>
排序算法学习和总结
查看>>
缓存优化
查看>>
Java内存模型vs JVM运行时数据区
查看>>
工作内存缓存问题
查看>>
对于同步的规则定义
查看>>
CAS(Compare and swap)
查看>>
WebSocket
查看>>
Lock API
查看>>
ReentrantLock(可重入锁)
查看>>