久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

Linux的精靈(daemon)進(jìn)程和僵尸(zombie)進(jìn)程 (zz)

 紫火神兵 2012-09-24

轉(zhuǎn)自:http://www./blog/archives/599

有些日子沒(méi)有跟工程師一起工作了,。昨天星期五,,我回到川崎的辦公室和同事一起結(jié)果一個(gè)客戶反饋的問(wèn)題。這個(gè)工作卻又讓我懷念以前作研發(fā)的那些時(shí)光,。突然覺(jué)得有些東西還是不應(yīng)該被忘記,,就寫(xiě)在這里作筆記了。

守護(hù)進(jìn)程(Daemon)

守護(hù)進(jìn)程——我情愿把他叫做精靈進(jìn)程——是多種操作系統(tǒng)中的一種常駐程序,。常駐的意思是,在系統(tǒng)運(yùn)行期間,,這些進(jìn)程都一直存在,。很明顯,,大多數(shù)服務(wù)器程序都是精靈進(jìn)程,。在這里我要說(shuō)一說(shuō)自己知道關(guān)于精靈進(jìn)程的方法,,和與此相關(guān)的一些技巧。

如何產(chǎn)生一個(gè)精靈進(jìn)程,?

Linux系統(tǒng)啟動(dòng)以后,,它通常啟動(dòng)的第一個(gè)進(jìn)程就是init進(jìn)程。init進(jìn)程的進(jìn)程ID是1,,并且它會(huì)一直在系統(tǒng)運(yùn)行期間存續(xù),。同 時(shí),,Linux對(duì)進(jìn)程的管理策略有兩個(gè)比較特殊的地方,,其中之一就是,,當(dāng)一個(gè)進(jìn)程的父進(jìn)程結(jié)束,它的子進(jìn)程如果還繼續(xù)運(yùn)行,,那么,,子進(jìn)程就會(huì)被init進(jìn) 程收養(yǎng),。也算就是說(shuō),,Linux對(duì)進(jìn)程的管理策略,,其實(shí)是一直在努力維護(hù)一棵樹(shù),。利用這一點(diǎn),就可產(chǎn)生伴隨init一直存在的精靈進(jìn)程,。代碼例子如下:

/* file: daemon_sample.c */
#include
#include
#include
#include

int main ()
{
pid_t pid,sid;

/* fork to leave parent */
pid = fork ();
if (pid < 0) {
printf ("failed to fork!\n");
exit (EXIT_FAILURE);
} else if (pid > 0) {
/* parent process go to exit */
exit (EXIT_SUCCESS);
}

/* child process */
chdir("/");
sid = setsid ();
if (sid < 0) {
printf ("Failed to set session id.\n");
exit (EXIT_FAILURE);
}
/* ensure all files created by itself are accessible */
umask (0);

printf ("Daemon adopted by parent %d\n", getppid());

/* daemon loop */
while (1) {
sleep (1);
}
}

產(chǎn)生一個(gè)精靈進(jìn)程的過(guò)程需要有一下幾步:

  1. 從啟動(dòng)該程序的進(jìn)程中fork出來(lái)一個(gè)子進(jìn)程,;如果子進(jìn)程產(chǎn)生成功,那么就將父進(jìn)程結(jié)束
  2. 子進(jìn)程需要作一些處理來(lái)保證自己作為精靈的地位,;改變當(dāng)前工作目錄,;利用setsid系統(tǒng)調(diào)用重新設(shè)置一個(gè)session;利用umask系統(tǒng)調(diào)用消除父進(jìn)程對(duì)于文件控制的影響,,從而保證精靈可以正確的訪問(wèn)它自己生成的各種文件——其中比較重要的是IPC
  3. 子進(jìn)程需要啟動(dòng)一個(gè)自身處理的循環(huán)

這是一個(gè)非常簡(jiǎn)單的例子,,通常情況下,,子進(jìn)程還需要關(guān)閉標(biāo)準(zhǔn)輸入輸出等等工作。與此相關(guān)的詳細(xì)討論可以查看
http://www./skripten/unix/linux-daemon-howto.html
這里有一個(gè)可以下載到本地的PDF版本
http://www./url?sa=t&source=web&ct=res&cd=2&url=http%3A%2F%2Fwww.cs.aau.dk%2F~adavid%2Fteaching%2FMTP-05%2Fexercises%2F10%2FLinux-Daemon_Writting.pdf&ei=W7pFSreDHoTW7APC0_Eh&usg=AFQjCNHyZnXmdKL8ebxJ8UXQsYeGHiqRwQ&sig2=7Of2PvUnmTm8xqZifI-aAw

怎樣判斷一個(gè)進(jìn)程是否是精靈進(jìn)程,?

恩,,奇怪的地方就在與此了,。如果用如下命令編譯上面的簡(jiǎn)短程序,,你會(huì)發(fā)現(xiàn)一處不太符合想象的地方,。

$ gcc -o daemon_sample daemon_sample.c

在終端窗口中運(yùn)行這個(gè)程序,然后我們作一些觀察,。

$ ./daemon_sample

按照上面我敘述過(guò)的內(nèi)容,,這個(gè)程序的將被init進(jìn)程收養(yǎng),。那么,理所當(dāng)然的它的父進(jìn)程ID應(yīng)該是“1”,。然而,,這個(gè)程序運(yùn)行時(shí)卻拋出了這樣一句話。

