linux中Daemon守护进程编程
?守護進程,也就是通常說的Daemon進程,是Linux中的后臺服務進程。它是一個生存期較長的進程,通常獨立于控制終端并且周期性地執行某種任務或等待處理某些發生的事件。守護進程常常在系統引導裝入時啟動,在系統關閉時終止。Linux系統有很多守護進程,大多數服務都是通過守護進程實現的,同時,守護進程還能完成許多系統任務,例如,作業規劃進程crond、打印進程lqd等(這里的結尾字母d就是Daemon的意思)。
????? 一般情況下守護進程可以通過以下幾種方式產生:
1,在系統啟動的時候由啟動腳本啟動,這些啟動腳本通常放在/etc/rc.d目錄下
2,利用inetd超級系統服務器啟動,如telnet等
3,由cron定時啟動以及在終端用nohup啟動的進程也是守護進程
???? 由于在Linux中,每一個系統與用戶進行交流的界面稱為終端,每一個從此終端開始運行的進程都會依附于這個終端,這個終端就稱為這些進程的控制終端,當控制終端被關閉時,相應的進程都會自動關閉。但是守護進程卻能夠突破這種限制,它從被執行開始運轉,直到整個系統關閉時才退出。如果想讓某個進程不因為用戶或終端或其他地變化而受到影響,那么就必須把這個進程變成一個守護進程。
守護進程的變成要點:
1. 蔽一些有關控制終端操作的信號
?? 這是為了防止在守護進程還沒悠運行之前,控制終端收到干擾推出或者掛起
signal(SIGTTOU,SIG_IGN);
signal(SIGTTIN,SIG_IGN);
signal(SIGTSTP,SIG_IGN);
signal(SIGHUP,SIG_IGN);
2. 在后臺運行。
為避免掛起控制終端而將Daemon放入后臺執行。方法是在進程中調用fork使父進程終止,讓Daemon在子進程中后臺執行。
??????if(pid=fork())
????????? exit(0);//是父進程,結束父進程,子進程繼續
3. 脫離控制終端,登錄會話和進程組
????? 進程屬于一個進程組,進程組號(GID)就是進程組長的進程號(PID)。登錄會話可以包含多個進程組。這些進程組共享一個控制終端。這個控制終端通常是創建進程的登錄終端。控制終端,登錄會話和進程組通常是從父進程繼承下來的。我們的目的就是要擺脫它們,使之不受它們的影響。方法是在第1點的基礎上,調用setsid()使進程成為會話組長:
????setsid()
4. 關閉打開的文件描述符
進程從創建它的父進程那里繼承了打開的文件描述符。如不關閉,將會浪費系統資源,造成進程所在的文件系統無法卸下以及引起無法預料的錯誤。按如下方法關閉它們:
??#define?? NOFILE?? 256? ;//不同系統中不同數值
? for(i=0;i<NOFILE;i++)
???????? colse(i);
5. 改變當前工作目錄
???? 進程活動時,其工作目錄所在的文件系統不能卸下。一般需要將工作目錄改變到根目錄。對于需要轉儲核心,寫運行日志的進程將工作目錄改變到特定目錄如/tmpchdir("/")
?? chdir("/");
6. 重設文件創建掩模
??? 進程從創建它的父進程那里繼承了文件創建掩模。它可能修改守護進程所創建的文件的存取位。為防止這一點,將文件創建掩模清除0:
?? umask(0);
7. 處理SIGCHLD(子進程退出信號)信號
?? 處理SIGCHLD信號并不是必須的。但對于某些進程,特別是服務器進程往往在請求到來時生成子進程處理請求。如果父進程不等待子進程結束,子進程 將成為僵尸進程(zombie)從而占用系統資源。如果父進程等待子進程結束,將增加父進程的負擔,影響服務器進程的并發性能。在Linux下可以簡單地 將SIGCHLD信號的操作設為SIG_IGN。
?signal(SIGCHLD,SIG_IGN);
下面給出一個例程
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <fcntl.h>
#include <sys/syslog.h>
#include <sys/param.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <time.h>
int init_daemon(const char *pname,int facility)
{
int pid;
int i;
/*忽略可能的終端信號*/
signal(SIGTTOU,SIG_IGN);
signal(SIGTTIN,SIG_IGN);
signal(SIGTSTP,SIG_IGN);
signal(SIGHUP,SIG_IGN);
//創建子進程,父進程推出
if( (pid=fork()))
exit(EXIT_SUCCESS);//是父進程,結束父進程,子進程繼續
else if(pid < 0)
{
perror("fork error!\n");
exit(EXIT_FAILURE);
}
setsid();//設置新會話組長,脫離終端
for(i=0;i<NOFILE;i++)
close(i);
open("/dev/null",O_RDONLY);
open("/dev/null",O_RDWR);
open("/dev/null",O_RDWR);
chdir("/");
umask(0);
signal(SIGCHLD,SIG_IGN);
openlog(pname,LOG_PID,facility);
return 0;
}
int main(int argc,char *argv[])
{
time_t ticks;
init_daemon(argv[0],LOG_KERN);
while(1)
{
sleep(1);
ticks = time(NULL); //讀取當前時間
syslog(LOG_INFO,"%s",asctime(localtime(&ticks)));//寫日志信息
}
return 0;
}
運行之后,使用???????????????????????tail -n 1 ? /var/log/message
就可以查看到日志信息了。
(清悠我心:http://hi.baidu.com/%C7%E5%D3%C6%CE%D2%D0%C4/blog/category/linux%D3%A6%D3%C3%B1%E0%B3%CC)
總結
以上是生活随笔為你收集整理的linux中Daemon守护进程编程的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: (原創) 深入探討blocking與no
- 下一篇: 毫秒级的时间处理上G的图片(生成缩略图)