main.c
#include "process.h"
int main(int argc, char *const *argv)
{
/*创建一个守护进程*/
if(creat_daemon() != 1)
{
/*创建失败则直接返回*/
return 1;
}
else/*在守护进程里面做自己要做的事情*/
{
/*进程监控*/
run_moniter("init.txt");
/*sleep*/
for(;;)
{
/*休息1秒*/
sleep(2);
}
}
return 0;
}
#include "process.h"
int exit_flag = 0;
int must_run_size;
struct proc_struct must_run_proc[SIZE];
/*
* @file process.c
* @function run_moniter
* @author 酸菜。
* @date 2021-05-10
*/
void run_moniter(char *Filename)
{
/*从配置文件当中读取配置信息,存入到must_run_proc
结构体数组当中,返回值为要监控的进程个数,其中每个
进程包括了进程ID以及进程名*/
must_run_size = get_proc(Filename, "aa", must_run_proc, SIZE);
/*小于0说明没有要监控的进程*/
if(must_run_size <= 0)
{
return;
}
#if 0
/*注册信号处理函数,用来闭守护进程*/
if(signal(SIGINT, exit_proc) == SIG_ERR)
{
printf("无法捕捉SIGUSR1信号!\n");
}
#endif
/*检测并启动未启动的进程*/
while(1)
{
moniter_run(must_run_proc, must_run_size);
sleep(2);
}
return;
}
/*
* @file main.c
* @function creat_daemon
* @author 酸菜。
* @date 2021-05-10
*/
int creat_daemon()
{
int fd;
/*创建子进程*/
switch (fork())
{
case -1:
/*创建子进程失败,这里可以写日志*/
return -1;
case 0:
/*子进程,走到这里,直接break*/
break;
default:
/*父进程(没有用了),直接退出*/
exit(0);
}
/*只有子进程流程才能走到这里脱离终端,
终端关闭,将跟此子进程无关,设置子进程
成为一个守护进程*/
if (setsid() == -1)
{
/*记录错误日志*/
return -1;
}
/*设置为0,不要让它来限制文件权限,以免引起混乱*/
umask(0);
/*打开黑洞设备,以读写方式打开*/
fd = open("/dev/null", O_RDWR);
if (fd == -1)
{
/*记录错误日志*/
return -1;
}
/*先关闭STDIN_FILENO[这是规矩,
已经打开的描述符,动他之前,先close,
类似于指针指向null,让/dev/null成为标准输入;*/
if (dup2(fd, STDIN_FILENO) == -1)
{
/*记录错误日志*/
return -1;
}
/*先关闭STDIN_FILENO,类似于指针指向null,让/dev/null成为标准输出*/
if (dup2(fd, STDOUT_FILENO) == -1)
{
/*记录错误日志*/
return -1;
}
/*fd应该是3,这个应该成立*/
if (fd > STDERR_FILENO)
{
/*释放资源这样这个文件描述符就可以被复用;不然这个文件描述会被一直占着*/
if (close(fd) == -1)
{
/*记录错误日志*/
return -1;
}
}
return 1;
}
/*
* @file process.c
* @function
* @author 酸菜。
* @date 2021-05-10
*/
int proc_find(struct proc_struct* src, struct proc_struct* dest)
{
char buffer[4096], *p, cmd[20];
int fd, len;
/*字符串拼接*/
sprintf(buffer, "%d/stat", src->pid);
fd = open(buffer, O_RDONLY);
if(fd == -1)
{
return 0;
}
memset(buffer, '\0', sizeof(buffer));
len = read(fd, buffer, sizeof(buffer) - 1);
close(fd);
if(len <= 0)
{
return 0;
}
p = buffer;
p = strrchr(p, '(');
{
char *q = strrchr(p, ')');
/*进程名称的长度*/
int len = q - p - 1;
/*应该不会超过128*/
if (len >= sizeof(src->process_name))
{
len = sizeof(src->process_name) - 1;
}
/*把从proc目录下读到的进程名称写入src->process_name*/
memcpy(src->process_name, p+1, len);
/*最后一位记得补'\0'*/
src->process_name[len]= 0;
/*现在p指向'('的后一位字符*/
p = q + 1;
}
/*两个进程名称进行比较,相等则说明该进程正在运行*/
return (strcmp(src->process_name, dest->process_name) == 0) ? 1 :0;
}
/*
* @file process.c
* @function check_proc
* @author 酸菜。
* @date 2021-05-10
*/
int check_proc(struct proc_struct* array)
{
DIR *dp;
char *dir = PROCES;
struct dirent *dirp;
struct proc_struct* proc;
struct proc_struct* tmp;
/*array为空则直接返回*/
if(array == NULL)
{
return 0;
}
/*切换到/proc路径*/
chdir(dir);
/*读取/proc目录下所有文件夹和文件的信息,
dp保存所有这些读取到的信息,如果dir是一个
文件,则直接返回NULL*/
if((dp = opendir(dir)) == NULL)
{
return 0;
}
/*循环读取dp读到的信息*/
while ((dirp = readdir(dp)) != NULL)
{
char data[30];
/*dirp->d_process_name文件夹名称,即进程ID
保存到data里*/
sprintf(data, "%s", dirp->d_name);
/*判断data的内容是否是纯数字*/
if((strspn(data, "0123456789") == strlen(data)))
{
proc = (struct proc_struct *)(malloc(sizeof(struct proc_struct)));
tmp = proc;
proc->pid = atoi(dirp->d_name);
/*判断配置文件里的进程是否在运行*/
if(proc_find(proc, array))
{
printf("进程正在运行!\n");
return 1;
}
free(tmp);
}
}
/*关闭该目录*/
closedir(dp);
return 0;
}
/*
* @file process.c
* @function get_proc
* @author 酸菜。
* @date 2021-05-10
*/
int get_proc(unsigned char *pu1Filename, unsigned char *pu1SearchStr, struct proc_struct* array, int size)
{
FILE *pFile;
static int nRet = 0;
unsigned char au1Buf[80];
unsigned char au1ReadStr[80];
unsigned char au1StrValue[80];
unsigned char au1TmpValue[80];
unsigned char *pu1Temp;
pFile = fopen ((const char*)pu1Filename, "r");
if ((pFile == NULL) || (size <= 0) || (array == NULL))
{
return 0;
}
memset(au1Buf, 0, 80);
while ((!feof (pFile)) && nRet < size)
{
fgets (au1Buf, 80, pFile);
if ((strstr (au1Buf, pu1SearchStr)) != NULL)
{
memset (au1ReadStr, 0, 80);
memset (au1StrValue, 0, 80);
memset (au1TmpValue, 0, 80);
sscanf(au1Buf, "%s%s%s", au1ReadStr, au1StrValue, au1TmpValue);
/*一行一行读取,不是要读取的字符串就直接下一个*/
if (strcmp (au1ReadStr, pu1SearchStr) != 0)
{
continue;
}
/*将读取到的value保存到结构体数组当中*/
if (strlen (au1TmpValue) != 0)
{
strcpy (&array->process_name[nRet], au1TmpValue);
}
else
{
pu1Temp = au1StrValue;
pu1Temp++;
strcpy(&array->process_name[nRet], pu1Temp);
}
nRet++;
break;
}
}
fclose (pFile);
return nRet;
}
/*
* @file process.c
* @function startProc
* @author 酸菜。
* @date 2021-05-10
*/
int startProc(struct proc_struct* proc, int must_run_size)
{
if(proc == NULL)
{
return 0;
}
int pid = fork();
if(pid == 0)
{
pid = fork();
if(pid == 0)
{
execl("/home/txj/test1", (char *)proc->process_name, NULL);
}
else
{
exit(0);
}
sleep(2);
}
else
{
/*不用关心子进程的退出状态,这里为了
避免子进程成为僵死进程直接使用NULL即可*/
wait(NULL);
sleep(1);
}
return 0;
}
/*
* @file process.c
* @function moniter_run
* @author 酸菜。
* @date 2021-05-10
*/
int moniter_run(struct proc_struct *must_run_proc, int proc_size)
{
int i4Index = 0;
for(i4Index = 0; i4Index < must_run_size; i4Index++)
{
if(check_proc(&(must_run_proc[i4Index])) <= 0)
{
startProc(&(must_run_proc[i4Index]), proc_size);
}
}
return 1;
}
/*
* @file process.c
* @function exit_proc
* @author 酸菜。
* @date 2021-05-10
*/
void exit_proc(int sig)
{
(void)sig;
kill(getpid(), SIGTERM);
exit(0);
}
#ifndef _PROCESS_H_
#define _PROCESS_H_
#include <memory.h>
#include <signal.h>
#include <pthread.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <dirent.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/stat.h>
#define PROCES "/proc"
#define SIZE 1024
#define MAX_PROC_NAME 80
/*进程结构体定义,保存从配置文件里读到的信息*/
struct proc_struct
{
char process_name[MAX_PROC_NAME];
int pid;
};
int creat_daemon();
int check_proc(struct proc_struct* array);
int proc_find(struct proc_struct* procl ,struct proc_struct* proc);
int get_proc(unsigned char *pu1FileName, unsigned char *pu1SearchStr, struct proc_struct* array,int size);
int startProc(struct proc_struct* proc, int must_run_size);
int moniter_run(struct proc_struct *must_run_proc, int proc_size);
void run_moniter(char *filename);
void exit_proc(int sig);
#endif
init.txt
aa =test1