- Linux的⼤多數服務器(因爲一般服務器都需要 7*24 小時不間斷運行)就是⽤守護進程實現的。⽐如,ftp服務器,ssh服務器,Web服務器httpd等。
- 守護進程也完成許多系統任務。⽐如,作業規劃進程crond等。
- 參數a表⽰不僅列當前⽤戶的進程,也列出所有其他⽤ 戶的進程
- 參數x表⽰不僅列有控制終端的進程,也列出所有⽆控制終端的進程
- 參數j表⽰列出與 作業控制相關的信息。
- 凡是TPGID⼀欄寫着-1的都是沒有控制終端的進程,也就是守護進程。
- 在COMMAND⼀列⽤[]括起來的名字表⽰內核線程,這些線程在內核⾥創建,沒有⽤戶空間代碼,因此 沒有程序⽂件名和命令⾏, 通常採⽤以k開頭的名字,表⽰Kernel。
- SysV Daemons (man手冊上分爲15步,比較麻煩)
- New-Style Daemons (新風格的守護進程,man手冊上分爲10步,也比較複雜)
- 調用fork創建子進程,父進程終止,讓子進程在後臺繼續執行.
- 子進程調用setsid創建一個新的會話,並失去控制終端,調用setsid()使子進程成爲新的會話組組長和新的進程組組長,同時失去控制終端.
- 忽略 SIGHUP 信號,當關閉終端的時候,會話就會結束,會話結束進程組就會結束,進程組結束進程就會結束,SIGHUP信號就是負責向其他進程組發送該信號,造成其他進程終止.
- 忽略 SIGCHLD 信號,避免後面創建的子進程產生殭屍進程.
- 再次調用fork創建子子進程,子進程終止,子子進程繼續執行,由於子子進程不在是會話組的組長,從而禁止進程重新打開終端(這一步不是必須的).
- 吧當前的工作目錄改成根目錄,一般將工作目錄改到根目錄,這樣進程的啓動目錄也可以被卸掉.
- 關閉打開的文件描述符,打開一個空設備,並複製到標準輸出和標準錯誤上.避免調用一些庫函數依然向屏幕輸出信息.
- 重設文件創建掩碼清除從父進程那裏繼承來的文件掩碼,設爲0
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <fcntl.h>
#include <sys/stat.h>
void MyDaemon()
{
// 1.創建子進程,子進程繼續執行,父進程終止
pid_t pid = fork();
if(pid < 0)
{
perror("fork");
return;
}
if(pid > 0)
{
exit(0);
}
// 2.子進程調用 setsid
setsid();
// 3.忽略 SIGHUP信號
signal(SIGHUP,SIG_IGN);
// 4.忽略 SIGCHLD信號
signal(SIGCHLD,SIG_IGN);
// 5.修改工作目錄爲根目錄
chdir("/");
// 6.重定向文件描述符
int fd = open("/dev/null",O_RDWR); //類似於垃圾桶的文件,寫入的數據直接丟棄
if(fd < 0)
{
perror("fd");
exit(1);
}
dup2(fd,1);
dup2(fd,2);
// 7.修改 umask
umask(0);
}
int main()
{
MyDaemon();
while(1)
{
sleep(1);
}
return 0;
}
上面的步驟太太太繁瑣了,C語言爲我們提供了一個daemon函數
#include <stdio.h>
#include <unistd.h>
int main()
{
daemon(0,0);
while(1)
{
sleep(1);
}
return 0;
}