成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專欄INFORMATION COLUMN

PHP進(jìn)程及進(jìn)程間通信

高勝山 / 1015人閱讀

摘要:擴(kuò)展完成兼容機(jī)通用如獲取進(jìn)程殺死進(jìn)程等。擴(kuò)展實(shí)現(xiàn)方式的進(jìn)程間通信之消息隊(duì)列。四進(jìn)程間通信通常中的進(jìn)程通信方式有消息隊(duì)列信號(hào)量共享內(nèi)存信號(hào)管道。下面這個(gè)例子中,父進(jìn)程等待秒鐘,向子進(jìn)程發(fā)送信號(hào)。子進(jìn)程捕獲信號(hào),掉信號(hào)處理函數(shù)處理。

一、引言

進(jìn)程是一個(gè)具有獨(dú)立功能的程序關(guān)于某個(gè)數(shù)據(jù)集合的一次運(yùn)行活動(dòng)。換句話說(shuō)就是,在系統(tǒng)調(diào)度多個(gè)cpu的時(shí)候,一個(gè)程序的基本單元。進(jìn)程對(duì)于大多數(shù)的語(yǔ)言都不是一個(gè)陌生的概念,作為"世界上最好的語(yǔ)言PHP"當(dāng)然也例外。

二、環(huán)境

php中的進(jìn)程是以擴(kuò)展的形式來(lái)完成。通過(guò)這些擴(kuò)展,我們能夠很輕松的完成進(jìn)程的一系列動(dòng)作。

pcntl擴(kuò)展:主要的進(jìn)程擴(kuò)展,完成進(jìn)程創(chuàng)建于等待操作。

posix擴(kuò)展:完成posix兼容機(jī)通用api,如獲取進(jìn)程id,殺死進(jìn)程等。

sysvmsg擴(kuò)展:實(shí)現(xiàn)system v方式的進(jìn)程間通信之消息隊(duì)列。

sysvsem擴(kuò)展:實(shí)現(xiàn)system v方式的信號(hào)量。

sysvshm擴(kuò)展:實(shí)現(xiàn)system v方式的共享內(nèi)存。

sockets擴(kuò)展:實(shí)現(xiàn)socket通信。

這些擴(kuò)展只能在linux/mac中使用,window下是不支持。最后建議php版本為5.5+。

相關(guān)代碼:進(jìn)程相關(guān)代碼

三、簡(jiǎn)單的例子

一個(gè)簡(jiǎn)單的PHP多進(jìn)程例子,該例子中,一個(gè)子進(jìn)程,一個(gè)父進(jìn)程。子進(jìn)程輸出5次,退出程序。