Daemon adopted by parent 29914

這里的29914是通過(guò)getppid()取得的,難道有什么不對(duì)頭,?為了確認(rèn)情況,,再用ps查看一下究竟發(fā)生了什么事情。

$ ps -e -o pid,ppid,cmd,tty | grep daemon_sample
29915 1 ./daemon_sample ?

利用ps命令的-o選項(xiàng),,可以查看進(jìn)程的pid,ppid,命令行和運(yùn)行終端的信息,。顯而易見(jiàn),這個(gè)精靈進(jìn)程事實(shí)上的ppid是“1”,。那么,,為什么 getppid()不能返回正確的值?難道這里是個(gè)BUG,?就目前Linux內(nèi)核的狀況來(lái)說(shuō),,這不是一個(gè)BUG,,查看getppid的手冊(cè)頁(yè)可以看 到,getppid并不保證能夠取得一個(gè)進(jìn)程被收養(yǎng)以后的父進(jìn)程ID,?;蛘哂信d趣的xdjm可以嘗試一下將這個(gè)功能升級(jí)一下:)。

換句話說(shuō),,不能使用getppid來(lái)判斷一個(gè)進(jìn)程時(shí)候是精靈進(jìn)程,。那么,應(yīng)該怎樣判斷,?

再看上面ps的輸出結(jié)果,,你會(huì)發(fā)現(xiàn)這個(gè)進(jìn)程的tty域是一個(gè)問(wèn)號(hào)。這表明,,該進(jìn)程并沒(méi)有被attach到任何終端設(shè)備上去,。事實(shí)上所有的精靈進(jìn)程都有這個(gè)特性。利用ps做一個(gè)驗(yàn)證吧,。

$ ps -e -o pid,ppid,cmd,tty | grep daemon
898 1 /sbin/udevd --daemon ?
2464 1 /bin/dbus-daemon --system ?
3305 1 avahi-daemon: running [capr ?
3829 1 //bin/dbus-daemon --fork -- ?
29915 1 ./daemon_sample ?
31584 29871 grep --color=auto daemon pts/1

這里有ps命令的結(jié)果,,它被attach到偽終端pts/1。所以,,可以利用這個(gè)特性來(lái)判斷一個(gè)進(jìn)程是否是精靈進(jìn)程,。

if ((devtty = open ("/dev/tty", O_RDWD)) < 0) {
printf ("This is a daemon\n");
} else {
printf ("This is not a daemon\n");
}

在UNIX論壇上有一個(gè)關(guān)于這個(gè)話題的舊帖子,地址如下:
http://www./high-level-programming/72479-how-find-if-process-daemon.html
精靈進(jìn)程大致就是這樣,。

僵尸進(jìn)程

僵尸進(jìn)程其實(shí)是個(gè)錯(cuò)誤,。

這個(gè)錯(cuò)誤產(chǎn)生的原因在于,子進(jìn)程已經(jīng)結(jié)束,,但是父進(jìn)程卻沒(méi)有對(duì)它進(jìn)行清理,。僵尸進(jìn)程會(huì)被init收編,,并且init會(huì)料理這些僵尸的“善后事宜”。我們可以寫(xiě)一個(gè)很蹩腳的程序來(lái)產(chǎn)生一個(gè)貨真價(jià)實(shí)的僵尸進(jìn)程,。僵尸來(lái)了,!

/* file: zombie.c */
#include
#include
#include

int main ()
{
pid_t child_pid;

/* Create a child process. */
child_pid = fork ();
if (child_pid > 0) {
/* This is the parent process. Sleep for a minitue. */
sleep (60);
} else {
/* This is the child process. Exit immediately. */
exit (EXIT_SUCCESS);
}
return 0;
}

編譯并運(yùn)行這個(gè)程序,在程序運(yùn)行期間,,利用ps查看它的狀態(tài),,你會(huì)得到下面的結(jié)果:

$ ps -e -o pid,stat,cmd | grep zombie
4302 S+ ./zombie
4303 Z+ [zombie]

你會(huì)發(fā)現(xiàn)進(jìn)程4302——也就是僵尸的父進(jìn)程——還沒(méi)有結(jié)束,而進(jìn)程4303進(jìn)程的狀態(tài)已經(jīng)變成了“Z”,。這也就意味這該程序產(chǎn)生的子進(jìn)程已經(jīng)變成了僵尸,。

在一般的桌面系統(tǒng)上,即使產(chǎn)生僵尸進(jìn)程也不是什么大不了的事情,,因?yàn)?,系統(tǒng)資源并不緊張的情況下,僵尸最終會(huì)被init清理,。但是,,在高負(fù)載的服務(wù) 器或者資源非常有限的嵌入式系統(tǒng)中如果大量出現(xiàn)僵尸,那會(huì)是個(gè)一個(gè)麻煩,。所以,,避免產(chǎn)生僵尸進(jìn)程的方法就是在父進(jìn)程中正確的處理wait和SIGCHLD 信號(hào),具體做法google一下可以出很多結(jié)果,,這里就不再累述了,。

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,,不代表本站觀點(diǎn),。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,,謹(jǐn)防詐騙,。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào),。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多