守護進程

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

1.      預備知識

1.1.   進程,進程組和會話關係

         進程組是進程的集合,會話又是進程組的集合。何爲會話?會話就是用戶登陸linux系統時建立的一個連接。每個會話又有個領頭進程。進程組可以理解爲shell中輸入的一條命令,比如一個linux可執行文件,執行後會啓動一個進程,這個進程又fork出一些子進程,這些進程就是一個進程組,而這些進程組的最初始者就爲進程組長。一個session只能有一個前臺進程組,用於和終端交互,前臺進程組的領頭組長一般是bash

會話、進程組、進程與控制終端的關係

1.2.   殭屍進程和孤兒進程

殭屍進程:子進程死亡,父進程並沒有調用waitwaitpid獲取子進程的狀態信息,那麼子進程的進程描述符仍然保存在系統中。這種進程稱之爲僵死進程。

孤兒進程:父進程死亡,子進程成了“孤兒”被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;

}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章