国产av日韩一区二区三区精品,成人性爱视频在线观看,国产,欧美,日韩,一区,www.成色av久久成人,2222eeee成人天堂

Table of Contents
Daemon守護(hù)進(jìn)程
Daemon進(jìn)程的編程規(guī)則
編寫守護(hù)進(jìn)程
Home php教程 php手冊(cè) 用PHP寫一個(gè)Daemon守護(hù)進(jìn)程

用PHP寫一個(gè)Daemon守護(hù)進(jìn)程

Jun 13, 2016 am 09:38 AM
php daemon

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

這又是一個(gè)有趣的概念,daemon在英語(yǔ)中是"精靈"的意思,就像我們經(jīng)常在迪斯尼動(dòng)畫里見(jiàn)到的那些,有些會(huì)飛,有些不會(huì),經(jīng)常圍著動(dòng)畫片的主人公轉(zhuǎn)來(lái)轉(zhuǎn)去,啰里啰唆地提一些忠告,時(shí)不時(shí)倒霉地撞在柱子上,有時(shí)候還會(huì)想出一些小小的花招,把主人公從敵人手中救出來(lái),正因如此,daemon有時(shí)也被譯作"守護(hù)神"。所以,daemon進(jìn)程在國(guó)內(nèi)也有兩種譯法,有些人譯作"精靈進(jìn)程",有些人譯作"守護(hù)進(jìn)程",這兩種稱呼的出現(xiàn)頻率都很高。

與真正的daemon相似,daemon進(jìn)程也習(xí)慣于把自己隱藏在人們的視線之外,默默為系統(tǒng)做出貢獻(xiàn),有時(shí)人們也把它們稱作"后臺(tái)服務(wù)進(jìn)程"。daemon進(jìn)程的壽命很長(zhǎng),一般來(lái)說(shuō),從它們一被執(zhí)行開(kāi)始,直到整個(gè)系統(tǒng)關(guān)閉,它們才會(huì)退出。幾乎所有的服務(wù)器程序,包括我們熟知的Apache和wu-FTP,都用daemon進(jìn)程的形式實(shí)現(xiàn)。很多Linux下常見(jiàn)的命令如inetd和ftpd,末尾的字母d就是指daemon。

為什么一定要使用daemon進(jìn)程呢?Linux中每一個(gè)系統(tǒng)與用戶進(jìn)行交流的界面稱為終端(terminal),每一個(gè)從此終端開(kāi)始運(yùn)行的進(jìn)程都會(huì)依附于這個(gè)終端,這個(gè)終端就稱為這些進(jìn)程的控制終端(Controlling terminal),當(dāng)控制終端被關(guān)閉時(shí),相應(yīng)的進(jìn)程都會(huì)被自動(dòng)關(guān)閉。關(guān)于這點(diǎn),讀者可以用X-Window中的XTerm試驗(yàn)一下,(每一個(gè)XTerm就是一個(gè)打開(kāi)的終端,)我們可以通過(guò)鍵入命令啟動(dòng)應(yīng)用程序,比如:$netscape 然后我們關(guān)閉XTerm窗口,剛剛啟動(dòng)的netscape窗口也會(huì)隨之一同突然蒸發(fā)。但是daemon進(jìn)程卻能夠突破這種限制,即使對(duì)應(yīng)的終端關(guān)閉,它也能在系統(tǒng)中長(zhǎng)久地存在下去,如果我們想讓某個(gè)進(jìn)程長(zhǎng)命百歲,不因?yàn)橛脩艋蚪K端或其他的變化而受到影響,就必須把這個(gè)進(jìn)程變成一個(gè)daemon進(jìn)程。

Daemon進(jìn)程的編程規(guī)則

如果想把自己的進(jìn)程變成daemon進(jìn)程,我們必須嚴(yán)格按照以下步驟進(jìn)行:

1. 調(diào)用fork產(chǎn)生一個(gè)子進(jìn)程,同時(shí)父進(jìn)程退出。我們所有后續(xù)工作都在子進(jìn)程中完成。這樣做我們可以:

  • 如果我們是從命令行執(zhí)行的該程序,這可以造成程序執(zhí)行完畢的假象,shell會(huì)回去等待下一條命令;
  • 剛剛通過(guò)fork產(chǎn)生的新進(jìn)程一定不會(huì)是一個(gè)進(jìn)程組的組長(zhǎng),這為第2步的執(zhí)行提供了前提保障。

