五、守护进程编程实例
守护进程实例先通过InitDaemon函数将普通进程改造成守护进程。然后,判断是否已有该守护进程的实例在运行,若有则退出运行;若无则先阻塞SIGHUP和SIGUSR1信号,然后为SIGHUP和SIGUSR1信号分别安装了信号处理函数,SIGHUP用于通知守护进程重新读取配置文件;SIGUSR1用于通知守护进程执行服务,也就是用echo打印从配置文件读到的信息。最后,进入一个死循环(守护进程主体):通过sigsuspend挂起守护进程等待信号发生,然后重新读取配置文件或执行服务,再挂起守护进程等待信号发生……。该实例通过sigprocmask、sigsuspend和sigaction的配合使用,避免了信号SIGHUP、SIGUSR1的丢失。该实例可以选择是否通过syslog输出信息,若用syslog输出信息,编译时加上-DUSE_SYSLOG。该实例也可以选择是否忽略子进程结束信号SIGCHLD,若忽略,编译时加上-DIGN_SIGCHLD。我们可以通过命令“kill -SIGHUP 守护进程pid”,通知守护进程重新读取配置文件;通过“kill -SIGUSR1 守护进程pid”,通知守护进程执行服务。
程序清单如下:
/*
* test.c
*
* Created on: 2011-04-23
* Author: lingdxuyan
*/
#include /* 标准输入输出定义 */
#include /* 标准函数库定义 */
#include /* Unix 标准函数定义 */
#include
#include
#include
#include /* 文件控制定义 */
#include /* 错误号定义 */
#include /* 信号定义 */
#include /* 定时器定义 */
#include /* 可变参数定义 */
#include /* syslog定义 */
#include
#include
#define true 1
#define false 0
typedef unsigned char BYTE;
typedef BYTE bool;
typedef BYTE byte;
#define MAX_BUF_SIZE 1024
#define CONFIG_FILE "/etc/daemon.conf"
#define LOG_FILE "/tmp/daemon.log"
#define LOCK_FILE "/var/run/daemon.pid"
#define LOCK_FILE_MODE (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)
static volatile sig_atomic_t g_nUpdateParameter = 1;
static volatile sig_atomic_t g_nServer = 0;
//static volatile int g_nUpdateParameter = 1;
//static volatile int g_nServer = 0;
/*
* 功能: 写日志
*/
void vWriteLog(int nPriority, const char *fmt, va_list va)
{
#ifdef USE_SYSLOG
vsyslog(LOG_DAEMON | nPriority, fmt, va);
#else
FILE *stream;
if (nPriority & LOG_ERR)
stream = stderr;
else
stream = stdout;
vfprintf(stream, fmt, va);
fflush(stream);
#endif
}
void WriteLog(int nPriority, const char *fmt, ...)
{
va_list va;
va_start(va, fmt);
vWriteLog(nPriority, fmt, va);
va_end(va);
}
/*
* 功能: 写错误日志,用法类似perror
*/
void ErrorLog(const char *str)
{
WriteLog(LOG_ERR, "%s: %s\n", str, strerror(errno));
}
/*
* 功能: 写错误日志,用法类似于printf
*/
void ErrorLogFmt(const char *fmt, ...)
{
va_list va;
va_start(va, fmt);
vWriteLog(LOG_ERR, fmt, va);
va_end(va);
}
/*
* 功能: 写日志,用法类似printf
*/
void InfoLog(const char *fmt, ...)
{
va_list va;
va_start(va, fmt);
vWriteLog(LOG_INFO, fmt, va);
va_end(va);
}
/*
* 功能: 重定向标准输入输出
*/
void RedirectStdIO(char *szInFile, char *szOutFile, char *szErrFile)
{
int fd;
if (NULL != szInFi