您的位置:首页 > 运维架构 > Linux

Linux系统的守护进程(Daemon Process)

2007-07-26 16:37 253 查看
这篇文章介绍守护进程的概念, 结构, 编写守护进程以及报告进程错误状况.

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, 更规矩更清晰.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: