Intro 守護進程,也就是通常說的Daemon進程,是Linux中的後臺服務進程。它是一個生存期較長的進程,通常獨立於控制終端並且周期性地執行某種任務或等待處理某些發生的事件。守護進程常常在系統引導裝入時啟動,在系統關閉時終止。Linux系統有很多守護進程,大多數服務都是通過守護進程實現的,同時, ...
Intro
-----
守護進程,也就是通常說的Daemon進程,是Linux中的後臺服務進程。它是一個生存期較長的進程,通常獨立於控制終端並且周期性地執行某種任務或等待處理某些發生的事件。守護進程常常在系統引導裝入時啟動,在系統關閉時終止。Linux系統有很多守護進程,大多數服務都是通過守護進程實現的,同時,守護進程還能完成許多系統任務,例如,作業規划進程crond、列印進程lqd等(這裡的結尾字母d就是Daemon的意思)。
由於在Linux中,每一個系統與用戶進行交流的界面稱為終端,每一個從此終端開始運行的進程都會依附於這個終端,這個終端就稱為這些進程的控制終端,當控制終端被關閉時,相應的進程都會自動關閉。但是守護進程卻能夠突破這種限制,它從被執行開始運轉,直到整個系統關閉時才退出。如果想讓某個進程不因為用戶或終端或其他地變化而受到影響,那麼就必須把這個進程變成一個守護進程,下麵將完整代碼貼上。
1 /************************************************ 2 * 該常式講解Linux守護進程的編程方法 3 ************************************************/ 4 #include <unistd.h> 5 #include <signal.h> 6 #include <sys/param.h> // NOFILE 7 #include <sys/stat.h> // umask 8 #include <stdio.h> 9 #include <stdlib.h> 10 #include <time.h> 11 #include <assert.h> 12 13 bool initDaemon() 14 { 15 // 屏蔽一些有關控制終端操作的信號 16 // 防止守護進程沒有正常運轉起來時,因控制終端受到干擾退出或掛起 17 assert(signal(SIGINT, SIG_IGN) != SIG_ERR); // 終端中斷 18 assert(signal(SIGHUP, SIG_IGN) != SIG_ERR); // 連接掛斷 19 assert(signal(SIGQUIT, SIG_IGN) != SIG_ERR);// 終端退出 20 assert(signal(SIGPIPE, SIG_IGN) != SIG_ERR);// 向無讀進程的管道寫數據 21 assert(signal(SIGTTOU, SIG_IGN) != SIG_ERR);// 後臺程式嘗試寫操作 22 assert(signal(SIGTTIN, SIG_IGN) != SIG_ERR);// 後臺程式嘗試讀操作 23 assert(signal(SIGTERM, SIG_IGN) != SIG_ERR);// 終止 24 25 // [1] 創建一個子進程,父進程退出 26 int pid = fork(); 27 if (pid) 28 { 29 // 父進程退出 30 exit(0); 31 } 32 else if (pid < 0) 33 { 34 return false; 35 } 36 37 // 子進程繼續運行 38 39 // [2] 在子進程中創建新的會話,setsid有三個作用 40 // a.讓進程擺脫原會話的控制 41 // b.讓進程擺脫原進程組的控制 42 // c.讓進程擺脫原控制終端的控制 43 int ret = setsid(); 44 if (ret < 0) 45 { 46 return false; 47 } 48 49 // [3] 禁止進程重新打開控制終端 50 // 進程已經成為無終端的會話組長,但它可以重新申請打開一個控制終端 51 // 可以通過使進程不再成為會話組長來禁止進程重新打開控制終端 52 pid = fork(); 53 if (pid) 54 { 55 // 結束第一個子進程 56 exit(0); 57 } 58 else if (pid < 0) 59 { 60 return false; 61 } 62 63 // 第二個子進程繼續運行 64 65 // [4] 關閉打開的文件描述符 66 // 進程從創建它的父進程那裡繼承了打開的文件描述符,如果不關閉,將會浪費系統資源, 67 // 造成進程所在的文件系統無法卸下以及引起無法預料的錯誤 68 for (int i = 0; i < NOFILE; ++i) 69 { 70 close(i); 71 } 72 73 // [5] 改變當前工作目錄 74 // 進程活動時,其工作目錄所在的文件系統不能卸下,一般將工作目錄改變到根目錄 75 ret = chdir("/"); 76 if (ret < 0) 77 { 78 return false; 79 } 80 81 // [6] 重新設置文件創建掩碼 82 // 進程從創建它的父進程那裡繼承了文件創建掩碼,它可能修改守護進程所創建的文件的存取位 83 // 所以將文件創建掩碼清除 84 umask(0); 85 86 return true; 87 } 88 89 int main() 90 { 91 // 初始化守護進程 92 bool ret = initDaemon(); 93 if (!ret) 94 { 95 printf("Init daemon failed\n"); 96 return 1; 97 } 98 99 FILE* file = NULL; 100 time_t t = 0; 101 102 // 每隔10秒向test.log報告運行狀態 103 while (true) 104 { 105 sleep(10); 106 file = fopen("./var/test.log", "a+"); 107 if (file != NULL) 108 { 109 t = time(NULL); 110 fprintf(file, "I am here at %s\n", asctime(localtime(&t))); 111 fclose(file); 112 } 113 } 114 115 return 0; 116 }
該例子的github地址:https://github.com/chxuan/samples/blob/master/Daemon/Daemon.cpp