守护进程简单的说就是在后台运行的服务,它的特点是后台运行,脱离终端。如何实现一个守护进程呢?为了阐述清楚,先解释些预备知识。
1. 预备知识
1.1. 进程,进程组和会话关系
进程组是进程的集合,会话又是进程组的集合。何为会话?会话就是用户登陆linux系统时建立的一个连接。每个会话又有个领头进程。进程组可以理解为shell中输入的一条命令,比如一个linux可执行文件,执行后会启动一个进程,这个进程又fork出一些子进程,这些进程就是一个进程组,而这些进程组的最初始者就为进程组长。一个session只能有一个前台进程组,用于和终端交互,前台进程组的领头组长一般是bash。
会话、进程组、进程与控制终端的关系
1.2. 僵尸进程和孤儿进程
僵尸进程:子进程死亡,父进程并没有调用wait或waitpid获取子进程的状态信息,那么子进程的进程描述符仍然保存在系统中。这种进程称之为僵死进程。
孤儿进程:父进程死亡,子进程成了“孤儿”被init进程收购。
如果进程不调用wait / waitpid的话,那么保留的那段信息就不会释放,其进程号就会一直被占用,但是系统所能使用的进程号是有限的,如果大量的产生僵死进程,将因为没有可用的进程号而导致系统不能产生新的进程. 此即为僵尸进程的危害,应当避免。
2. Demo
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <sys/param.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <time.h>
#define SHUTDOWNTIME 120 // shutdown OS 2 minuteslater
void init_daemon(void)
{
int pid;
int i;
if(pid=fork())
exit(0); //是父进程,结束父进程
else if(pid< 0)
exit(1); //fork失败,退出
//是第一子进程,后台继续执行
setsid(); //第一子进程成为新的会话组长和进程组长
//并与控制终端分离
if(pid=fork())
exit(0); //是第一子进程,结束第一子进程
else if(pid< 0)
exit(1); //fork失败,退出
//是第二子进程,继续
//第二子进程不再是会话组长
for(i=0;i<NOFILE;++i) //关闭打开的文件描述符
close(i);
chdir("/"); //改变工作目录到/tmp
umask(0); //重设文件创建掩模
return;
}
void sig_child(int signo)
{
pid_t pid;
int stat;
//处理僵尸进程
while ((pid = waitpid(-1, &stat, WNOHANG)) >0)
printf("child %dterminated.\n", pid);
}
void GetTime(int *ps32Time)
{
characCmdStr[100];
char acTemp[4];
FILE *fp;
int i;
signal(SIGCHLD,sig_child);
for(i = 0; i <3; i++)
{
sprintf(acCmdStr,"%s%d","date | cut -d\" \" -f4 | cut -d: -f ",i + 1);
fp = popen(acCmdStr,"r"); // 注意因为popen为重启一个进程执行shell命令,可能会产//生僵尸进程,需要signal处理
fgets(acTemp,sizeof(acTemp),fp);
*(ps32Time + i) =atoi(acTemp);
}
pclose(fp);
}
int main()
{
ints32StartTime[3];
int s32CurTime[3];
ints32TimeInterval = 0;
init_daemon();
GetTime(s32StartTime);
while(1)
{
GetTime(s32CurTime);
s32TimeInterval = (s32CurTime[0] - s32StartTime[0]) * 3600 +(s32CurTime[1] - s32StartTime[1]) * 60 + s32CurTime[2] - s32StartTime[2];
if(s32TimeInterval < 0)
{
s32TimeInterval += 24 * 3600;
}
if(s32TimeInterval >= SHUTDOWNTIME)
{
// dowith something
}
sleep(60); //sleep 60s
}
return 0;
} }
sleep(60); //sleep 60s
}
return 0;
}
转载于:https://blog.51cto.com/4895268/1425421