守護進程簡單的說就是在後臺運行的服務,它的特點是後臺運行,脫離終端。如何實現一個守護進程呢?爲了闡述清楚,先解釋些預備知識。
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;
}