?? 13.htm
字號(hào):
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<meta name="GENERATOR" content="Microsoft FrontPage 3.0">
<title>C:\WINDOWS\Desktop\UnixProg\7.htm</title>
</head>
<body>
<font SIZE="2">
<h1 align="center">第十三章 精靈進(jìn)程 </h1>
<p>13.1 介紹 </p>
<p>精靈(Daemons)是生存期長(zhǎng)的一種進(jìn)程。它們常常在系統(tǒng)引導(dǎo)裝入時(shí)啟動(dòng),在系
</p>
<p>統(tǒng)關(guān)閉(shutdown)時(shí)終止。因?yàn)樗鼈儧]有控制終端,所以我們說它們是在后臺(tái)運(yùn)
</p>
<p>行的。UNIX系統(tǒng)有很多精靈進(jìn)程,它們執(zhí)行日常事物活動(dòng)。 </p>
<p>本章說明精靈的進(jìn)程結(jié)構(gòu),以及如何編寫精靈進(jìn)程程序,因?yàn)榫`沒有控制終端,
</p>
<p>我們需要了解在有關(guān)事物出問題時(shí),精靈進(jìn)程如何報(bào)告出錯(cuò)情況。
</p>
<p>13.2 精靈進(jìn)程的特征 </p>
<p>讓我們先來察看一些常用的系統(tǒng)精靈進(jìn)程,以及它們?cè)鯓雍偷诰耪轮兴鶖⑹龅母拍?
</p>
<p>:進(jìn)程組、控制終端和對(duì)話期相關(guān)聯(lián)。ps(1)命令打印系統(tǒng)中各個(gè)進(jìn)程的狀態(tài)。該
</p>
<p>命令有多個(gè)選擇項(xiàng),有關(guān)細(xì)節(jié)請(qǐng)參考系統(tǒng)手冊(cè)。為了察看本節(jié)討論中所需的信息,
</p>
<p>在4.3+BSD或SUN OS 系統(tǒng)下執(zhí)行: </p>
<p>ps -axj </p>
<p>選擇項(xiàng)-a顯示由其他用戶(others)所擁有的進(jìn)程的狀態(tài);-x顯示沒有控制終端的
</p>
<p>進(jìn)程的狀態(tài)。-j顯示與作業(yè)有關(guān)的信息:對(duì)話期ID、進(jìn)程組ID、控制終端以及終端
</p>
<p>進(jìn)程組ID。在SVR4之下,與此相類似的命令是ps -efjc。(在某些符合"美國(guó)國(guó)防
</p>
<p>部安全性準(zhǔn)則"要求的UNIX系統(tǒng)中,只能使用ps
查看自己所擁有的進(jìn)程。)ps的輸 </p>
<p>出大致是: </p>
<p>PPID PID PGID SID TT TPGID UID COMMAND </p>
<p>0 0 0 0 ? -1 0 </p>
<p>wapper </p>
<p>0 1 0 0 ? -1 0 </p>
<p>sbin/init - </p>
<p>0 2 0 0 ? -1 0 </p>
<p>agedaemon </p>
<p>1 80 80 80 ? -1 0 </p>
<p>yslogd </p>
<p>1 88 88 88 ? -1 0 </p>
<p>usr/lib/sendmail -bd -qlh </p>
<p>1 105 37 37 ? -1 0 </p>
<p>pdate </p>
<p>1 108 108 108 ? -1 0 </p>
<p>ron </p>
<p>1 114 114 114 ? -1 0 </p>
<p>netd </p>
<p>1 117 117 117 ? -1 0 </p>
<p>usr/lib/lpd </p>
<p>其中,已移去了一些我們并無(wú)興趣的列,例如累計(jì)CPU時(shí)間。按照順序,各列標(biāo)題
</p>
<p>的意義是:父進(jìn)程ID、進(jìn)程ID、進(jìn)程組ID、終端名稱、終端進(jìn)程組ID(與該控制終
</p>
<p>端相關(guān)的前臺(tái)進(jìn)程組)、用戶ID以及實(shí)際命令字符串。 </p>
<p>這些ps命令在支持對(duì)話期ID的系統(tǒng)(SUN OS)上運(yùn)行,我們?cè)?.5節(jié)的sets
</p>
<p>id函數(shù)中提及對(duì)話期ID。它是對(duì)話期首進(jìn)程的進(jìn)程ID。但是,4.3+BSD系統(tǒng)將打印
</p>
<p>與本進(jìn)程所屬進(jìn)程組對(duì)應(yīng)的session結(jié)構(gòu)的地址(見9.11) </p>
<p>進(jìn)程0、1以及2是8.2節(jié)中所述的進(jìn)程。這些進(jìn)程非常特殊,存在于系統(tǒng)的整個(gè)生命
</p>
<p>期中。它們沒有父進(jìn)程ID,沒有組進(jìn)程ID,也沒有對(duì)話期ID。syslogd精靈進(jìn)程可
</p>
<p>用于任何為操作人員記錄系統(tǒng)消息的程序。可以在一臺(tái)實(shí)際的控制臺(tái)上打印這些消
</p>
<p>息,也可將它們寫到一個(gè)文件中(在13.4.2中將對(duì)syslog設(shè)施進(jìn)行說明)。sendm
</p>
<p>ail是標(biāo)準(zhǔn)郵遞精靈進(jìn)程。update程序定期將核心緩存中的內(nèi)容寫到硬盤上(通常
</p>
<p>是每隔30秒)。為了做到這一點(diǎn),該程序每隔30秒調(diào)用sync(2)函數(shù)一次(在4.
</p>
<p>24節(jié)中已對(duì)sync進(jìn)行了說明)。cron精靈進(jìn)程在指定的日期和時(shí)間執(zhí)行指定的命令
</p>
<p>。許多系統(tǒng)管理任務(wù)是由cron定期地使相關(guān)程序執(zhí)行而得以實(shí)現(xiàn)的。我們已在9.3
</p>
<p>節(jié)中提到inetd精靈進(jìn)程。它監(jiān)聽系統(tǒng)的網(wǎng)絡(luò)界面,以輸入對(duì)各種網(wǎng)絡(luò)服務(wù)器的請(qǐng)
</p>
<p>求。最后一個(gè)精靈進(jìn)程,lpd,處理對(duì)系統(tǒng)提出的各個(gè)打印請(qǐng)求。 </p>
<p>注意,所有精靈進(jìn)程都以超級(jí)用戶(用戶ID為0)的優(yōu)先權(quán)運(yùn)行。沒有一個(gè)精靈進(jìn)
</p>
<p>程具有控制終端-終端名稱設(shè)置為問號(hào)(?)、終端前臺(tái)進(jìn)程組ID設(shè)置為-1。缺少
</p>
<p>控制終端可能是精靈進(jìn)程調(diào)用了setsid的結(jié)果。除update以外的所有精靈進(jìn)程都是
</p>
<p>進(jìn)程組的首進(jìn)程,對(duì)話期的首進(jìn)程,而且是這些進(jìn)程組和對(duì)話期中的唯一進(jìn)程。u
</p>
<p>pdate是它所在進(jìn)程組(37)和對(duì)話期(37)中的唯一進(jìn)程,但是該進(jìn)程組的首進(jìn)
</p>
<p>程(可能也是該對(duì)話期的首進(jìn)程)已經(jīng)終止。最后,應(yīng)當(dāng)引起注意的是所有這些精
</p>
<p>靈進(jìn)程的父進(jìn)程都是init進(jìn)程。 </p>
<p>13.3 編程規(guī)則 </p>
<p>在編寫精靈進(jìn)程程序時(shí)需遵循一些基本規(guī)則,以便防止產(chǎn)生并不希望的交互作用。
</p>
<p>下面先說明這些規(guī)則,然后是一個(gè)按照規(guī)則編寫的函數(shù)daemon-init。 </p>
<p>1. 首先做的是調(diào)用fork,然后使父進(jìn)程終止。這樣做實(shí)現(xiàn)了下面幾點(diǎn)。第一,如
</p>
<p>果該精靈進(jìn)程是由一條簡(jiǎn)單shell命令啟動(dòng)的,那么使父進(jìn)程終止使得shell認(rèn)為這
</p>
<p>條命令已經(jīng)執(zhí)行完成。第二,子進(jìn)程繼承了父進(jìn)程的進(jìn)程組ID,但具有一個(gè)新的進(jìn)
</p>
<p>程ID,這就保證了子進(jìn)程不是一個(gè)進(jìn)程組的首進(jìn)程。這對(duì)于下面就要做的setsid調(diào)
</p>
<p>用是必要的前提條件。 </p>
<p>2. 調(diào)用setsid以創(chuàng)建一個(gè)新對(duì)話期。于是執(zhí)行9.5節(jié)中列舉的三個(gè)操作。使調(diào)用進(jìn)
</p>
<p>程:(1)成為新對(duì)話期的首進(jìn)程,(2)成為一個(gè)新進(jìn)程組的首進(jìn)程,(3)沒有
</p>
<p>控制終端。 </p>
<p>在SVR之下,有些人建議在此時(shí)再調(diào)用fork,并使父進(jìn)程終止。第二個(gè)子進(jìn)程作為
</p>
<p>精靈進(jìn)程繼續(xù)運(yùn)行。這樣就保證了該精靈進(jìn)程不是對(duì)話期首進(jìn)程,于是按照SVR4規(guī)
</p>
<p>則(見9.6節(jié))可以防止它取得控制終端。另一方面,為了避免取得控制終端,無(wú)
</p>
<p>論何時(shí)打開一個(gè)中斷設(shè)備都要指定O-NOCTTY。 </p>
<p>3.
將當(dāng)前工作目錄更改為根目錄。從父進(jìn)程繼承過來的當(dāng)前工作目錄可能在一個(gè)
</p>
<p>裝配的文件系統(tǒng)中。因?yàn)榫`進(jìn)程通常在系統(tǒng)再引導(dǎo)之前是一直存在的,所以如果
</p>
<p>精靈進(jìn)程的當(dāng)前工作目錄在一個(gè)裝配文件系統(tǒng)中,那么該文件系統(tǒng)就不能被拆卸。
</p>
<p>另外,某些精靈進(jìn)程可能會(huì)把當(dāng)前工作目錄更改到某個(gè)指定位置,在此位置做它們
</p>
<p>的工作。例如,行式打印機(jī)假脫機(jī)精靈進(jìn)程常常將其工作目錄更改到它們的spool
</p>
<p>目錄上。 </p>
<p>4. 將文件方式創(chuàng)建屏蔽字設(shè)置為0。由繼承得來的文件方式創(chuàng)建屏蔽字可能會(huì)拒絕
</p>
<p>設(shè)置某些許可權(quán)。例如,若精靈進(jìn)程要?jiǎng)?chuàng)建一個(gè)組可讀、寫的文件,而繼承的文件
</p>
<p>方式創(chuàng)建屏蔽字,屏蔽了這兩種許可權(quán),則所要求的組可讀、寫就不能起作用。
</p>
<p>5.
關(guān)閉不再需要的文件描述符。這樣使精靈進(jìn)程就不再持有從其父進(jìn)程繼承來的
</p>
<p>某些文件描述符(父進(jìn)程可能是shell進(jìn)程,或某個(gè)其它進(jìn)程)。但是,究竟關(guān)閉
</p>
<p>那些描述符則與具體的精靈進(jìn)程有關(guān),所以在下面的例子中不包含此步驟。可以使
</p>
<p>用程序2.3中的open_max函數(shù)來決定最高文件描述符值,并關(guān)閉直到該值的所有描
</p>
<p>述符。 </p>
<p>實(shí)例 </p>
<p>程序13.1是個(gè)函數(shù),可由想初始化成為一個(gè)精靈進(jìn)程的程序調(diào)用。 </p>
<p>#include <sys/types.h> </p>
<p>#include <sys/stat.h> </p>
<p>#include <fcntl.h> </p>
<p>#include "ourhdr.h" </p>
<p>int </p>
<p>daemon_init(void) </p>
<p>{ </p>
<p>pid_t pid; </p>
<p>if ( (pid = fork()) < 0) </p>
<p>return(-1); </p>
<p>else if (pid != 0) </p>
<p>exit(0); /* parent goes bye-bye */ </p>
<p>/* child continues */ </p>
<p>setsid(); /* become session leader */ </p>
<p>chdir("/"); /* change working directory */ </p>
<p>umask(0); /* clear our file mode creation mask */ </p>
<p>return(0); </p>
<p>} </p>
<p>程序13.1 初始化一個(gè)精靈進(jìn)程 </p>
<p>若daemon-init函數(shù)由main函數(shù)調(diào)用,然后進(jìn)入睡眠狀態(tài),那么我們可以用ps命令
</p>
<p>檢查該精靈進(jìn)程的狀態(tài): </p>
<p>$a.out </p>
<p>$ps_axj </p>
<p>PPID PID PGID SID TT TPGID UID COMMAND </p>
<p>1 735 735 735 ? -1 224 a.out </p>
<p>從中可以看到,該精靈進(jìn)程已被正確地初始化。 </p>
<p>13.4 出錯(cuò)記錄 </p>
<p>與精靈進(jìn)程有關(guān)的一個(gè)問題是如何處理出錯(cuò)消息。因?yàn)樗鼪]有控制終端,所以不能
</p>
<p>只是寫到標(biāo)準(zhǔn)出錯(cuò)輸出上。在很多工作站上,控制臺(tái)設(shè)備運(yùn)行一個(gè)窗口系統(tǒng),所以
</p>
<p>我們不希望所有精靈進(jìn)程都寫到控制臺(tái)設(shè)備上。我們也不希望每個(gè)精靈進(jìn)程將它自
</p>
<p>己的出錯(cuò)消息寫到一個(gè)單獨(dú)的文件中。對(duì)系統(tǒng)管理人員而言;如果要關(guān)心哪一個(gè)精
</p>
<p>靈進(jìn)程寫到哪一個(gè)記錄文件中,并定期地檢查這些文件,那么一定會(huì)使他感到頭痛
</p>
<p>。所以,需要有一個(gè)集中的精靈進(jìn)程出錯(cuò)記錄設(shè)施。 </p>
<p>貝克萊開發(fā)了BSD syslog 設(shè)施,并廣泛應(yīng)用于4.2BSD。從4.×BSD導(dǎo)出的很多系統(tǒng)
</p>
<p>都支持syslog。在13.4.2中說明該設(shè)施。 </p>
<p>在系統(tǒng)V中,從來沒有一個(gè)集中的精靈進(jìn)程記錄設(shè)施。SVR4支持BSD風(fēng)格的syslog設(shè)
</p>
<p>施,在SVR4之下的inetd精靈進(jìn)程使用syslog。在SVR中,syslog的基礎(chǔ)是/dev/lo
</p>
<p>g流設(shè)備驅(qū)動(dòng)程序,在下一節(jié)對(duì)此進(jìn)行說明。 </p>
<p>13.4.1 SVR4流log驅(qū)動(dòng)程序 </p>
<p>SVR4提供了一種流設(shè)備驅(qū)動(dòng)程序,其界面具有流出錯(cuò)記錄,流事件跟蹤以及控制臺(tái)
</p>
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -