#include <string.h>
#include<unistd.h>
#include<signal.h>
#include<sys/param.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<fcntl.h>
#include<string.h>
#include<termios.h>
#include <syslog.h>
#include <dirent.h>
#include <ctype.h>
#define SNAME "sdemo" //守护线程名称
#define NAME "test" //需要启动检测的程序
#define RNAME "/root/bin/test &" //程序目录和资源
//判断进程是否存在 预先判断守护进程是否存在,若已存在,不生成守护进程,若不存在,生成守护进程,在判断程序是否运行
int judge_pid_exist(int flag,char* pidName) //判断进程是否运行
{
DIR *dir; //进程目录
struct dirent * next;
int flags = 0;
int flagss = 0;
FILE *status;
char buffer[1024];
char name[1024];
dir = opendir("/proc"); ///proc中包括当前的进程信息,读取该目录
if (!dir) //目录不存在结束
{
printf("Cannot open /proc\n");
return 0;
}
//遍历 读取进程信息
while ((next = readdir(dir)) != NULL)
{
//跳过"."和".."两个文件名
if ((strcmp(next->d_name, "..") == 0) || (strcmp(next->d_name, ".") == 0)) continue;
//如果文件名不是数字则跳过
if (!isdigit(*next->d_name)) continue;
//判断是否能打开状态文件
sprintf(buffer,"/proc/%s/status",next->d_name);
if (!(status = fopen(buffer,"r"))) continue;
//读取状态文件
if (fgets(buffer,1024,status) == NULL)
{
fclose(status);
continue;
}
fclose(status);
sscanf(buffer,"%*s %s",name); //读取PID对应的程序名,格式为Name: 程序名
// if (strcmp(name,pidName) == 0) //判断程序名是否符合预期
if(strstr(name,pidName))
{
if(flag == 1)
{
flagss = 1;
// printf("%s\n",name);
closedir(dir); //符合
return 1;
}
else if(flag == 0)
{
flagss = 2;
flags++;
}
}
}
closedir(dir);
if(flagss == 1) return 0;
else if(flagss == 2)
{
if(flags > 1) return 0;
return 1;
}
}
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(1,NAME)) system(RNAME);//father
sleep(1);
}
}
int main(void)
{
if(judge_pid_exist(0,SNAME)) init_daemon(); //判断守护进程是否已运行
}