linux上編寫守護程序的例程

2021-05-23 16:22:39 字數 4179 閱讀 5875

linux上編寫守護程序的例程

摘自《開放系統世界》

2023年第5

期郭吉平、任蓮的文章

「親自動手編寫守護程序」。

/*郭吉平、任蓮

親自動手編寫守護程序

*/#include

#include

#include

void main(int argc, char ** argv)

} 守護程序在

linux/unix

系統中有著廣泛的應用。有時,開發人員也想把自己的程式變成守護程序。在建立乙個守護程序的時候,要接觸到子程序、程序組、會晤期、訊號機制、檔案、目錄和控制終端等多個概念。因此守護程序還是比較複雜的,在這裡詳細地討論

linux/unix

的守護程序的編寫,總結出八條經驗,並給出應用範例。

程式設計要點

1.遮蔽一些有關控制終端操作的訊號。防止在守護程序沒有正常運轉起來時,控制終端受到干擾退出或掛起。示例如下:

signal(sigttou,sig_ign);

signal(sigttin,sig_ign);

signal(sigtstp,sig_ign);

signal(sighup ,sig_ign);

所有的訊號都有自己的名字。這些名字都以

「sig」

開頭,只是後面有所不同。開發人員可以通過這些名字了解到系統中發生了什麼事。當訊號出現時,開發人員可以要求系統進行以下三種操作:

◆忽略訊號。大多數訊號都是採取這種方式進行處理的,這裡就採用了這種用法。但值得注意的是對

sigkill

和sigstop

訊號不能做忽略處理。

◆捕捉訊號。最常見的情況就是,如果捕捉到

sigchid

訊號,則表示子程序已經終止。然後可在此訊號的捕捉函式中呼叫

waitpid()

函式取得該子程序的程序

id和它的終止狀態。另外,如果程序建立了臨時檔案,那麼就要為程序終止訊號

sigterm

編寫乙個訊號捕捉函式來清除這些臨時檔案。

◆執行系統的預設動作。對絕大多數訊號而言,系統的預設動作都是終止該程序。

對這些有關終端的訊號,一般採用忽略處理,從而保障了終端免受干擾。

這類訊號分別是,

sigttou

(表示後台程序寫控制終端)、

sigttin

(表示後台程序讀控制終端)、

sigtstp

(表示終端掛起)和

sighup

(程序組長退出時向所有會議成員發出的)。

2.將程式進入後台執行。由於守護程序最終脫離控制終端,到後台去執行。方法是在程序中呼叫

fork

使父程序終止,讓

daemon

在子程序中後台執行。這就是常說的「脫殼

」。子程序繼續函式

fork()

的定義如下:

#include

#include

pid_t fork(void);

該函式是

linux/unix

程式設計中非常重要的函式。它被呼叫一次,但返回兩次。這兩次返回的區別是子程序的返回值為

「0」,而父程序的返回值為子程序的

id。如果出錯則返回

「-1」。3.

脫離控制終端、登入會話和程序組。開發人員如果要擺脫它們,不受它們的影響,一般使用

setsid()

設定新會話的領頭程序,並與原來的登入會話和程序組脫離。這只是其中的一種方法,也有如下處理的辦法:

if((fd = open("/dev/tty",o_rdwr)) >= 0) 其中

/dev/tty

是乙個流裝置,也是終端對映,呼叫

close()

函式將終端關閉。

4.禁止程序重新開啟控制終端。程序已經成為無終端的會話組長,但它可以重新申請開啟乙個控制終端。開發人員可以通過不再讓程序成為會話組長的方式來禁止程序重新開啟控制終端,需要再次呼叫

fork

函式。上面的程式**表示結束第一子程序,第二子程序繼續(第二子程序不再是會話組長)。

5. 關閉開啟的檔案描述符,並重定向標準輸入、標準輸出和標準錯誤輸出的檔案描述符。程序從建立它的父程序那裡繼承了開啟的檔案描述符。如果不關閉,將會浪費系統資源,引起無法預料的錯誤。關閉三者的**如下:

for (fd = 0, fdtablesize = getdtablesize();fd < fdtablesize; fd++)close(fd);

但標準輸入、標準輸出和標準錯誤輸出的重定向是可選的。也許有的程式想保留標準輸入(

0)、標準輸出(

1)和標準錯誤輸出(

2),那麼迴圈應繞過這三者。**如下:

for (fd =3, fdtablesize = getdtablesize();fd < fdtablesize; fd++)close(fd);

有的程式有些特殊的需求,還需要將這三者重新定向。示例如下:

error=open("/tmp/error",o_wronly|o_creat,0600);dup2(error,2); close(error); in=open("/tmp/in",o_rdonly|o_creat,0600); if(dup2(in,0)==-1)perror("in"); close(in);

out=open("/tmp/out",o_wronly|o_creat,0600); if(dup2(out,1)==-1) perror("out"); close(out); 6.

改變工作目錄到根目錄或特定目錄程序活動時,其工作目錄所在的檔案系統不能卸下。

一般需要將工作目錄改變到根目錄或特定目錄,注意使用者對此目錄需要有讀寫權。防止超級使用者解除安裝裝置時系統報告裝置忙。

7.處理

sigchld

訊號。sigchld

訊號是子程序結束時,向核心傳送的訊號。

如果父程序不等待子程序結束,子程序將成為殭屍程序(

zombie

)從而占用系統資源。因此需要對

sigchld

訊號做出處理,**殭屍程序的資源,避免造成不必要的資源浪費。可以用如下語句:

signal(sigchld,(void *)reap_status);

捕捉訊號

sigchld

,用下面的函式進行處理:

void reap_status()

8.在linux/unix

下有個syslogd

的守護程序,向使用者提供了

syslog()

系統呼叫。任何程式都可以通過

syslog

記錄事件。

由於syslog

非常好用和易配置,所以很多程式都使用

syslog

來傳送它們的記錄資訊。一般守護程序也使用

syslog

向系統輸出資訊。

syslog

有三個函式,一般只需要用

syslog(...)

函式,openlog()/closelog()

可有可無。

syslog()

在shslog.h

定義如下:

#include

void syslog(int priority,char *format,...);

其中引數

priority

指明了程序要寫入資訊的等級和用途。第二個引數是乙個格式串,指定了記錄輸出的格式。在這個串的最後需要指定乙個

%m,對應

errno

錯誤碼。

應用範例

下面給出

linux

下程式設計的守護程序的應用範例,在

unix

中,不同版本實現的細節可能不一致,但其實現的原則是與

linux

一致的。

#include

#include

#include

main(int argc,char **argv) }

此程式在

turbo linux 4.0

下編譯通過。這個程式比較簡單,但基本體現了守護程序的程式設計要點。讀者針對實際應用中不同的需要,還可以做相應的調整。

linux

聯盟收集整理

編寫守護程序

include include include include include include void main int argc,char argv 守護程序在linux unix系統中有著廣泛的應用。有時,開發人員也想把自己的程式變成守護程序。在建立乙個守護程序的時候,要接觸到子程序 程序組 ...

Linux程序與守護程序的編寫試驗

1 編寫乙個程式建立乙個子程序,父程序隨後掛起,子程序迴圈列印自己的程序號和父程序號,並對比ps查詢到的程序號。2 編寫乙個程式建立n個子程序p1,p2,p3 pn,其中n由鍵盤輸入,p i 是p i 1 的父程序,列印每個程序的程序號,父程序號和子程序號。3 編寫乙個程式建立n個子程序p1,p2,...

編寫Linux Unix守護程序

守護程序在linux unix系統中有著廣泛的應用。有時,開發人員也想把自己的程式變成守護程序。在建立乙個守護程序的時候,要接觸到子程序 程序組 會晤期 訊號機制 檔案 目錄和控制終端等多個概念。因此守護程序還是比較複雜的,在這裡詳細地討論linux unix的守護程序的編寫,總結出八條經驗,並給出...