溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

Linux系統(tǒng)守護(hù)進(jìn)程怎么理解

發(fā)布時(shí)間:2022-01-26 11:34:36 來源:億速云 閱讀:146 作者:柒染 欄目:開發(fā)技術(shù)

這篇文章主要為大家分析了Linux系統(tǒng)守護(hù)進(jìn)程怎么理解的相關(guān)知識(shí)點(diǎn),內(nèi)容詳細(xì)易懂,操作細(xì)節(jié)合理,具有一定參考價(jià)值。如果感興趣的話,不妨跟著跟隨小編一起來看看,下面跟著小編一起深入學(xué)習(xí)“Linux系統(tǒng)守護(hù)進(jìn)程怎么理解”的知識(shí)吧。

什么是守護(hù)進(jìn)程?例如淘寶、支付寶等必須7*24小時(shí)不停的運(yùn)行,這就是一個(gè)非常典型的守護(hù)進(jìn)程。

1、查看系統(tǒng)中的進(jìn)程

 ps axj1

參數(shù)a表示不僅列當(dāng)前用戶的進(jìn)程,也列出所有其他用戶的進(jìn)程, 參數(shù)x表示不僅列有控制終端的進(jìn)程,也列出所無控制終端的進(jìn)程, 參數(shù)j表示列出與作業(yè)控制相關(guān)的信息。

Linux系統(tǒng)守護(hù)進(jìn)程怎么理解 凡是TPGID一欄寫著-1的都是沒有控制終端的進(jìn)程,也就是守護(hù)進(jìn)程。在COMMAND一列用[]括起來的 名字表示內(nèi)核線程,這些線程在內(nèi)核里創(chuàng)建,沒有用戶空間代碼,因此沒有程序文件名和命令行, 通常采用以k開頭的名字,表示Kernel。init進(jìn)程我們已經(jīng)很熟悉了,udevd負(fù)責(zé)維 護(hù)/dev目錄下的設(shè)備?文件,acpid負(fù)責(zé)電源管理,syslogd負(fù)責(zé)維護(hù)/var/log下的日志文件,可以看出,守護(hù)進(jìn)程通 常采用以d結(jié)尾的名字,表示Daemon。

2、setsid函數(shù) 1>創(chuàng)建守護(hù)進(jìn)程最關(guān)鍵的一步是調(diào)用setsid函數(shù)創(chuàng)建一個(gè)新的Session,并成為Session Leader。

 #include pid_t setsid(void);12

返回值:該函數(shù)調(diào)用成功時(shí)返回新創(chuàng)建的Session的id(其實(shí)也就是當(dāng)前進(jìn)程的id),出錯(cuò)返回-1。

2>需要注意的是,,調(diào)用這個(gè)函數(shù)之前,當(dāng)前進(jìn)程不允許是進(jìn)程組的Leader,否則該函數(shù)返回-1。 解決辦法:先fork再調(diào)用setsid,fork創(chuàng)建的子進(jìn)程和父進(jìn)程在同一個(gè)進(jìn) 程組中,進(jìn)程組的Leader必然是該組的第一個(gè)進(jìn)程,所以子進(jìn)程不可能是該組的第一個(gè)進(jìn)程,在子 進(jìn)程中調(diào)用setsid就不會(huì)有問題了。

3>成功調(diào)用該函數(shù)的結(jié)果是: \1. 創(chuàng)建一個(gè)新的Session,當(dāng)前進(jìn)程成為Session Leader,當(dāng)前進(jìn)程的id就是Session的id。 \2. 創(chuàng)建一個(gè)新的進(jìn)程組,當(dāng)前進(jìn)程成為進(jìn)程組的Leader,當(dāng)前進(jìn)程的id就是進(jìn)程組的id。 \3. 如果當(dāng)前進(jìn)程原本有一個(gè)控制終端,則它失去這個(gè)控制終端,成為一個(gè)沒有控制終端的進(jìn)程。所謂失去控制終端是指,原來的控制終端仍然是打開的,仍然可以讀寫,但只是一個(gè)普通的打開文件而不是控制終端了。

3、創(chuàng)建守護(hù)進(jìn)程的步驟 1>調(diào)用umask將文件模式創(chuàng)建屏蔽字設(shè)置為0.

 umask(0);//umask必須清0,否則創(chuàng)建文件受系統(tǒng)默認(rèn)權(quán)限的影響1

文件權(quán)限掩碼是屏蔽掉文件權(quán)限中的對(duì)應(yīng)位。由于使用fork()函數(shù)新創(chuàng)建的子進(jìn)程繼承了父進(jìn)程的文件權(quán)限掩碼,這就給該子進(jìn)程使用文件帶了很多的麻煩(比如父進(jìn)程中的文件沒有執(zhí)行文件的權(quán)限,然而在子進(jìn)程中希望執(zhí)行相應(yīng)的文件這個(gè)時(shí)候就會(huì)出問題)。因此在子進(jìn)程中要把文件的權(quán)限掩碼設(shè)置成為0,即在此時(shí)有最大的權(quán)限,這樣可以大大增強(qiáng)該守護(hù)進(jìn)程的靈活性。

