先簡單來了解一下多程式 [來初步瞭解一下PHP多程式及簡單demo]
php的多程式是不是可以無限制的fork子程式?
fork呼叫的一個奇妙之處就是它僅僅被呼叫一次,卻能夠返回兩次,它可能有三種不同的返回值:
- 在父程式中,fork返回新建立子程式的程式ID;
- 在子程式中,fork返回0;
- 如果出現錯誤,fork返回一個負值;
在fork函式執行完畢後,如果建立新程式成功,則出現兩個程式,一個是子程式,一個是父程式。在子程式中,fork函式返回0,在父程式中,fork返回新建立子程式的程式ID。我們可以通過fork返回的值來判斷當前程式是子程式還是父程式。
引用一位網友的話來解釋fpid的值為什麼在父子程式中不同。“其實就相當於連結串列,程式形成了連結串列,父程式的fpid(p 意味point)指向子程式的程式id, 因為子程式沒有子程式,所以其fpid為0
<?php
//定義程式數量
define('FORK_NUMS', 5);
//用於儲存程式pid
$pids = array();
//我們建立5個子程式
for ($i = 0; $i < FORK_NUMS; ++$i) {
$pids[$i] = pcntl_fork();
if ($pids[$i] == -1) {
die('fork error');
} else if ($pids[$i]) {
//這裡是父程式空間,也就是主程式
//我們的for迴圈第一次進入到這裡時,pcntl_wait會掛起當前主程式,等待第一個子程式執行完畢退出
//注意for迴圈的程式碼是在主程式的,掛起主程式,相當於當前的for迴圈也阻塞在這裡了
//第一個子程式退出後,然後再建立第二個子程式,到這裡後又掛起,等待第二個子程式退出,繼續建立第三個,等等。。
pcntl_wait($status);
} else {
//這裡是子程式空間
echo "父程式ID: ", posix_getppid(), " 程式ID : ", posix_getpid(), " {$i} \r\n";
//我們讓子程式等待3秒,再退出
sleep(3);
exit;
}
}
阻塞與非阻塞案例
通過pcntl_fork來建立子程式,使用pcntl_wait和pcntl_waitpid來回收子程式。子程式退出後,父程式沒有及時回收,就會產生殭屍程式。
[阻塞案例]
<?php
define('FORK_NUMS', 5);
$pids = array();
//建立5個子程式
for($i = 0; $i < FORK_NUMS; ++$i) {
$pids[$i] = pcntl_fork();
if($pids[$i] == -1) {
die('fork error');
} else if ($pids[$i]) {
pcntl_wait($status);
} else {
echo getmypid() , " {$i} \r\n";
exit;
}
}
# php fork.php
52470 0
52471 1
52472 2
52473 3
52474 4
以上程式碼通過for迴圈fork出5個子程式,父程式會阻塞著等待子程式退出,然後建立下一個子程式。
---------------------BUG:建立多程式的目的,就是為了能夠並行的處理任務,阻塞的方式並不是我們期待的結果。------------------
[非阻塞案例]
<?php
define('FORK_NUMS', 5);
$pids = array();
//建立5個子程式
for($i = 0; $i < FORK_NUMS; ++$i) {
$pids[$i] = pcntl_fork();
if($pids[$i] == -1) {
die('fork error');
} else if ($pids[$i]) {
pcntl_wait($status, WNOHANG);
} else {
echo getmypid() , " {$i} \r\n";
exit;
}
}
//反覆執行幾次,發現沒有規律
[root@bogon default]# php fork.php
52645 0
52647 2
52646 1
52648 3
52649 4
[root@bogon default]# php fork.php
52660 0
52663 3
52664 4
52661 1
52662 2
[root@bogon default]# php fork.php
52681 0
52683 2
52685 4
52684 3
52682 1
我們可以通過設定pcntl_wait的第二個引數為WNOHANG來控制程式是否阻塞。該函式可以在沒有子程式退出的情況下立刻跳出執行後續程式碼。
pcntl_wait等同於以pid為-1呼叫pcntl_waitpid函式。
pcntl_waitpid函式可以等待指定pid的程式。
本文章參考的https://www.cnblogs.com/jkko123/p/6294602.html