Linux下Daemon进程示例。
将进程ID写入到文件中,并对文件加锁,确保只有一个daemon进程在运行。此外,有信号处理函数示例。
(备注:参考大名鼎鼎的 APUE中示例,整理而出 :))
#include <iostream>
using namespace std;
//TO BE ADDED
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <signal.h>
#define PIDFILE "main.pid"
int Lockfile(const int iFd)
{
struct flock stLock;
stLock.l_type = F_WRLCK; /* F_RDLCK, F_WRLCK, F_UNLCK */
stLock.l_start = 0; /* byte offset, relative to l_whence */
stLock.l_whence = SEEK_SET; /* SEEK_SET, SEEK_CUR, SEEK_END */
stLock.l_len = 0; /* #bytes (0 means to EOF) */
return (fcntl(iFd, F_SETLK, &stLock));
}
int IsRunning()
{
const int iPidFile = open(PIDFILE, O_RDWR | O_CREAT, (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH));
if (iPidFile < 0)
{
cout << "Can not open pid file:" << PIDFILE << endl;
return -1;
}
//lock file
if (Lockfile(iPidFile) < 0)
{
if ((EACCES == errno) || (EAGAIN == errno))
{
close(iPidFile);
cout << "Is already running" << endl;
return 1; //already running
}
//fail to lock
cout << "Cant lock pid file:" << PIDFILE << endl;
return -1;
}
//write pid
ftruncate(iPidFile, 0);
char buf[16];
sprintf(buf, "%ld", (long)getpid());
write(iPidFile, buf, strlen(buf) + 1);
return 0;
}
int SetDaemon()
{
//umask(0);
int iPid = 0;
if ((iPid = fork()) < 0)
{
//fork error
return -1;
}
else if (0 != iPid) //parent
{
exit(0);
}
//setsid();
return 0;
}
void SigTerm(int iSig)
{
cout << "Recv single term," << iSig << endl;
}
void SigHup(int iSig)
{
cout << "Recv single hup," << iSig << endl;
}
void SigUsr1(int iSig)
{
cout << "Recv single Usr1," << iSig << endl;
}
int HandleSingle()
{
struct sigaction stSigAct;
stSigAct.sa_handler = SigTerm;
sigemptyset(&stSigAct.sa_mask);
sigaddset(&stSigAct.sa_mask, SIGTERM);
stSigAct.sa_flags = 0;
if (sigaction(SIGTERM, &stSigAct, NULL) < 0)
{
cout << "Can not catch SIGTERM," << strerror(errno) << endl;
return -1;
}
stSigAct.sa_handler = SigHup;
sigemptyset(&stSigAct.sa_mask);
sigaddset(&stSigAct.sa_mask, SIGHUP);
stSigAct.sa_flags = 0;
if (sigaction(SIGHUP, &stSigAct, NULL) < 0)
{
cout << "Can not catch SIGHUP," << strerror(errno) << endl;
return -1;
}
stSigAct.sa_handler = SigUsr1;
sigemptyset(&stSigAct.sa_mask);
sigaddset(&stSigAct.sa_mask, SIGUSR1);
stSigAct.sa_flags = 0;
if (sigaction(SIGUSR1, &stSigAct, NULL) < 0)
{
cout << "Can not catch SIGUSR1," << strerror(errno) << endl;
return -1;
}
return 0;
}
int main()
{
int iRet = 0;
iRet = SetDaemon();
if (0 != iRet)
{
cout << "Fail to set daemon, now exit." << endl;
exit(0);
}
iRet = IsRunning();
if (0 != iRet)
{
cout << "Is running!" << endl;
exit(1);
}
cout << "\nmain daemon running..." << endl;
iRet = HandleSingle();
if (iRet < 0)
{
cout << "HandleSingle error" << endl;
exit(1);
}
while (1)
{
pause(); //wait for signal
}
//sleep(60); //sleeping 60s
//pause() causes the calling process (or thread) to sleep until a signal is delivered
// that either terminates the process or causes the invocation of
// a signal-catching function.
//sleep() makes the calling thread sleep until seconds seconds have elapsed or a
//signal arrives which is not ignored.
return 0;
}