Linux守候進程

在一個遠程監控系統中,我們使用了守候進程。結合《Linux高級程序設計》的相關內容,對守候進程做個整理。

守候進程,又稱守護進程(Daemon),是在後臺運行的一種特殊的進程,脫離於終端。類似於Windows服務程序。守候進程適用於像我們項目中的數據採集類的程序,因爲客戶的誤操作等原因,造成服務器的重啓,這時要保證數據的接收是正常的,那麼,很有必要將採集程序運行在後臺,不被顯示的終端界面所影響。

我們使用在系統啓動時,隨啓動腳本來啓動守候進程, 在/etc/rc.local里加上一句 /usr/local/haven/Daemon(即你的程序所在路徑)。

 

守候進程的編程步驟一般比較死,都是規定好的,是一個套路:

1、屏蔽一些有關控制終端操作的信號;防止在守護進程沒有正常運行起來前,控制終端收到干擾退出或掛起。

2、在後臺運行,爲了避免掛起控制終端將其放入後臺執行。

3、脫離控制終端和進程,控制終端和進程組是從父進程繼承下來的,要擺脫他們,使子進程成爲新的會話組長。

4.、禁止進程重新打開控制終端,因爲可以重新申請打開一個控制終端,那麼再創建一個子進程。

5.、關閉打開的文件描述符,若不關閉會浪費系統資源。

6、改變當前工作目錄,進程工作時,其工作目錄在文件系統不能寫下的。因此放在根目錄,寫運行日誌的進程將工作目錄改變到特定目錄。

7、重設文件創建掩碼。

8、處理SIGCHLD信號(子進程退出信號)。對於某些,特別是服務器進程往往在請求到來時生成子進程處理請求。如果父進程不等待子進程結束,子進程將成爲殭屍進程從而佔用了資源,如果父進程等待子進程結束,將增加父進程的負擔,影響服務器進程的併發性能。從而使用此步驟來解決這一問題。

下面是一個簡單實現:Daemon.c

 

  1. #include<unistd.h>  
  2. #include<signal.h>  
  3. #include<fcntl.h>  
  4. #include<sys/syslog.h>  
  5. #include<sys/param.h>  
  6. #include<sys/stat.h>  
  7. #include<stdio.h>  
  8. #include<stdlib.h>  
  9.  
  10. int init_daemon(const char *pname,int facility)  
  11. {  
  12.     int pid;  
  13.     int i;  
  14.     signal(SIGTTOU,SIG_IGN);   //處理可能的終端信號  
  15.     signal(SIGTTIN,SIG_IGN);  
  16.     signal(SIGTSTP,SIG_IGN);  
  17.     signal(SIGHUP ,SIG_IGN);  
  18.  
  19.     if(pid=fork())                       //創建子進程,父親進程退出  
  20.     {  
  21.        exit(EXIT_SUCCESS);  
  22.     }  
  23.     else if(pid<0)  
  24.     {  
  25.        perror("fork");  
  26.        exit(EXIT_FAILURE);  
  27.     }  
  28.     setsid();                           //設置新會話組長,新進程組長,脫離終端  
  29.     if(pid=fork())                    //創建新進程,子進程不能再申請終端  
  30.     {  
  31.        exit(EXIT_SUCCESS);  
  32.     }  
  33.     else if(pid<0)  
  34.     {  
  35.        perror("fork");  
  36.     }  
  37.     for(i=0;i<NOFILE;++i) //關閉父進程打開的文件描述符  
  38.        close(i);  
  39.     open("/dev/null",O_RDONLY); //對標準輸入全部重新定向到文件中  
  40.     open("/dev/null",O_RDWR);  
  41.     open("/dev/null",O_RDWR);  
  42.  
  43.     chdir("/tmp");                    //修改主目錄  
  44.     umask(0);                        // 重建設置文件掩碼  
  45.     signal(SIGCHLD,SIG_IGN);   //處理子進程退出  
  46.     openlog(pname,LOG_PID,facility); //與守護進程建立聯繫,加上進程號,文件名  
  47.     return ;  
  48. }  
  49.  
  50. int main(int argc ,char *argv[])  
  51. {  
  52.     FILE *fp;  
  53.     time_t ticks;  
  54.     init_daemon(argv[0],LOG_KERN);//執行守候進程  
  55.     while(1)  
  56.     {  
  57.        sleep(1);  
  58.        ticks=time(NULL);  
  59.        syslog(LOG_INFO, "%s", asctime(localtime(&ticks))); //寫日誌信息  
  60.     }  

編譯運行:

[root@localhost haven]# gcc -o Daemon Daemon.c
[root@localhost haven]# ./Daemon

查看:
[root@localhost haven]# ps aux|grep Daemon
root     13021  0.0  0.0   1648   420 ?        S    14:26   0:00 ./Daemon
root     13092  0.0  0.0   3916   660 pts/1    R+   14:28   0:00 grep Daemon

查看日誌:
[root@localhost haven]# tail /var/log/messages
Feb 29 14:28:53 localhost ./Daemon[13021]: Wed Feb 29 14:28:53 2012
Feb 29 14:28:54 localhost ./Daemon[13021]: Wed Feb 29 14:28:54 2012
Feb 29 14:28:55 localhost ./Daemon[13021]: Wed Feb 29 14:28:55 2012
Feb 29 14:28:56 localhost ./Daemon[13021]: Wed Feb 29 14:28:56 2012
Feb 29 14:28:57 localhost ./Daemon[13021]: Wed Feb 29 14:28:57 2012
Feb 29 14:28:58 localhost ./Daemon[13021]: Wed Feb 29 14:28:58 2012
Feb 29 14:28:59 localhost ./Daemon[13021]: Wed Feb 29 14:28:59 2012
Feb 29 14:29:00 localhost ./Daemon[13021]: Wed Feb 29 14:29:00 2012
Feb 29 14:29:01 localhost ./Daemon[13021]: Wed Feb 29 14:29:01 2012
Feb 29 14:29:02 localhost ./Daemon[13021]: Wed Feb 29 14:29:02 2012

 

by HavenZhao    http://vcsky.net

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