Linux进程守护C++实现
Linux进程守护使用脚本也很容易实现,但是有时需要各种自定义的需求做一个代码级的也是不错。
#ifndef _MSC_VER
#include <unistd.h>
#include <signal.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <time.h>
#include <stdio.h>
#include <dirent.h>
#include <ctype.h>
#include <syslog.h>
#include <termios.h>
#include <sys/param.h>
#include <sys/types.h>
#include <sys/stat.h>
static bool flag = true;
void create_daemon();
void handler(int);
#define SELFNAME "appdogd" //守护线程名称
#define APPNAME "testuidemo" //需要启动检测的程序
#define RUNNAME "/home/pi/testuidemo&" //程序目录和资源
//判断进程是否存在 预先判断守护进程是否存在,若已存在,不生成守护进程,若不存在,生成守护进程,在判断程序是否运行
int judge_pid_exist(const char* pidName) //判断进程是否运行
{
int cnt = 0;
DIR* dir = NULL; //进程目录
struct dirent* next = NULL;
FILE* status = NULL;
char buffer[1024] = { 0 };
char name[1024] = { 0 };
dir = opendir("/proc"); ///proc中包括当前的进程信息,读取该目录
if (dir == NULL) //目录不存在结束
{
printf("Cannot open /proc\n");
return (-1);
}
//遍历 读取进程信息
while ((next = readdir(dir)) != NULL)
{
//跳过"."和".."两个文件名
if ((strcmp(next->d_name, "..") == 0) || (strcmp(next->d_name, ".") == 0))
{
continue;
}
//如果文件名不是数字则跳过
if (isdigit(*next->d_name) == 0)
{
continue;
}
//判断是否能打开状态文件
sprintf(buffer, "/proc/%s/status", next->d_name);
if ((status = fopen(buffer, "r")) != NULL)
{
//读取状态文件
if (fgets(buffer, sizeof(buffer) / sizeof(*buffer), status) == NULL)
{
fclose(status);
continue;
}
fclose(status);
sscanf(buffer, "%*s %s", name); //读取PID对应的程序名,格式为Name: 程序名
if (strstr(name, pidName) != NULL)
{
cnt++;//符合
}
}
}
closedir(dir);
return cnt;
}
void init_daemon(void) //守护进程初始化函数
{
int pid = 0;
int i = 0;
if (pid = fork())
{
exit(0);//是父进程,结束父进程
}
else if (pid < 0)
{
exit(1);//fork失败,退出
}
setsid(); //第一子进程成为新的会话组长和进程组长,并与控制终端分离
for (i = 0; i < NOFILE; i++)
{
close(i);//关闭打开的文件描述符
}
chdir(".");//改变工作目录到/tmp
umask(0);//重设文件创建掩模
while (1) //判断程序是否运行
{
if (judge_pid_exist(APPNAME) == 0)
{
system(RUNNAME);//father
}
sleep(3);
}
}
#endif // !_MSC_VER
int main(int argc, char ** argv)
{
std::cout << "Hello CMake." << std::endl;
if (judge_pid_exist(SELFNAME) == 0)
{
init_daemon(); //判断守护进程是否已运行
}
return 0;
}