wu

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

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



posted on 2012-03-11 20:58  butterflydog  阅读(206)  评论(0编辑  收藏  举报