至於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個核心的操做:
(C語言用函數指針實現,JS能夠用匿名函數,PHP能夠用匿名函數、對象方法數組、字符串函數名)
Reactor只是一個事件發生器,實際對socket句柄的操做,如connect/accept、send/recv、close是在callback中完成的。
具體編碼可參考下面的代碼(須要先安裝Reactor擴展):
Reactor模型還能夠與多進程、多線程結合起來用,既實現異步非阻塞IO,又利用到多核。
目前流行的異步服務器程序都是這樣的方式:如