2>調(diào)用fork,父進(jìn)程退出(exit)。 原因: 1)如果該守護(hù)進(jìn)程是作為一條簡(jiǎn)單的shell命令啟動(dòng)的,那么?父進(jìn)程終止使得shell認(rèn)為該命令已經(jīng)執(zhí)行完畢。 2)保證子進(jìn)程不是一個(gè)進(jìn)程組的組長(zhǎng)進(jìn)程。

3>調(diào)用setsid創(chuàng)建一個(gè)新會(huì)話。 setsid會(huì)導(dǎo)致: 1)調(diào)用進(jìn)程成為新會(huì)話的首進(jìn)程。 2)調(diào)用進(jìn)程成為一個(gè)進(jìn)程組的組長(zhǎng)進(jìn)程 。 3)調(diào)用進(jìn)程沒有控制終端。(再次fork一次,保證daemon進(jìn)程,之后不會(huì)打開tty設(shè)備)

調(diào)用setsid的原因: 由于創(chuàng)建守護(hù)進(jìn)程的第一步是調(diào)用fork()函數(shù)來創(chuàng)建子進(jìn)程,再將父進(jìn)程退出。由于在調(diào)用了fork()函數(shù)的時(shí)候,子進(jìn)程拷貝了父進(jìn)程的會(huì)話期、進(jìn)程組、控制終端等資源、雖然父進(jìn)程退出了,但是會(huì)話期、進(jìn)程組、控制終端等并沒有改變,因此,需要用setsid()韓式來時(shí)該子進(jìn)程完全獨(dú)立出來,從而擺脫其他進(jìn)程的控制。

4>將當(dāng)前工作目錄更改為根目錄。 防止當(dāng)前目錄有一個(gè)目錄被刪除,導(dǎo)致守護(hù)進(jìn)程無效。 使用fork()創(chuàng)建的子進(jìn)程是繼承了父進(jìn)程的當(dāng)前工作目錄,由于在進(jìn)程運(yùn)行中,當(dāng)前目錄所在的文件系統(tǒng)是不能卸載的,這對(duì)以后使用會(huì)造成很多的麻煩。因此通常的做法是讓“/”作為守護(hù)進(jìn)程的當(dāng)前目錄,當(dāng)然也可以指定其他的別的目錄來作為守護(hù)進(jìn)程的工作目錄。

5>關(guān)閉不再需要的文件描述符。 同文件權(quán)限碼一樣,用fork()函數(shù)新建的子進(jìn)程會(huì)從父進(jìn)程那里繼承一些已經(jīng)打開了的文件。這些文件被打開的文件可能永遠(yuǎn)不會(huì)被守護(hù)進(jìn)程讀寫,如果不進(jìn)行關(guān)閉的話將會(huì)浪費(fèi)系統(tǒng)的資源,造成進(jìn)程所在的文件系統(tǒng)無法卸下以及引起預(yù)料的錯(cuò)誤。

如:關(guān)閉標(biāo)準(zhǔn)輸入流、標(biāo)準(zhǔn)輸出流、標(biāo)準(zhǔn)錯(cuò)誤流。

 close(0);
 close(1);
 close(2);123

6>其他:忽略SIGCHLD信號(hào)。

 signal(SIGCHLD,SIG_IGN);1