這樣做還會(huì)出現(xiàn)一種很有趣的現(xiàn)象:由于父進(jìn)程已經(jīng)先于子進(jìn)程退出,會(huì)造成子進(jìn)程沒(méi)有父進(jìn)程,變成一個(gè)孤兒進(jìn)程(orphan)。每當(dāng)系統(tǒng)發(fā)現(xiàn)一個(gè)孤兒進(jìn)程,就會(huì)自動(dòng)由1號(hào)進(jìn)程收養(yǎng)它,這樣,原先的子進(jìn)程就會(huì)變成1號(hào)進(jìn)程的子進(jìn)程。

2. 調(diào)用setsid系統(tǒng)調(diào)用。這是整個(gè)過(guò)程中最重要的一步。它的作用是創(chuàng)建一個(gè)新的會(huì)話(session),并自任該會(huì)話的組長(zhǎng)(session leader)。如果調(diào)用進(jìn)程是一個(gè)進(jìn)程組的組長(zhǎng),調(diào)用就會(huì)失敗,但這已經(jīng)在第1步得到了保證。調(diào)用setsid有3個(gè)作用:

  • 讓進(jìn)程擺脫原會(huì)話的控制;
  • 讓進(jìn)程擺脫原進(jìn)程組的控制;
  • 讓進(jìn)程擺脫原控制終端的控制;

總之,就是讓調(diào)用進(jìn)程完全獨(dú)立出來(lái),脫離所有其他進(jìn)程的控制。

3. 把當(dāng)前工作目錄切換到根目錄。

如果我們是在一個(gè)臨時(shí)加載的文件系統(tǒng)上執(zhí)行這個(gè)進(jìn)程的,比如:/mnt/floppy/,該進(jìn)程的當(dāng)前工作目錄就會(huì)是/mnt/floppy/。在整個(gè)進(jìn)程運(yùn)行期間該文件系統(tǒng)都無(wú)法被卸下(umount),而無(wú)論我們是否在使用這個(gè)文件系統(tǒng),這會(huì)給我們帶來(lái)很多不便。解決的方法是使用chdir系統(tǒng)調(diào)用把當(dāng)前工作目錄變?yōu)楦夸?,?yīng)該不會(huì)有人想把根目錄卸下吧。

當(dāng)然,在這一步里,如果有特殊的需要,我們也可以把當(dāng)前工作目錄換成其他的路徑,比如/tmp。

4. 將文件權(quán)限掩碼設(shè)為0。

這需要調(diào)用系統(tǒng)調(diào)用umask,參見(jiàn)附錄3。每個(gè)進(jìn)程都會(huì)從父進(jìn)程那里繼承一個(gè)文件權(quán)限掩碼,當(dāng)創(chuàng)建新文件時(shí),這個(gè)掩碼被用于設(shè)定文件的默認(rèn)訪問(wèn)權(quán)限,屏蔽掉某些權(quán)限,如一般用戶的寫權(quán)限。當(dāng)另一個(gè)進(jìn)程用exec調(diào)用我們編寫的daemon程序時(shí),由于我們不知道那個(gè)進(jìn)程的文件權(quán)限掩碼是什么,這樣在我們創(chuàng)建新文件時(shí),就會(huì)帶來(lái)一些麻煩。所以,我們應(yīng)該重新設(shè)置文件權(quán)限掩碼,我們可以設(shè)成任何我們想要的值,但一般情況下,大家都把它設(shè)為0,這樣,它就不會(huì)屏蔽用戶的任何操作。

如果你的應(yīng)用程序根本就不涉及創(chuàng)建新文件或是文件訪問(wèn)權(quán)限的設(shè)定,你也完全可以把文件權(quán)限掩碼一腳踢開(kāi),跳過(guò)這一步。

5. 關(guān)閉所有不需要的文件。

同文件權(quán)限掩碼一樣,我們的新進(jìn)程會(huì)從父進(jìn)程那里繼承一些已經(jīng)打開(kāi)了的文件。這些被打開(kāi)的文件可能永遠(yuǎn)不被我們的daemon進(jìn)程讀或?qū)?,但它們一樣消耗系統(tǒng)資源,而且可能導(dǎo)致所在的文件系統(tǒng)無(wú)法卸下。需要指出的是,文件描述符為0、1和2的三個(gè)文件(文件描述符的概念將在下一章介紹),也就是我們常說(shuō)的輸入、輸出和報(bào)錯(cuò)這三個(gè)文件也需要被關(guān)閉。很可能不少讀者會(huì)對(duì)此感到奇怪,難道我們不需要輸入輸出嗎?但事實(shí)是,在上面的第2步后,我們的daemon進(jìn)程已經(jīng)與所屬的控制終端失去了聯(lián)系,我們從終端輸入的字符不可能達(dá)到daemon進(jìn)程,daemon進(jìn)程用常規(guī)的方法(如printf)輸出的字符也不可能在我們的終端上顯示出來(lái)。所以這三個(gè)文件已經(jīng)失去了存在的價(jià)值,也應(yīng)該被關(guān)閉。

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

