您好,登錄后才能下訂單哦!
這篇文章主要為大家分析了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)的信息。
凡是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)站!
免責(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)容。