守護進程簡介
守護進程(Daemon Process),也就是通常說的 Daemon 進程(精靈進程),是 Linux 中的后台服務進程。它是一個生存期較長的進程,通常獨立於控制終端並且周期性地執行某種任務或等待處理某些發生的事件。一般采用以 d 結尾的名字。
◼ 守護進程具備下列特征:
1.生命周期很長,守護進程會在系統啟動的時候被創建並一直運行直至系統被關閉。
2.它在后台運行並且不擁有控制終端。沒有控制終端確保了內核永遠不會為守護進程自動生成任何控制信號以及終端相關的信號(如 SIGINT、SIGQUIT)。
創建步驟
(1)執行一個 fork(),之后父進程退出,子進程繼續執行。
(2)子進程調用 setsid() 開啟一個新會話。
(3)清除進程的 umask 以確保當守護進程創建文件和目錄時擁有所需的權限。
(4)修改進程的當前工作目錄,通常會改為根目錄(/)。
(5)關閉守護進程從其父進程繼承而來的所有打開着的文件描述符。
(6)在關閉了文件描述符0、1、2之后,守護進程通常會打開/dev/null 並使用dup2() 使所有這些描述符指向這個設備。
(7)核心業務邏輯
問題
為什么(1)(2)步驟,使用子進程是為了防止進程組id沖突,新建會話不會和控制終端關聯。
為什么需要(3),並不是必須的,步驟(3)也就是設置掩碼。
為什么需要(4),因為守護進程的特點1,防止該目錄被刪除。
為什么(5),與父進程的終端完全脫離。
(6)中的/dev/null,這個設備一般碰到什么就丟棄。
代碼案例
/* 寫一個守護進程,每隔2s獲取一下系統時間,將這個時間寫入到磁盤文件中。 */ #include <stdio.h> #include <sys/stat.h> #include <sys/types.h> #include <unistd.h> #include <fcntl.h> #include <sys/time.h> #include <signal.h> #include <time.h> #include <stdlib.h> #include <string.h> void work(int num) { // 捕捉到信號之后,獲取系統時間,寫入磁盤文件 time_t tm = time(NULL); struct tm * loc = localtime(&tm); char * str = asctime(loc); int fd = open("time.txt", O_RDWR | O_CREAT | O_APPEND, 0664); write(fd ,str, strlen(str)); close(fd); } int main() { // 1.創建子進程,退出父進程 pid_t pid = fork(); if(pid > 0) { exit(0); } // 2.將子進程重新創建一個會話 setsid(); // 3.設置掩碼 umask(022); // 4.更改工作目錄 chdir("/home/nowcoder/"); // 5. 關閉、重定向文件描述符 int fd = open("/dev/null", O_RDWR); dup2(fd, STDIN_FILENO); dup2(fd, STDOUT_FILENO); dup2(fd, STDERR_FILENO); // 6.業務邏輯 // 捕捉定時信號 struct sigaction act; act.sa_flags = 0; act.sa_handler = work; sigemptyset(&act.sa_mask); sigaction(SIGALRM, &act, NULL); struct itimerval val; val.it_value.tv_sec = 2; val.it_value.tv_usec = 0; val.it_interval.tv_sec = 2; val.it_interval.tv_usec = 0; // 創建定時器 setitimer(ITIMER_REAL, &val, NULL); // 不讓進程結束 while(1) { sleep(10); } return 0; }