在我之前的文章中,介紹過(guò)Gearman的使用。在我的項(xiàng)目中,我使用了PHP來(lái)編寫一直運(yùn)行的Worker。如果按照Gearman官方推薦的例子,只是簡(jiǎn)單的一個(gè)循環(huán)來(lái)等待任務(wù),會(huì)有一些問(wèn)題,包括:1、當(dāng)代碼進(jìn)行過(guò)修改之后,如何讓代碼的修改生效;2、重啟Worker的時(shí)候,如何保證當(dāng)前的任務(wù)處理完成才重啟。

針對(duì)這個(gè)問(wèn)題,我考慮了以下的解決方法:

  1. 每次修改完代碼后,Worker需要手工重啟(先殺死然后啟動(dòng))。這個(gè)只能解決重新加載配置文件的問(wèn)題。
  2. 在Worker中設(shè)置,單次任務(wù)循環(huán)完成后,就對(duì)Worker進(jìn)行重啟。這個(gè)方案的問(wèn)題在于消耗比較大。
  3. 在Worker中添加一個(gè)退出函數(shù),如果需要Worker退出的時(shí)候,在Client端發(fā)送一個(gè)優(yōu)先級(jí)比較高的退出調(diào)用。這個(gè)需要客戶端配合,在使用后臺(tái)類任務(wù)時(shí),不太適合。
  4. 在Worker中檢查文件是否發(fā)生變化,如果發(fā)生了變化,退出并重啟自身。
  5. 為Worker編寫信號(hào)控制,接受重啟指令,類似于 http restart graceful 指令。

最后,結(jié)合4和5兩種方法,可以實(shí)現(xiàn)這樣一個(gè)Daemon,如果配置文件發(fā)生了變化,他就會(huì)自動(dòng)重啟;如果接受到了用戶的 kill -1 pid 信號(hào),也會(huì)重新啟動(dòng)。

代碼如下:

<?php

declare( ticks = 1 );
// This case will check the config file regularly, if the config file changed, it will restart it self
// If you want to restart the daemon gracefully, give it a HUP signal
// by shiqiang<cocowool@gmail.com> at 2011-12-04

$init_md5 = md5_file( 'config.php');

// register signal handler
pcntl_signal( SIGALRM, "signal_handler", true );
pcntl_signal( SIGHUP, 'signal_handler', TRUE );

$job_flag = FALSE;    //Job status flag, to justify if the job has been finished
$signal_flag = FALSE;    //Signal status flag, to justify whether we received the kill -1 signal

while( 1 ){
    $job_flag = FALSE;    //Job status flag
    print "Worker start running ... n";
    sleep(5);
    print "Worker's task done ... n";
    $flag = TRUE;    //Job status flag
    AutoStart( $signal_flag );
}

function signal_handler( $signal ) {
    global $job_flag;
    global $signal_flag;

    switch( $signal ){
        case SIGQUIT:
            print date('y-m-d H:i:s', time() ) . " Caught Signal : SIGQUIT - No : $signal n";
            exit(0);
            break;
        case SIGSTOP:
            print date('y-m-d H:i:s', time() ) . " Caught Signal : SIGSTOP - No : $signal n";
            break;
        case SIGHUP:
            print date('y-m-d H:i:s', time() ) . " Caught Signal : SIGHUP - No : $signal n";
            if( $flag === TRUE ){
                AutoStart( TRUE );
            }else{
                $signal_flag = TRUE;
            }
            break;
        case SIGALRM:
            print date('y-m-d H:i:s', time() ) . " Caught Signal : SIGALRM - No : $signal n";
            //pcntl_exec( '/bin/ls' );
            pcntl_alarm( 5 );
            break;
        default:
            break;
    }
}

function AutoStart( $signal = FALSE, $filename = 'config.php' ){
    global $init_md5;

    if( $signal || md5_file( $filename ) != $init_md5 ){
        print "The config file has been changed, we are going to restart. n";
        $pid = pcntl_fork();
        if( $pid == -1 ){
            print "Fork error n";
        }else if( $pid > 0 ){
            print "Parent exit n";
            exit(0);
        }else{
            $init_md5 = md5_file( $filename );
            print "Child continue to run n";
        }
    }
}
?>
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn

Hot AI Tools

Undress AI Tool

Undress AI Tool

Undress images for free

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Clothoff.io

Clothoff.io

AI clothes remover

Video Face Swap

Video Face Swap

Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Tools

Notepad++7.3.1

