php中pcntl_fork詳解

pcntl_fork()函數是php-pcntl模塊中用於建立進程的函數。(不支持windows)

至於php_pcntl擴展如何安裝開啓這裏就不介紹了,只分析pcntl_fork()這個函數自己。php

複製代碼

1.$one = 123;
2.$one++;
3.$two = time();
4.$pid = [];
5.$pid = pcntl_fork();
6.$three = time();

複製代碼

當:pcntl_fork()函數執行的時候,會建立一個子進程。子進程會複製當前進程,也就是父進程的全部:數據,代碼,還有狀態。react

1.當pcntl_fork()建立子進程成功後,在父進程內,返回0,在子進程內返回自身的進程號,失敗則返回-1linux

2.子進程會複製父進程的代碼,數據。那麼就說明:子,父進程擁有的代碼和數據會如出一轍。windows

3.重點:子進程會複製父進程的狀態,那麼就有上面的示例代碼:在第五行執行了pcntl_fork,那麼建立出的子進程,代碼也是從第五行開始執行的。又子進程複製了數據,代碼。因此,在子進程內同理存在:$one,$two等變量數組

for ($i = 0; $i < 3; $i++) {
    $pid = pcntl_fork();
}
sleep(30);

那麼:上面的for循環,實際會產生多少個子進程?答案是7個,在linux下,用ps命令將能夠看到8個進程(1個父進程,7個子進程)
緣由:父進程在$i=0時,建立出一個子進程0,此時的子進程,還會繼續執行循環。建立出屬於本身的子進程。同理:$i=1時也會這樣……服務器

參考:https://www.jianshu.com/p/5f383a85d663swoole

 

PHP建立多進程的Demo示例:多線程

複製代碼

<?php
/**
 * PHP多進程和多線程的處理
 */

//建立socket監聽
$socketserv = stream_socket_server('tcp://0.0.0.0:8000', $errno, $errstr);
//建立5個子進程
for ($i = 0; $i < 5; $i++) {
    //使用pcntl_fork()建立進程,會返回pid,若是pid==0,則表示主進程
    if (pcntl_fork() == 0) {
        //循環監聽
        while (true) {
            $conn = stream_socket_accept($socketserv);
            //若是監聽失敗,則從新去監聽
            if(!$conn){
                continue;
            }
            //讀取流信息,讀取的大小 是9000
            $request = fread($conn, 9000);
            //寫入響應
            $response = 'hello';
            fwrite($conn, $response);
            //關閉流
            fclose($conn);
        }
        //建立完全部的子進程,而後退出
        exit(0);
    }
}

複製代碼

運行 php stream_socket.php,使用ps -ef 查看進程,會看到多出了以下的5個進程:異步

 

擴展:PHP的異步非阻塞模型 Reactor:socket

 

 

Reactor有4個核心的操做:

  • add 添加socket監聽到reactor
  • set 修改事件監聽,能夠設置監聽的類型,如可讀、可寫
  • del 從reactor中移除,再也不監聽事件
  • callback 就是事件發生後對應的處理邏輯,通常在add/set時制定。

         (C語言用函數指針實現,JS能夠用匿名函數,PHP能夠用匿名函數、對象方法數組、字符串函數名)

 

Reactor只是一個事件發生器,實際對socket句柄的操做,如connect/accept、send/recv、close是在callback中完成的。

具體編碼可參考下面的代碼(須要先安裝Reactor擴展):

 

Reactor模型還能夠與多進程、多線程結合起來用,既實現異步非阻塞IO,又利用到多核。

目前流行的異步服務器程序都是這樣的方式:如

  • Nginx:多進程Reactor
  • Nginx+Lua:多進程Reactor+協程
  • Golang:單線程Reactor+多線程協程
  • Swoole:多線程Reactor+多進程Worker 

參考:http://rango.swoole.com/archives/508

相關文章
相關標籤/搜索