• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            Prayer

            在一般中尋求卓越
            posts - 1256, comments - 190, trackbacks - 0, articles - 0
              C++博客 :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理

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

            Posted on 2009-03-13 20:39 Prayer 閱讀(460) 評論(0)  編輯 收藏 引用 所屬分類: LINUX/UNIX/AIX

            實現(xiàn)守護(hù)進(jìn)程的步驟

            守護(hù)進(jìn)程(Daemon)是運行在后臺的一種特殊進(jìn)程。它獨立于控制終端并且周期性地執(zhí)行某種任務(wù)或等待處理某些發(fā)生的事件。守護(hù)進(jìn)程是一種很有用的進(jìn)程。Linux的大多數(shù)服務(wù)器就是用守護(hù)進(jìn)程實現(xiàn)的。比如,Internet服務(wù)器inetd,Web服務(wù)器httpd等。同時,守護(hù)進(jìn)程完成許多系統(tǒng)任務(wù)。比如,作業(yè)規(guī)劃進(jìn)程crond,打印進(jìn)程lpd等。

            在Linux系統(tǒng)中,要編程實現(xiàn)一個守護(hù)進(jìn)程必須遵守如下的步驟。

            1.讓init進(jìn)程成為新產(chǎn)生進(jìn)程的父進(jìn)程。

            調(diào)用fork函數(shù)創(chuàng)建子進(jìn)程后,使父進(jìn)程立即退出。這樣,產(chǎn)生的子進(jìn)程將變成孤兒進(jìn)程,并被init進(jìn)程接管,同時,所產(chǎn)生的新進(jìn)程將變?yōu)樵诤笈_運行。

            2.調(diào)用setsid函數(shù)

            通過調(diào)用setsid函數(shù),使得新創(chuàng)建的進(jìn)程脫離控制終端,同時創(chuàng)建新的進(jìn)程組,并成為該進(jìn)程組的首進(jìn)程。為了使讀者更好地理解這一步驟,下面介紹進(jìn)程組、會話(session)的基本概念。

            在Linux系統(tǒng)中,所有的進(jìn)程都屬于各自的進(jìn)程組。進(jìn)程組是一個或多個進(jìn)程的集合。打個比方,可以認(rèn)為某個班級是一個進(jìn)程組,而其中成員就是進(jìn)程。一個班級至少有一個成員。當(dāng)一個班級的最后一個成員不存在的時候,這個班級也就不存在了,也就是進(jìn)程組消亡了。

            每個進(jìn)程組都有類似于進(jìn)程號的標(biāo)識,稱為進(jìn)程組ID。進(jìn)程組ID是由領(lǐng)頭進(jìn)程的進(jìn)程號決定的,每個進(jìn)程組都存在一個領(lǐng)頭進(jìn)程。進(jìn)程組的存在與否與領(lǐng)頭進(jìn)程是否存在沒有關(guān)系。

            會話是一個或多個進(jìn)程組的集合。與進(jìn)程組類似,每個會話都存在一個領(lǐng)頭進(jìn)程。Linux是一個多用戶的操作系統(tǒng),在同一時刻系統(tǒng)中會存在屬于不同用戶的多個進(jìn)程。如果用戶在某個終端上發(fā)送了某個信號,例如,按下“Ctrl+C”發(fā)送SIGINT信號,如何確保信號被正確地發(fā)送到對應(yīng)的進(jìn)程,同時不會影響使用其他終端的用戶的進(jìn)程?

            會話和進(jìn)程組是Linux內(nèi)核用于管理多用戶情況下用戶進(jìn)程的方法。每個進(jìn)程都屬于一個進(jìn)程組,而進(jìn)程組又屬于某個會話。當(dāng)用戶從終端登錄系統(tǒng)(不管是終端還是偽終端),系統(tǒng)會創(chuàng)建一個新的會話。在該終端上啟動的進(jìn)程都會被系統(tǒng)劃歸到會話的進(jìn)程組中。

            會話中的進(jìn)程通過該會話中的領(lǐng)頭進(jìn)程(常稱其為控制進(jìn)程)與一個終端相連。該終端是會話的控制終端。一個會話只能有一個控制終端,反之一樣。如果會話存在一個控制終端,則它必然擁有一個前臺進(jìn)程組。屬于該組的進(jìn)程可以從控制終端獲得輸入。這時,其他的進(jìn)程組都為后臺進(jìn)程組。圖8.3所示為會話、進(jìn)程組、進(jìn)程與控制終端之間的關(guān)系。

            圖8.3 會話、進(jìn)程組、進(jìn)程與控制終端的關(guān)系

            由于守護(hù)進(jìn)程沒有控制終端,而使用fork函數(shù)創(chuàng)建的子進(jìn)程繼承了父進(jìn)程的控制終端、會話和進(jìn)程組,因此,必須創(chuàng)建新的會話,以脫離父進(jìn)程的影響。Linux系統(tǒng)提供了setsid函數(shù)用于創(chuàng)建新的會話。setsid函數(shù)的信息如表8.1所示。

            表8.1                                                             setsid函數(shù)

            頭文件

            <unistd.h>

            函數(shù)形式

            pid_t setsid(void);

            返回值

            成功

            失敗

            是否設(shè)置errno

            調(diào)用進(jìn)程的會話ID

            −1

            setsid函數(shù)將創(chuàng)建新的會話,并使得調(diào)用setsid函數(shù)的進(jìn)程成為新會話的領(lǐng)頭進(jìn)程。調(diào)用setsid函數(shù)的進(jìn)程是新創(chuàng)建會話中的惟一的進(jìn)程組,進(jìn)程組ID為調(diào)用進(jìn)程的進(jìn)程號。setsid函數(shù)產(chǎn)生這一結(jié)果還有個條件,即調(diào)用進(jìn)程不為一個進(jìn)程的領(lǐng)頭進(jìn)程。由于在第一步中調(diào)用fork的父進(jìn)程退出,使得子進(jìn)程不可能是進(jìn)程組的領(lǐng)頭進(jìn)程。該會話的領(lǐng)頭進(jìn)程沒有控制終端與其相連。至此,滿足了守護(hù)進(jìn)程沒有控制終端的要求。

            3.更改當(dāng)前工作目錄

            使用fork函數(shù)產(chǎn)生的子進(jìn)程將繼承父進(jìn)程的當(dāng)前工作目錄。當(dāng)進(jìn)程沒有結(jié)束時,其工作目錄是不能被卸載的。為了防止這種問題發(fā)生,守護(hù)進(jìn)程一般會將其工作目錄更改到根目錄下(/目錄)。更改工作目錄使用的函數(shù)是chdir。

            4.關(guān)閉文件描述符,并重定向標(biāo)準(zhǔn)輸入、輸出和錯誤輸出

            新產(chǎn)生的進(jìn)程從父進(jìn)程繼承了某些打開的文件描述符,如果不使用這些文件描述符,則需要關(guān)閉它們。守護(hù)進(jìn)程是運行在系統(tǒng)后臺的,不應(yīng)該在終端有任何的輸出信息。可以使用dup函數(shù)將標(biāo)準(zhǔn)輸入、輸出和錯誤輸出重定向到/dev/null設(shè)備上(/dev/null是一個空設(shè)備,向其寫入數(shù)據(jù)不會有任何輸出)。下面給出具體的代碼:

                  int fd;

                  //將標(biāo)準(zhǔn)輸入輸出重定向到空設(shè)備

                  fd = open ("/dev/null", O_RDWR, 0);

                  if (fd != -1)

                {

                   dup2 (fd, STDIN_FILENO);

                   dup2 (fd, STDOUT_FILENO);

                  dup2 (fd, STDERR_FILENO);

                  if (fd > 2)

                    close (fd);

                }

            5.設(shè)置守護(hù)進(jìn)程的文件權(quán)限創(chuàng)建掩碼

            很多情況下,守護(hù)進(jìn)程會創(chuàng)建一些臨時文件。出于安全性的考慮,往往不希望這些文件被別的用戶查看。這時,可以使用umask函數(shù)修改文件權(quán)限,創(chuàng)建掩碼的取值,以滿足守護(hù)進(jìn)程的要求。

            8.2.2 守護(hù)進(jìn)程具體實現(xiàn)

            本節(jié)給出一個守護(hù)進(jìn)程創(chuàng)建的實例。程序p8.1.c中定義了daemon函數(shù),用于實現(xiàn)對守護(hù)進(jìn)程的創(chuàng)建。其創(chuàng)建思想在8.2.1中有詳細(xì)的介紹,程序的具體代碼如下:

            //p8.1.c 守護(hù)進(jìn)程的實現(xiàn)

            #include <stdio.h>

            #include <unistd.h>

            #include <sys/types.h>

            #include <sys/stat.h>

            #include <fcntl.h>

            /* daemon函數(shù)用于將調(diào)用函數(shù)的進(jìn)程轉(zhuǎn)化為守護(hù)進(jìn)程 */

            int

            daemon (int nochdir, int noclose)

            {

            pid_t pid;

            pid = fork ();

            /* 如果創(chuàng)建進(jìn)程失敗 */

            if (pid < 0)

                {

                  perror ("fork");

                  return -1;

                }

            /* 父進(jìn)程退出運行 */

            if (pid != 0)

                exit (0);

            /* 成為會話領(lǐng)頭進(jìn)程 */

            pid = setsid();

            if (pid < -1)

                {

                  perror ("setsid");

                  return -1;

                }

            /* 將工作目錄修改成根目錄 */

            if (! nochdir)

                chdir ("/");

            /* 將標(biāo)準(zhǔn)輸入輸出重定向到空設(shè)備 */

            if (! noclose)

                {

                  int fd;

                  fd = open ("/dev/null", O_RDWR, 0);

                  if (fd != -1)

                {

                  dup2 (fd, STDIN_FILENO);

                  dup2 (fd, STDOUT_FILENO);

                  dup2 (fd, STDERR_FILENO);

                  if (fd > 2)

                    close (fd);

                }

                }

            umask (0027);

            return 0;

            }

            int main(void)

            {

                   daemon(0,0);

                   sleep(1000);

               

                   return 0;

            }  

            使用gcc編譯p8.1.c,得到名為p8.1的可執(zhí)行文件。執(zhí)行該程序,程序?qū)⒁允刈o(hù)進(jìn)程的狀態(tài)運行,如圖8.4所示。

            色综合久久中文色婷婷| 国产—久久香蕉国产线看观看| 久久有码中文字幕| 精品多毛少妇人妻AV免费久久 | 99久久777色| 久久精品国产亚洲Aⅴ香蕉| 久久人人爽人人爽人人片av麻烦| 久久久精品2019免费观看| 久久se这里只有精品| 一本色道久久88—综合亚洲精品| yellow中文字幕久久网| 久久久国产乱子伦精品作者| 一级做a爰片久久毛片毛片| A级毛片无码久久精品免费| 久久精品无码专区免费东京热 | 久久久久亚洲AV成人网人人软件| 久久久www免费人成精品| 精品久久久久久无码中文野结衣| 久久久久国产精品熟女影院| 国产精品毛片久久久久久久| 色8激情欧美成人久久综合电| 久久久久一区二区三区| 久久99国产综合精品女同| 综合网日日天干夜夜久久 | 午夜不卡久久精品无码免费| 久久夜色精品国产亚洲av| 99精品久久久久久久婷婷| 99热成人精品热久久669| 亚洲国产精品久久久天堂| 久久久久久国产a免费观看黄色大片| 99久久精品费精品国产一区二区 | 国产精品热久久无码av| 久久国产精品-久久精品| 久久不射电影网| 久久精品国产精品青草app| 成人资源影音先锋久久资源网| 亚洲中文字幕无码久久综合网| 久久久久久精品成人免费图片| 伊人久久大香线蕉av不卡| 亚洲国产成人乱码精品女人久久久不卡 | 久久久久久国产精品无码下载|