Notepad++7.3.1

Easy-to-use and free code editor

SublimeText3 Chinese version

SublimeText3 Chinese version

Chinese version, very easy to use

Zend Studio 13.0.1

Zend Studio 13.0.1

Powerful PHP integrated development environment

Dreamweaver CS6

Dreamweaver CS6

Visual web development tools

SublimeText3 Mac version

SublimeText3 Mac version

God-level code editing software (SublimeText3)

How to get the current session ID in PHP? How to get the current session ID in PHP? Jul 13, 2025 am 03:02 AM

The method to get the current session ID in PHP is to use the session_id() function, but you must call session_start() to successfully obtain it. 1. Call session_start() to start the session; 2. Use session_id() to read the session ID and output a string similar to abc123def456ghi789; 3. If the return is empty, check whether session_start() is missing, whether the user accesses for the first time, or whether the session is destroyed; 4. The session ID can be used for logging, security verification and cross-request communication, but security needs to be paid attention to. Make sure that the session is correctly enabled and the ID can be obtained successfully.

PHP get substring from a string PHP get substring from a string Jul 13, 2025 am 02:59 AM

To extract substrings from PHP strings, you can use the substr() function, which is syntax substr(string$string,int$start,?int$length=null), and if the length is not specified, it will be intercepted to the end; when processing multi-byte characters such as Chinese, you should use the mb_substr() function to avoid garbled code; if you need to intercept the string according to a specific separator, you can use exploit() or combine strpos() and substr() to implement it, such as extracting file name extensions or domain names.

How do you perform unit testing for php code? How do you perform unit testing for php code? Jul 13, 2025 am 02:54 AM

UnittestinginPHPinvolvesverifyingindividualcodeunitslikefunctionsormethodstocatchbugsearlyandensurereliablerefactoring.1)SetupPHPUnitviaComposer,createatestdirectory,andconfigureautoloadandphpunit.xml.2)Writetestcasesfollowingthearrange-act-assertpat

How to split a string into an array in PHP How to split a string into an array in PHP Jul 13, 2025 am 02:59 AM

In PHP, the most common method is to split the string into an array using the exploit() function. This function divides the string into multiple parts through the specified delimiter and returns an array. The syntax is exploit(separator, string, limit), where separator is the separator, string is the original string, and limit is an optional parameter to control the maximum number of segments. For example $str="apple,banana,orange";$arr=explode(",",$str); The result is ["apple","bana

JavaScript Data Types: Primitive vs Reference JavaScript Data Types: Primitive vs Reference Jul 13, 2025 am 02:43 AM

JavaScript data types are divided into primitive types and reference types. Primitive types include string, number, boolean, null, undefined, and symbol. The values are immutable and copies are copied when assigning values, so they do not affect each other; reference types such as objects, arrays and functions store memory addresses, and variables pointing to the same object will affect each other. Typeof and instanceof can be used to determine types, but pay attention to the historical issues of typeofnull. Understanding these two types of differences can help write more stable and reliable code.

Using std::chrono in C Using std::chrono in C Jul 15, 2025 am 01:30 AM

std::chrono is used in C to process time, including obtaining the current time, measuring execution time, operation time point and duration, and formatting analysis time. 1. Use std::chrono::system_clock::now() to obtain the current time, which can be converted into a readable string, but the system clock may not be monotonous; 2. Use std::chrono::steady_clock to measure the execution time to ensure monotony, and convert it into milliseconds, seconds and other units through duration_cast; 3. Time point (time_point) and duration (duration) can be interoperable, but attention should be paid to unit compatibility and clock epoch (epoch)

How to pass a session variable to another page in PHP? How to pass a session variable to another page in PHP? Jul 13, 2025 am 02:39 AM

In PHP, to pass a session variable to another page, the key is to start the session correctly and use the same $_SESSION key name. 1. Before using session variables for each page, it must be called session_start() and placed in the front of the script; 2. Set session variables such as $_SESSION['username']='JohnDoe' on the first page; 3. After calling session_start() on another page, access the variables through the same key name; 4. Make sure that session_start() is called on each page, avoid outputting content in advance, and check that the session storage path on the server is writable; 5. Use ses

How does PHP handle Environment Variables? How does PHP handle Environment Variables? Jul 14, 2025 am 03:01 AM

ToaccessenvironmentvariablesinPHP,usegetenv()orthe$_ENVsuperglobal.1.getenv('VAR_NAME')retrievesaspecificvariable.2.$_ENV['VAR_NAME']accessesvariablesifvariables_orderinphp.iniincludes"E".SetvariablesviaCLIwithVAR=valuephpscript.php,inApach

See all articles