您好,登錄后才能下訂單哦!
這篇文章主要為大家分析了Linux系統守護進程怎么理解的相關知識點,內容詳細易懂,操作細節合理,具有一定參考價值。如果感興趣的話,不妨跟著跟隨小編一起來看看,下面跟著小編一起深入學習“Linux系統守護進程怎么理解”的知識吧。
什么是守護進程?例如淘寶、支付寶等必須7*24小時不停的運行,這就是一個非常典型的守護進程。
1、查看系統中的進程
ps axj1
參數a表示不僅列當前用戶的進程,也列出所有其他用戶的進程, 參數x表示不僅列有控制終端的進程,也列出所無控制終端的進程, 參數j表示列出與作業控制相關的信息。
凡是TPGID一欄寫著-1的都是沒有控制終端的進程,也就是守護進程。在COMMAND一列用[]括起來的 名字表示內核線程,這些線程在內核里創建,沒有用戶空間代碼,因此沒有程序文件名和命令行, 通常采用以k開頭的名字,表示Kernel。init進程我們已經很熟悉了,udevd負責維 護/dev目錄下的設備?文件,acpid負責電源管理,syslogd負責維護/var/log下的日志文件,可以看出,守護進程通 常采用以d結尾的名字,表示Daemon。
2、setsid函數 1>創建守護進程最關鍵的一步是調用setsid函數創建一個新的Session,并成為Session Leader。
#include pid_t setsid(void);12
返回值:該函數調用成功時返回新創建的Session的id(其實也就是當前進程的id),出錯返回-1。
2>需要注意的是,,調用這個函數之前,當前進程不允許是進程組的Leader,否則該函數返回-1。 解決辦法:先fork再調用setsid,fork創建的子進程和父進程在同一個進 程組中,進程組的Leader必然是該組的第一個進程,所以子進程不可能是該組的第一個進程,在子 進程中調用setsid就不會有問題了。
3>成功調用該函數的結果是: \1. 創建一個新的Session,當前進程成為Session Leader,當前進程的id就是Session的id。 \2. 創建一個新的進程組,當前進程成為進程組的Leader,當前進程的id就是進程組的id。 \3. 如果當前進程原本有一個控制終端,則它失去這個控制終端,成為一個沒有控制終端的進程。所謂失去控制終端是指,原來的控制終端仍然是打開的,仍然可以讀寫,但只是一個普通的打開文件而不是控制終端了。
3、創建守護進程的步驟 1>調用umask將文件模式創建屏蔽字設置為0.
umask(0);//umask必須清0,否則創建文件受系統默認權限的影響1
文件權限掩碼是屏蔽掉文件權限中的對應位。由于使用fork()函數新創建的子進程繼承了父進程的文件權限掩碼,這就給該子進程使用文件帶了很多的麻煩(比如父進程中的文件沒有執行文件的權限,然而在子進程中希望執行相應的文件這個時候就會出問題)。因此在子進程中要把文件的權限掩碼設置成為0,即在此時有最大的權限,這樣可以大大增強該守護進程的靈活性。
2>調用fork,父進程退出(exit)。 原因: 1)如果該守護進程是作為一條簡單的shell命令啟動的,那么?父進程終止使得shell認為該命令已經執行完畢。 2)保證子進程不是一個進程組的組長進程。
3>調用setsid創建一個新會話。 setsid會導致: 1)調用進程成為新會話的首進程。 2)調用進程成為一個進程組的組長進程 。 3)調用進程沒有控制終端。(再次fork一次,保證daemon進程,之后不會打開tty設備)
調用setsid的原因: 由于創建守護進程的第一步是調用fork()函數來創建子進程,再將父進程退出。由于在調用了fork()函數的時候,子進程拷貝了父進程的會話期、進程組、控制終端等資源、雖然父進程退出了,但是會話期、進程組、控制終端等并沒有改變,因此,需要用setsid()韓式來時該子進程完全獨立出來,從而擺脫其他進程的控制。
4>將當前工作目錄更改為根目錄。 防止當前目錄有一個目錄被刪除,導致守護進程無效。 使用fork()創建的子進程是繼承了父進程的當前工作目錄,由于在進程運行中,當前目錄所在的文件系統是不能卸載的,這對以后使用會造成很多的麻煩。因此通常的做法是讓“/”作為守護進程的當前目錄,當然也可以指定其他的別的目錄來作為守護進程的工作目錄。
5>關閉不再需要的文件描述符。 同文件權限碼一樣,用fork()函數新建的子進程會從父進程那里繼承一些已經打開了的文件。這些文件被打開的文件可能永遠不會被守護進程讀寫,如果不進行關閉的話將會浪費系統的資源,造成進程所在的文件系統無法卸下以及引起預料的錯誤。
如:關閉標準輸入流、標準輸出流、標準錯誤流。
close(0); close(1); close(2);123
6>其他:忽略SIGCHLD信號。
signal(SIGCHLD,SIG_IGN);1
4、自己創建守護進程:
1 /************************************** 2 *文件說明:mydaemon.c 3 *作者:段曉雪 4 *創建時間:2024年11月20日 星期三 12時26分43秒 5 *開發環境:Kali Linux/g++ v6.3.0 6 ****************************************/ 7 8 #include 9 #include 10 #include 11 #include 12 #include 13 #include 14 15 void mydaemon() 16 { 17 umask(0);//將文件模式創建屏蔽字設為0 18 pid_t pid = fork();//創建子進程 19 if(pid == -1) 20 perror("fork error"); 21 else if(pid == 0)//child 22 { 23 setsid();//創建新會話 24 if(chdir("/")ps axj | grep mydaemon查看精靈進程: 5、調用系統函數daemon創建守護進程 #include int daemon(int nochdir, int noclose);121>daemon函數主要用于希望脫離控制臺,以守護進程的形式在后臺運行的程序。 2>當nochdir為0時,daemon將更改當前進程的目錄為root(“/”)目錄。 3> 當noclose為0時,daemon將進程的STDIN,STDOUT,STDERR都重定向到/dev/null。 /dev/null:linux下的黑洞,寫入的所有數據會直接丟棄。用daemon函數創建守護進程: 1 /************************************** 2 *文件說明:daemon.c 3 *作者:段曉雪 4 *創建時間:2024年11月22日 星期五 06時53分52秒 5 *開發環境:Kali Linux/g++ v6.3.0 6 ****************************************/ 7 8 #include 9 #include 10 11 int main() 12 { 13 daemon(1,1);//創建守護進程 14 while(1); 15 return 0; 16 }12345678910111213141516三、如何殺死守護進程?1> 利用ps axj | grep 守護進程名字找到相應的守護進程,然后用kill -9 進程號將對應進程殺死。 2>利用ps -ef命令查找相應的守護進程,再用kill命令將其殺死。 …… 3>也可創建shell腳本對進程的啟動、關閉、重啟進行自動管理。四、為什么有人創建守護進程會fork兩次?一個daemon函數常見的實現: int daemon(void) { pid_t pid = fork(); //第一次fork if( pid != 0 ) exit(0);//parent //first children if(setsid() == -1) { printf("setsid failed\n"); assert(0); exit(-1); } umask(0); pid = fork(); //第二次fork if( pid != 0) exit(0); //second children chdir ("/"); for (int i = 0; i可以看到上面的代碼里我fork了兩次,雖然說這并不是必須的,但是這的確是對守護進程做出了一些更優化的操作。首先第一次fork:這里第一次fork的作用就是讓shell認為這條命令已經終止,不用掛在終端輸入上;再一個是為了后面的setsid服務,因為調用setsid函數的進程不能是進程組組長(會報錯Operation not permitted),如果不fork子進程,那么此時的父進程是進程組組長,無法調用setsid。所以到這里子進程便成為了一個新會話組的組長。第二次fork:第二次fork是為了避免后期進程誤操作而再次打開終端。因為打開一個控制終端的前提條件是該進程必須為會話組組長,而我們通過第二次fork,確保了第二次fork出來的子進程不會是會話組組長。下面羅列一下控制終端會產生哪些信號。程序中只要處理好這些信號,同樣能達到上面函數實現的目的。//后臺進程讀取/寫入終端輸入產生下面兩個信號,或者控制終端不存在情況讀取和寫入會產生 signal(SIGTTOU, SIG_IGN); signal(SIGTTIN, SIG_IGN);12//按CTRL-C ,CTRL-\ CTRL-Z會向前臺進程組發送下面這些信號 signal(SIGINT, SIG_IGN ); signal(SIGQUIT, SIG_IGN ); signal(SIGTSTP, SIG_IGN );123//終端斷開,會給會話組長或孤兒進程組所有成員發送下面信號 signal(SIGHUP, SIG_IGN );1還有有些信號也可以由終端shell產生,需要關注 signal(SIGCONT, SIG_IGN ); signal(SIGSTOP, SIG_IGN );12上面這些信號,應該有些程序缺省處理(SIG_DFL)本身動作就是忽略(SIG_IGN),不是退出進程。不過按照上面寫也不會造成什么問題。至此關于Linux系統守護進程的具體 內容分享完畢,歡迎大家在評論區留言。以上就是良許教程網為各位朋友分享的Linux系統相關內容。想要了解更多Linux相關知識記得關注公眾號“良許Linux”,或掃描下方二維碼進行關注,更多干貨等著你!
關于“Linux系統守護進程怎么理解”就介紹到這了,更多相關內容可以搜索億速云以前的文章,希望能夠幫助大家答疑解惑,請多多支持億速云網站!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。