4、自己創(chuàng)建守護(hù)進(jìn)程:

   1 /**************************************
   2 *文件說明:mydaemon.c
   3 *作者:段曉雪
   4 *創(chuàng)建時(shí)間:2024年11月20日 星期三 12時(shí)26分43秒
   5 *開發(fā)環(huán)境: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);//將文件模式創(chuàng)建屏蔽字設(shè)為0
  18     pid_t pid = fork();//創(chuàng)建子進(jìn)程
  19     if(pid == -1)
  20         perror("fork error");
  21     else if(pid == 0)//child
  22     {
  23         setsid();//創(chuàng)建新會(huì)話
  24         if(chdir("/")ps axj | grep mydaemon查看精靈進(jìn)程: 5、調(diào)用系統(tǒng)函數(shù)daemon創(chuàng)建守護(hù)進(jìn)程 #include int daemon(int nochdir, int noclose);121>daemon函數(shù)主要用于希望脫離控制臺(tái),以守護(hù)進(jìn)程的形式在后臺(tái)運(yùn)行的程序。 2>當(dāng)nochdir為0時(shí),daemon將更改當(dāng)前進(jìn)程的目錄為root(“/”)目錄。 3> 當(dāng)noclose為0時(shí),daemon將進(jìn)程的STDIN,STDOUT,STDERR都重定向到/dev/null。 /dev/null:linux下的黑洞,寫入的所有數(shù)據(jù)會(huì)直接丟棄。用daemon函數(shù)創(chuàng)建守護(hù)進(jìn)程:   1 /**************************************
   2 *文件說明:daemon.c
   3 *作者:段曉雪
   4 *創(chuàng)建時(shí)間:2024年11月22日 星期五 06時(shí)53分52秒
   5 *開發(fā)環(huán)境:Kali Linux/g++ v6.3.0
   6 ****************************************/
   7
   8 #include   9 #include  10
  11 int main()
  12 {
  13     daemon(1,1);//創(chuàng)建守護(hù)進(jìn)程
  14     while(1);
  15     return 0;
  16 }12345678910111213141516三、如何殺死守護(hù)進(jìn)程?1> 利用ps axj | grep 守護(hù)進(jìn)程名字找到相應(yīng)的守護(hù)進(jìn)程,然后用kill -9 進(jìn)程號(hào)將對(duì)應(yīng)進(jìn)程殺死。 2>利用ps -ef命令查找相應(yīng)的守護(hù)進(jìn)程,再用kill命令將其殺死。  …… 3>也可創(chuàng)建shell腳本對(duì)進(jìn)程的啟動(dòng)、關(guān)閉、重啟進(jìn)行自動(dòng)管理。四、為什么有人創(chuàng)建守護(hù)進(jìn)程會(huì)fork兩次?一個(gè)daemon函數(shù)常見的實(shí)現(xiàn): 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了兩次,雖然說這并不是必須的,但是這的確是對(duì)守護(hù)進(jìn)程做出了一些更優(yōu)化的操作。首先第一次fork:這里第一次fork的作用就是讓shell認(rèn)為這條命令已經(jīng)終止,不用掛在終端輸入上;再一個(gè)是為了后面的setsid服務(wù),因?yàn)檎{(diào)用setsid函數(shù)的進(jìn)程不能是進(jìn)程組組長(zhǎng)(會(huì)報(bào)錯(cuò)Operation not permitted),如果不fork子進(jìn)程,那么此時(shí)的父進(jìn)程是進(jìn)程組組長(zhǎng),無法調(diào)用setsid。所以到這里子進(jìn)程便成為了一個(gè)新會(huì)話組的組長(zhǎng)。第二次fork:第二次fork是為了避免后期進(jìn)程誤操作而再次打開終端。因?yàn)榇蜷_一個(gè)控制終端的前提條件是該進(jìn)程必須為會(huì)話組組長(zhǎng),而我們通過第二次fork,確保了第二次fork出來的子進(jìn)程不會(huì)是會(huì)話組組長(zhǎng)。下面羅列一下控制終端會(huì)產(chǎn)生哪些信號(hào)。程序中只要處理好這些信號(hào),同樣能達(dá)到上面函數(shù)實(shí)現(xiàn)的目的。//后臺(tái)進(jìn)程讀取/寫入終端輸入產(chǎn)生下面兩個(gè)信號(hào),或者控制終端不存在情況讀取和寫入會(huì)產(chǎn)生   signal(SIGTTOU, SIG_IGN);
    signal(SIGTTIN, SIG_IGN);12//按CTRL-C ,CTRL-\ CTRL-Z會(huì)向前臺(tái)進(jìn)程組發(fā)送下面這些信號(hào)    signal(SIGINT,  SIG_IGN );
    signal(SIGQUIT, SIG_IGN );
    signal(SIGTSTP, SIG_IGN );123//終端斷開,會(huì)給會(huì)話組長(zhǎng)或孤兒進(jìn)程組所有成員發(fā)送下面信號(hào)    signal(SIGHUP,  SIG_IGN );1還有有些信號(hào)也可以由終端shell產(chǎn)生,需要關(guān)注 signal(SIGCONT, SIG_IGN );
 signal(SIGSTOP, SIG_IGN );12上面這些信號(hào),應(yīng)該有些程序缺省處理(SIG_DFL)本身動(dòng)作就是忽略(SIG_IGN),不是退出進(jìn)程。不過按照上面寫也不會(huì)造成什么問題。至此關(guān)于Linux系統(tǒng)守護(hù)進(jìn)程的具體 內(nèi)容分享完畢,歡迎大家在評(píng)論區(qū)留言。以上就是良許教程網(wǎng)為各位朋友分享的Linux系統(tǒng)相關(guān)內(nèi)容。想要了解更多Linux相關(guān)知識(shí)記得關(guān)注公眾號(hào)“良許Linux”,或掃描下方二維碼進(jìn)行關(guān)注,更多干貨等著你!

關(guān)于“Linux系統(tǒng)守護(hù)進(jìn)程怎么理解”就介紹到這了,更多相關(guān)內(nèi)容可以搜索億速云以前的文章,希望能夠幫助大家答疑解惑,請(qǐng)多多支持億速云網(wǎng)站!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI