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

CentOS下的Daemon进程

2016-03-07 15:56 567 查看
Date:2016-03-03

Author:kagula

Environment:

[1]CentOS7

[2]Win10

[3]Visual Studio 2013 Update5

[4]gcc 4.8.5

Prologue:

  经我几次测试,baidu上说的普通进程的缺陷我还是看不出来

比如说:

[1]普通进程也可以后台运行,不受终端影响。终端退出后它还是存在的。

[2]普通进程在kill后,也能catch到信号,做正常退出动作,然后再调用Exit退出。

但是为了避免未知的问题还是改了代码,把它弄成Daemon进程。

这里记下示例代码,免得时间长忘记了。

主要有FakeServer.cpp、SourceLinux.cpp、utility.cpp三个文件组成,
“Daemon process”的重点是在SourceLinux.cpp中。

弄个假的服务程序段

FakeServer.cpp
#include "FakeServer.h"

extern bool g_bTerm;

void  fakeServer()
{
while (1)
{
if (g_bTerm)
{
break;
}
}
}


在CentOS下启动Daemon process的代码

SourceLinux.cpp
#ifndef WIN32
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <fcntl.h>
#include <errno.h>
#include <syslog.h>
#include <string.h>

#include <signal.h>

#include "FakeServer.h"
#include "utility.h"

//the var may need thread protection.
//g_bTerm用于通知服务器是否结束程序.
bool g_bTerm = false;

//通知我们的服务器代码,可以结束服务了。。。
void signal_term_handler(int signal_num)
{
g_bTerm = true;
kagula::g_log.info("signal_term_handler work!");
}

int main(int argc, char* argv)
{
pid_t pid, sid;

/* Fork off the parent process */
pid = fork();
if (pid < 0) {
exit(EXIT_FAILURE);
}

/* If we got a good PID, then we can exit the parent process. */
if (pid > 0) {
exit(EXIT_SUCCESS);
}

//产生的子进程将变成孤儿进程,并被init进程接管.
//同时,所产生的新进程将变为在后台运行.

/* Create a new SID for the child process */
//setsid函数将创建新的会话,并使得调用setsid函数的进程成为新会话的领头进程.
//会话的领头进程没有控制终端与其相连。满足了守护进程没有控制终端的要求.
sid = setsid();
if (sid < 0) {
/* Log any failure here */
exit(EXIT_FAILURE);
}

/* Change the current working directory */
if ((chdir("/")) < 0) {
/* Log any failure here */
exit(EXIT_FAILURE);
}

//赋予当前进程最大文件读写权限.
umask(0);

/* Close out the standard file descriptors */
//Daemon Process不能使用终端,这些文件描述符就是多余
//所以关闭他们
close(STDIN_FILENO);
close(STDOUT_FILENO);
close(STDERR_FILENO);

//
kagula::InitLog();
kagula::g_log.info("Initialization log module.");

//检查进程的数量,如果大于等于2说明已经启动了两个进程.
//那就退出当前进程.
if (kagula::NumberOfProcess()>=2)
{
kagula::g_log.error("Already running...");
return -1;
}

//处理Kill <pid>发出的信号,并进行退出处理。
signal(SIGTERM,signal_term_handler);

//启动我们(假)的服务程序.
fakeServer();

//释放“用于判断当前进程数量的”共享内存。
kagula::ReleaseKagula();

//退出
exit(EXIT_SUCCESS);

return 0;
}

#endif


编译上面的代码所需要的支撑文件

utility.h
#ifndef _UTILITY_H_
#define _UTILITY_H_

#include "simpleLog.h"

namespace kagula
{
void InitLog();
extern simpleLogClass g_log;

int NumberOfProcess();
bool ReleaseKagula();
}

#endif


utility.cpp

#include "utility.h"

#include <boost/interprocess/shared_memory_object.hpp>
#include <boost/interprocess/mapped_region.hpp>

namespace kagula
{
simpleLogClass g_log;

void InitLog()
{
g_log.fileMaxSize = 64 * 1024;
#ifdef WIN32
g_log.fileName = "processname.log";
g_log.fileOldName = "processname.log";
#else
g_log.fileName = "/var/log/kagula/processname.log";
g_log.fileOldName = "/var/log/kagula/processname.log";
#endif
}

#define SHARED_MEMORY_OBJECT_NAME "TestCentOSDaemonProcess"
int NumberOfProcess()
{
boost::interprocess::shared_memory_object shdmem(boost::interprocess::open_or_create, SHARED_MEMORY_OBJECT_NAME, boost::interprocess::read_write);
shdmem.truncate(8);//shdmem.truncate(1024);//设定共享内存大小

boost::interprocess::mapped_region region(shdmem, boost::interprocess::read_write);
int *i1 = static_cast<int*>(region.get_address());
(*i1) += 1;

return (*i1);
}

bool ReleaseKagula()
{
return boost::interprocess::shared_memory_object::remove(SHARED_MEMORY_OBJECT_NAME);
}
}


CMakeLists.txt

project(TestCentOSDaemonProcess)
cmake_minimum_required(VERSION 2.8)
SET( CMAKE_VERBOSE_MAKEFILE ON )

find_package(Boost 1.57 COMPONENTS system filesystem thread date_time REQUIRED)
include_directories(${Boost_INCLUDE_DIRS})
LINK_DIRECTORIES(/usr/local/lib)

aux_source_directory(. DIR_SRCS)

#undefined reference to `boost::system::system_category()
#自己在c++命令行上加入-lboost_system,手动在执行c++成功
#For boost Interprocess library in CentOS7
#-lboost_date_time -lrt
add_executable(TestCentOSDaemonProcess ${Boost_LIBRARIES} ${DIR_SRCS})


常见问题

xxx.so文件找不到

添加库文件search path

vi /etc/ld.so.conf  

#在最后一样添加“/usr/local/lib”

#使路径生效

/sbin/ldconfig -v  

#现在程序可以运行了



查看Daemon进程


TestCentOSDaemonProcess是Daemon进程文件名称
ps -ef|grep TestCentOSDaemonProcess

Reference

[1]《CentOS 7.x设置自定义开机启动,添加自定义系统服务》
http://www.centoscn.com/CentOS/config/2015/0507/5374.html
[2]《centos7 开机/etc/rc.local 不执行的问题》

[3]《Linux下系统日志的使用》
http://blog.chinaunix.net/uid-26983585-id-3322977.html
[3]《signal() 函数详解》
http://blog.sina.com.cn/s/blog_8184e03301013ddz.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: