1. 程式人生 > >"守護程序"(daemon)就是一直在後臺執行的程序

"守護程序"(daemon)就是一直在後臺執行的程序

//fork執行中已經出現父和子程序,狀態一樣但不是相同的程序,兩條程序執行序都指向了fork函式內建立程序程式碼後面一句的指令集,
        //此時是父程序佔據cpu時間,父程序繼續執行根據fork後面的程式碼實現返回建立的pid,
        //子程序之後繼續執行根據fork程式碼實現返回的是0
        //建立子程序失敗返回-1
        $pid = pcntl_fork();
        if (-1 === $pid) {
            throw new Exception('fork fail');
        } elseif ($pid > 0) {
            exit(0);
        }

在Linux/UNIX系統引導的時候會開啟很多服務,這些服務稱為守護程序(也叫Daemon程序)。守護程序是脫離於控制終端並且在後臺週期性地執行某種任務或等待處理某些事件的程序,脫離終端是為了避免程序在執行過程中的資訊在任何終端上顯示並且程序也不會被任何終端所產生的中斷資訊所終止。

建立守護程序的一般步驟

(1) 建立子程序,退出父程序

為了脫離控制終端需要退出父程序,之後的工作都由子程序完成。在Linux中父程序先於子程序退出會造成子程序成為孤兒程序,而每當系統發現一個孤兒程序時,就會自動由1號程序(init)收養它,這樣,原先的子程序就會變成init程序的子程序。

ps –ef | grep ProcName          通過PID/PPID檢視程序的父子關係

(2) 在子程序中建立新的會話

使用系統函式setsid來完成。

man 2 setsid    檢視關於setsid函式的說明

setsid – creates a session and sets theprocess group ID

#include <unistd.h>

pid_t setsid(void);

setsid() creates a new session if thecalling process is not a process group leader. The calling process is theleader of the new session, the process group leader of the new process group,and has no controlling tty. The process group ID and session ID of the callingprocess are set to the PID of the calling process. The calling process will bethe only process in this new process group and in this new session.

程序組:是一個或多個程序的集合。程序組有程序組ID來唯一標識。除了程序號PID之外,程序組ID也是一個程序的必備屬性。每個程序組都有一個組長程序,其組長程序的程序號等於程序組ID,且該程序組ID不會因組長程序的退出而受到影響。

setsid函式作用:用於建立一個新的會話,並擔任該會話組的組長。呼叫setsid有3個作用

(a) 讓程序擺脫原會話的控制;

(b) 讓程序擺脫原程序組的控制;

(c) 讓程序擺脫原控制終端的控制;

使用setsid函式的目的:由於建立守護程序的第一步呼叫了fork函式來建立子程序再將父程序退出。由於在呼叫fork函式時,子程序拷貝了父程序的會話期、程序組、控制終端等,雖然父程序退出了,但會話期、程序組、控制終端等並沒有改變,因此,這還不是真正意義上的獨立開了。使用setsid函式後,能夠使程序完全獨立出來,從而擺脫其他程序的控制。

(3) 改變當前目錄為根目錄

使用fork建立的子程序繼承了父程序的當前的工作目錄。由於在程序執行中,當前目錄所在的檔案系統是不能解除安裝的,這對以後的使用會造成諸多的麻煩。因此,通常的做法是讓根目錄”/”作為守護程序的當前工作目錄。這樣就可以避免上述的問題。如有特殊的需求,也可以把當前工作目錄換成其他的路徑。改變工作目錄的方法是使用chdir函式。

(4) 重設檔案許可權掩碼

檔案許可權掩碼:是指遮蔽掉檔案許可權中的對應位。例如,有個檔案許可權掩碼是050,它就遮蔽了檔案組擁有者的可讀與可執行許可權(對應二進位制為,rwx, 101)。由於fork函式建立的子程序繼承了父程序的檔案許可權掩碼,這就給子程序使用檔案帶來了諸多的麻煩。因此,把檔案許可權掩碼設定為0(即,不遮蔽任何許可權),可以增強該守護程序的靈活性。設定檔案許可權掩碼的函式是umask。通常的使用方法為umask(0)。

(5) 關閉檔案描述符

用fork建立的子程序也會從父程序那裡繼承一些已經打開了的檔案。這些被開啟的檔案可能永遠不會被守護程序讀寫,但它們一樣消耗系統資源,而且可能導致所在的檔案系統無法解除安裝。在使用setsid呼叫之後,守護程序已經與所屬的控制終端失去了聯絡,因此從終端輸入的字元不可能達到守護程序,守護程序中用常規方法(如printf)輸出的字元也不可能在終端上顯示出來。所以,檔案描述符為0、1、2(即,標準輸入、標準輸出、標準錯誤輸出)的三個檔案已經失去了存在的價值,也應該關閉。

(6) 守護程序退出處理

當用戶需要外部停止守護程序時,通常使用kill命令停止該守護程序。所以,守護程序中需要編碼來實現kill發出的signal訊號處理,達到程序正常退出。

http://blog.csdn.net/delphiwcdj/article/details/7364343

http://www.ruanyifeng.com/blog/2016/02/linux-daemon.html

當我們只fork()一次後,存在父程序和子程序。這時有兩種方法來避免產生殭屍程序:

  • 父程序呼叫waitpid()等函式來接收子程序退出狀態。
  • 父程序先結束,子程序則自動託管到Init程序(pid = 1)。

      目前先考慮子程序先於父程序結束的情況:     

  • 若父程序未處理子程序退出狀態,在父程序退出前,子程序一直處於殭屍程序狀態。
  • 若父程序呼叫waitpid()(這裡使用阻塞呼叫確保子程序先於父程序結束)來等待子程序結束,將會使父程序在呼叫waitpid()後進入睡眠狀態,只有子程序結束父程序的waitpid()才會返回。 如果存在子程序結束,但父程序還未執行到waitpid()的情況,那麼這段時期子程序也將處於殭屍程序狀態。

      由此,可以看出父程序與子程序有父子關係,除非保證父程序先於子程序結束或者保證父程序在子程序結束前執行waitpid(),子程序均有機會成為殭屍程序。那麼如何使父程序更方便地建立不會成為殭屍程序的子程序呢?這就要用兩次fork()了。

      父程序一次fork()後產生一個子程序隨後立即執行waitpid(子程序pid, NULL, 0)來等待子程序結束,然後子程序fork()後產生孫子程序隨後立即exit(0)。這樣子程序順利終止(父程序僅僅給子程序收屍,並不需要子程序的返回值),然後父程序繼續執行。這時的孫子程序由於失去了它的父程序(即是父程序的子程序),將被轉交給Init程序託管。於是父程序與孫子程序無繼承關係了,它們的父程序均為Init,Init程序在其子程序結束時會自動收屍,這樣也就不會產生殭屍程序了。

#include <stdio.h>  
#include <unistd.h>  
#include <stdlib.h>  
#include <sys/wait.h>  
  
int main(void)  
{  
    pid_t   pid;  
  
    if( ( pid = fork() ) < 0 ){  
        fprintf( stdout, "fork error!\n" );  
    } else if( pid == 0 ) {                     /*first child*/  
        if (( pid = fork()) < 0 )  
            printf( "fork error!\n" );  
        else if( pid > 0 )  
            exit( 0 );  
      
    sleep( 2 );  
    printf( "Second child , parent pid = %d\n", getppid() );  
    exit( 0 );            
    }  
  
    if( waitpid( pid, NULL, 0 ) != pid )  
        printf( "waitpid error!\n" );  
  
    printf( "father of original!\n" );  
  
    exit( 0 );  
  
  
}

相關推薦

"守護程序"daemon就是一直後臺執行程序

//fork執行中已經出現父和子程序,狀態一樣但不是相同的程序,兩條程序執行序都指向了fork函式內建立程序程式碼後面一句的指令集, //此時是父程序佔據cpu時間,父程序繼續執行根據fork後面的程式碼實現返回建立的pid, //子程

Linux學習——守護程序daemon

建立守護程序的步驟: 1)父程序中執行fork後,執行exit退出; 2)在子程序中呼叫setsid;(脫離控制檯) 3)讓根目錄“/”成為子程序的工作目錄; 4)把子程序的umask變為0; 5)關閉任何不需要的檔案描述符。 其中,setsid函式建立一個新會話和一個新程

用C語言在Linux系統下建立守護程序Daemon

      守護程序(daemon)是指在後臺執行的,沒有控制終端與之相連的程序。它獨立於控制終端,週期性地執行某種任務。Linux的大多數伺服器就是用守護程序的方式實現的。如web伺服器程序http等。守護程序在後臺執行,類似於Windows中的系統服務。      

Python中多程序的使用 Python的多執行threading與多程序multiprocessing 示例程式碼 Python多程序程式設計

程序:程式的一次執行(程式載入記憶體,系統分配資源執行)。每個程序有自己的記憶體空間,資料棧等,程序之間可以進行通訊,但是不能共享資訊。 執行緒:所有的執行緒執行在同一個程序中,共享相同的執行環境。每個獨立的執行緒有一個程式入口,順序執行序列和程式的出口。 執行緒的執行可以被強佔,中斷或者暫時被

go lang 後臺守護程序執行daemon

引用:https://bitbucket.org/kardianos/service service will install / un-install, start / stop, and run a program as a service (daemon).

linux系統程式設計之程序守護程序詳解及建立,daemon()使用

一,守護程序概述 Linux Daemon(守護程序)是執行在後臺的一種特殊程序。它獨立於控制終端並且週期性地執行某種任務或等待處理某些發生的事件。它不需要使用者輸入就能執行而且提供某種服務,不是對整個系統就是對某個使用者程式提供服務。Linux系統的大多數伺服器就是通過守護程序實現的。常見的守護程序包括系

linux 編寫守護程序例子 Daemon

例子如下 #include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <unistd.h>  //fork int Daemon(void)

php寫守護進程Daemon

waitpid tar cas gid 函數的參數 日誌 enabled pcntl 有一個 護進程(Daemon)是運行在後臺的一種特殊進程。它獨立於控制終端並且周期性地執行某種任務或等待處理某些發生的事件。守護進程是一種很有用的進程。php也可以實現守護進程的功能。

rsync後臺服務方式daemon、linux日誌

例如 核心 lin messages 免密 開機啟動 網絡 全部 輸入 一:rsync後臺服務方式(daemon) 可以理解為,在遠程主機上建立一個rsync服務器,在服務器上配置好rsync的各種應用,然後本機作為rsync的一個客戶端去連接遠程的rsync服務器。先配置

Java 多線程守護線程Daemon

機會 兩種 如何 產生 tex begin 就會 set final 定義 Java 中有兩種線程: 一種是用戶線程(User Thread),一種是守護線程(Daemon Thread)。 守護線程是一種特殊的線程, 它的特殊有“陪伴”的含義, 當線程中不存在非守護線程時

php 守護程序 簡單

首先需要解釋的是什麼是守護程序。 守護程序就是在後臺一直執行的程序。比如我們啟動的httpd,mysqld等程序都是常駐記憶體內執行的程式。 針對需求進行分析: 需求:有一個常駐佇列messageQueue(假設在redis記憶體中),這個佇列會有可能有請求不定期的往佇列中增加元素。同時我們要求在佇列中

守護程序瞭解

守護程序 主程序建立子程序,然後將該程序設定成守護自己的程序,守護程序伴隨著子程序的結束而結束。 如果我們有兩個任務需要併發執行,那麼開一個主程序和一個子程序分別去執行就ok了,如果子程序的任務在主程序任務結束後就沒有存在的必要了,那麼該子程序應該在開啟前就被設定成守護程序。主程序程式碼執行結束,守護程序

Python多執行緒與多程序程式設計 這麼簡單

""" <axiner>宣告:(錯了另刂扌丁我) (如若有誤,請記得指出喲,謝謝了!!!) """ 多程序程式設計>>>見上篇   什麼時候用多程序程式設計? 由於 GIL鎖,多執行緒無法充分多核優勢。即在耗cpu時,多執行緒無法去並行

Python多執行緒與多程序程式設計 這麼簡單

""" <axiner>宣告:(錯了另刂扌丁我) (如若有誤,請記得指出喲,謝謝了!!!) """ 先來了解一個概念,GIL? GIL的全稱為Global Interpreter Lock, 全域性直譯器鎖。 Python程式碼的執行由Python 虛擬機器(也叫直譯器主

【Oracle 叢集】ORACLE DATABASE 11G RAC 知識圖文詳細教程之快取融合技術和主要後臺程序

      前面已經介紹了 RAC 的後臺程序,為了更深入的瞭解這些後臺程序的工作原理,先了解一下 RAC 中多節點對共享資料檔案訪問的管理是如何進行的。要了解 RAC 工作原理的中心,需要知道 Cache Fusion 這個重要的概念,要發揮 Cache Fusion 的作用,要有一個前提條件,那就

用vbs等實現輔助網站的後臺執行工作程序

現在我們開始考慮監控程序,剛開始我考慮重用我們前面的後臺程序的設計,讓ASP頁面去做這個工作,但是考慮到IIS沒有許可權執行重啟Windows服務這麼核心的操作,所以只能將這個工作放在vbs中去做了。 還好我們的vbs都是通過新增到服務的方式,用SYSTEM使

Mac OS守護程序服務列表及優化建議

/sbin/launchd系統及使用者程序管理器,它是核心裝載成功後在OS環境下啟動的第一個程序,是Mac OS最重要的程序之一。你無法禁用它。 /usr/libexec/kextd 核心擴充套件服務,響應核心或使用者程序的請求,比如裝載或解除安裝核心擴充套件或提供核心

java多執行緒之守護執行Daemon

在Java中有兩類執行緒:User Thread(使用者執行緒)、Daemon Thread(守護執行緒)  用個比較通俗的比如,任何一個守護執行緒都是整個JVM中所有非守護執行緒的保姆: 只要當前JVM例項中尚存在任何一個非守護執行緒沒有結束,守護執行緒就全部工作;

java併發程式設計:之守護執行Daemon

在Java中有兩類執行緒:User Thread(使用者執行緒)、Daemon Thread(守護執行緒) 用個比較通俗的比喻,任何一個守護執行緒都是整個JVM中所有非守護執行緒的保姆:只要當前JVM例項中尚存在任何一個非守護執行緒沒有結束,守護執行緒就全部工作;只有當最後一

[日更-2019.5.18] Android 系統內的守護程序--core類中的服務 : adbd

宣告 其實很好奇Android系統中的一些關鍵守護程序服務的作用; 暫且大概分析下它們的作用,這樣有助於理解整個系統的工作過程;