$parentPid = posix_getpid();
echo "parent progress pid:{$parentPid}
";
$childList = array();
$pid = pcntl_fork();
if ( $pid == -1) {
    // 創(chuàng)建失敗
    exit("fork progress error!
");
} else if ($pid == 0) {
    // 子進(jìn)程執(zhí)行程序
    $pid = posix_getpid();
    $repeatNum = 5;
    for ( $i = 1; $i <= $repeatNum; $i++) {
        echo "({$pid})child progress is running! {$i} 
";
        $rand = rand(1,3);
        sleep($rand);
    }
    exit("({$pid})child progress end!
");
} else {
    // 父進(jìn)程執(zhí)行程序
    $childList[$pid] = 1;
}
// 等待子進(jìn)程結(jié)束
pcntl_wait($status);
echo "({$parentPid})main progress end!";

完美,終于創(chuàng)建了一個(gè)子進(jìn)程,一個(gè)父進(jìn)程。完了么?沒(méi)有,各個(gè)進(jìn)程之間相互獨(dú)立的,沒(méi)有任何交集,使用范圍嚴(yán)重受到現(xiàn)在。怎么辦,哪就進(jìn)程間通信(interprogress communication)唄。

四、進(jìn)程間通信(IPC)

通常linux中的進(jìn)程通信方式有:消息隊(duì)列、信號(hào)量、共享內(nèi)存、信號(hào)、管道、socket。

1.消息隊(duì)列

消息隊(duì)列是存放在內(nèi)存中的一個(gè)隊(duì)列。如下代碼將創(chuàng)建3個(gè)生產(chǎn)者子進(jìn)程,2個(gè)消費(fèi)者子進(jìn)程。這5個(gè)進(jìn)程將通過(guò)消息隊(duì)列通信。

$parentPid = posix_getpid();
echo "parent progress pid:{$parentPid}
";$childList = array();
// 創(chuàng)建消息隊(duì)列,以及定義消息類型(類似于數(shù)據(jù)庫(kù)中的庫(kù))
$id = ftok(__FILE__,"m");
$msgQueue = msg_get_queue($id);
const MSG_TYPE = 1;
// 生產(chǎn)者
function producer(){
    global $msgQueue;
    $pid = posix_getpid();
    $repeatNum = 5;
    for ( $i = 1; $i <= $repeatNum; $i++) {
        $str = "({$pid})progress create! {$i}";
        msg_send($msgQueue,MSG_TYPE,$str);
        $rand = rand(1,3);
        sleep($rand);
    }
}
// 消費(fèi)者
function consumer(){
    global $msgQueue;
    $pid = posix_getpid();
    $repeatNum = 6;
    for ( $i = 1; $i <= $repeatNum; $i++) {
        $rel = msg_receive($msgQueue,MSG_TYPE,$msgType,1024,$message);
        echo "{$message} | consumer({$pid}) destroy 
";
        $rand = rand(1,3);
        sleep($rand);
    }
}
function createProgress($callback){
    $pid = pcntl_fork();
    if ( $pid == -1) {
        // 創(chuàng)建失敗
        exit("fork progress error!
");
    } else if ($pid == 0) {
        // 子進(jìn)程執(zhí)行程序
        $pid = posix_getpid();
        $callback();
        exit("({$pid})child progress end!
");
    }else{
        // 父進(jìn)程執(zhí)行程序
        return $pid;
    }
}
// 3個(gè)寫進(jìn)程
for ($i = 0; $i < 3; $i ++ ) {
    $pid = createProgress("producer");
    $childList[$pid] = 1;
    echo "create producer child progress: {$pid} 
";
}
// 2個(gè)寫進(jìn)程
for ($i = 0; $i < 2; $i ++ ) {
    $pid = createProgress("consumer");
    $childList[$pid] = 1;
    echo "create consumer child progress: {$pid} 
";
}
// 等待所有子進(jìn)程結(jié)束
while(!empty($childList)){
    $childPid = pcntl_wait($status);
    if ($childPid > 0){
        unset($childList[$childPid]);
    }
}
echo "({$parentPid})main progress end!
";

由于消息隊(duì)列去數(shù)據(jù)是,只有一個(gè)進(jìn)程能去到,所以不需要額外的鎖或信號(hào)量。

2. 信號(hào)量與共享內(nèi)存

信號(hào)量:是系統(tǒng)提供的一種原子操作,一個(gè)信號(hào)量,同時(shí)只有你個(gè)進(jìn)程能操作。一個(gè)進(jìn)程獲得了某個(gè)信號(hào)量,就必須被該進(jìn)程釋放掉。

共享內(nèi)存:是系統(tǒng)在內(nèi)存中開(kāi)辟的一塊公共的內(nèi)存區(qū)域,任何一個(gè)進(jìn)程都可以訪問(wèn),在同一時(shí)刻,可以有多個(gè)進(jìn)程訪問(wèn)該區(qū)域,為了保證數(shù)據(jù)的一致性,需要對(duì)該內(nèi)存區(qū)域加鎖或信號(hào)量。

以下,創(chuàng)建多個(gè)進(jìn)程修改內(nèi)存中的同一個(gè)值。

$parentPid = posix_getpid();
echo "parent progress pid:{$parentPid}
";
$childList = array();

// 創(chuàng)建共享內(nèi)存,創(chuàng)建信號(hào)量,定義共享key
$shm_id = ftok(__FILE__,"m");
$sem_id = ftok(__FILE__,"s");
$shareMemory = shm_attach($shm_id);
$signal = sem_get($sem_id);
const SHARE_KEY = 1;
// 生產(chǎn)者
function producer(){
    global $shareMemory;
    global $signal;
    $pid = posix_getpid();
    $repeatNum = 5;
    for ( $i = 1; $i <= $repeatNum; $i++) {
        // 獲得信號(hào)量
        sem_acquire($signal);
        
        if (shm_has_var($shareMemory,SHARE_KEY)){
            // 有值,加一
            $count = shm_get_var($shareMemory,SHARE_KEY);
            $count ++;
            shm_put_var($shareMemory,SHARE_KEY,$count);
            echo "({$pid}) count: {$count}
";
        }else{
            // 無(wú)值,初始化
            shm_put_var($shareMemory,SHARE_KEY,0);
            echo "({$pid}) count: 0
";
        }
        // 用完釋放
        sem_release($signal);
        
        $rand = rand(1,3);
        sleep($rand);
    }
}
function createProgress($callback){
    $pid = pcntl_fork();
    if ( $pid == -1) {
        // 創(chuàng)建失敗
        exit("fork progress error!
");
    } else if ($pid == 0) {
        // 子進(jìn)程執(zhí)行程序
        $pid = posix_getpid();
        $callback();
        exit("({$pid})child progress end!
");
    }else{
        // 父進(jìn)程執(zhí)行程序
        return $pid;
    }
}
// 3個(gè)寫進(jìn)程
for ($i = 0; $i < 3; $i ++ ) {
    $pid = createProgress("producer");
    $childList[$pid] = 1;
    echo "create producer child progress: {$pid} 
";
}
// 等待所有子進(jìn)程結(jié)束
while(!empty($childList)){
    $childPid = pcntl_wait($status);
    if ($childPid > 0){
        unset($childList[$childPid]);
    }
}
// 釋放共享內(nèi)存與信號(hào)量
shm_remove($shareMemory);
sem_remove($signal);
echo "({$parentPid})main progress end!
";
3.信號(hào)

信號(hào)是一種系統(tǒng)調(diào)用。通常我們用的kill命令就是發(fā)送某個(gè)信號(hào)給某個(gè)進(jìn)程的。具體有哪些信號(hào)可以在liunx/mac中運(yùn)行kill -l查看。下面這個(gè)例子中,父進(jìn)程等待5秒鐘,向子進(jìn)程發(fā)送sigint信號(hào)。子進(jìn)程捕獲信號(hào),掉信號(hào)處理函數(shù)處理。

$parentPid = posix_getpid();
echo "parent progress pid:{$parentPid}
";

// 定義一個(gè)信號(hào)處理函數(shù)
function sighandler($signo) {
    $pid = posix_getpid();
    echo "{$pid} progress,oh no ,I"m killed!
";
    exit(1);
}

$pid = pcntl_fork();
if ( $pid == -1) {
    // 創(chuàng)建失敗
    exit("fork progress error!
");
} else if ($pid == 0) {
    // 子進(jìn)程執(zhí)行程序
    // 注冊(cè)信號(hào)處理函數(shù)
    declare(ticks=10);
    pcntl_signal(SIGINT, "sighandler");
    $pid = posix_getpid();
    while(true){
        echo "{$pid} child progress is running!
";
        sleep(1);
    }
    exit("({$pid})child progress end!
");
}else{
    // 父進(jìn)程執(zhí)行程序
    $childList[$pid] = 1;
    // 5秒后,父進(jìn)程向子進(jìn)程發(fā)送sigint信號(hào).
    sleep(5);
    posix_kill($pid,SIGINT);
    sleep(5);
}
echo "({$parentPid})main progress end!
";
4.管道(有名管道)

管道是比較常用的多進(jìn)程通信手段,管道分為無(wú)名管道與有名管道,無(wú)名管道只能用于具有親緣關(guān)系的進(jìn)程間通信,而有名管道可以用于同一主機(jī)上任意進(jìn)程。這里只介紹有名管道。下面的例子,子進(jìn)程寫入數(shù)據(jù),父進(jìn)程讀取數(shù)據(jù)。

// 定義管道路徑,與創(chuàng)建管道
$pipe_path = "/data/test.pipe";
if(!file_exists($pipe_path)){
    if(!posix_mkfifo($pipe_path,0664)){
        exit("create pipe error!");
    }
}
$pid = pcntl_fork();
if($pid == 0){
    // 子進(jìn)程,向管道寫數(shù)據(jù)
    $file = fopen($pipe_path,"w");
    while (true){
        fwrite($file,"hello world");
        $rand = rand(1,3);
        sleep($rand);
    }
    exit("child end!");
}else{
    // 父進(jìn)程,從管道讀數(shù)據(jù)
    $file = fopen($pipe_path,"r");
    while (true){
        $rel = fread($file,20);
        echo "{$rel}
";
        $rand = rand(1,2);
        sleep($rand);
    }
}
5.socket

socket即我們常說(shuō)的套接字編程。這個(gè)待補(bǔ)充。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/22105.html

相關(guān)文章

  • 進(jìn)程通信

    摘要:接受不到消息消息隊(duì)列通過(guò)指定而被創(chuàng)建后,任意一方銷毀了該隊(duì)列,都會(huì)導(dǎo)致其他發(fā)送或接收方失敗。用法場(chǎng)景進(jìn)程,中代碼段要用到中代碼段的結(jié)果。完成了進(jìn)程間同步問(wèn)題此外進(jìn)程間通信采用的方式是共享內(nèi)存。 參考文章 深刻理解Linux進(jìn)程間通信(IPC) 進(jìn)程間通信(IPC)介紹 php高級(jí)應(yīng)用之進(jìn)程控制及進(jìn)程間通訊 workman 作者發(fā)布 PHP 相關(guān)進(jìn)程間通信擴(kuò)展 -- System V ...

    Richard_Gao 評(píng)論0 收藏0
  • PHP進(jìn)程通信

    摘要:一進(jìn)程間通信理解間進(jìn)程通信機(jī)制,先了解下進(jìn)程間有哪些通訊機(jī)制歷史發(fā)展按照歷史來(lái)源主要有兩大塊的管道,,信號(hào)的消息隊(duì)列,共享內(nèi)存,信號(hào)燈。信號(hào)量主要作為進(jìn)程間,以及進(jìn)程內(nèi)部線程之間的通訊手段。主要依賴,兼容擴(kuò)展實(shí)現(xiàn)方式的進(jìn)程間通信之消息隊(duì)列。 PHP間進(jìn)程如何通信,PHP相關(guān)的服務(wù)的IPC是實(shí)現(xiàn)方式,IPC的思想如何用到項(xiàng)目中。 一、linux進(jìn)程間通信 理解php間進(jìn)程通信機(jī)制,先了解...

    haobowd 評(píng)論0 收藏0
  • PHP進(jìn)程初探 --- 進(jìn)程通信二三事

    摘要:多進(jìn)程通信之一命名管道。多進(jìn)程通信之三信號(hào)量與共享內(nèi)存。共享內(nèi)存是最快是進(jìn)程間通信方式,因?yàn)閭€(gè)進(jìn)程之間并不需要數(shù)據(jù)復(fù)制,而是直接操控同一份數(shù)據(jù)。的一些書籍中甚至不建議新手輕易使用這種進(jìn)程間通信的方式,因?yàn)檫@是一種極易產(chǎn)生死鎖的解決方案。 [原文地址:https://blog.ti-node.com/blog...] 往往開(kāi)啟多進(jìn)程的目的是為了一起干活加速效率,前面說(shuō)了不同進(jìn)程之間的內(nèi)存...

    hearaway 評(píng)論0 收藏0
  • PHP進(jìn)程通信

    摘要:是用編寫的,因此它對(duì)系統(tǒng)底層的操作與很像,同大多數(shù)語(yǔ)言一樣,進(jìn)程間通信的方式有以下幾種消息隊(duì)列,管道,共享內(nèi)存,和信號(hào)。創(chuàng)建管道創(chuàng)建進(jìn)程,子進(jìn)程寫管道,父進(jìn)程讀管道通過(guò)函數(shù)創(chuàng)建一個(gè)子進(jìn)程。當(dāng)返回時(shí)表示創(chuàng)建進(jìn)程失敗。 PHP是用C編寫的,因此它對(duì)系統(tǒng)底層API的操作與C很像,同大多數(shù)語(yǔ)言一樣,PHP進(jìn)程間通信的方式有以下幾種:消息隊(duì)列,管道,共享內(nèi)存,socket和信號(hào)。本文是對(duì)這幾種通...

    verano 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

閱讀需要支付1元查看
<