利用PHP用寫Multi Process程式 - 2 使用信號機
2.1 互斥機制
多程序程式設計一定會遇到的問題就是:不同的程序間在兢爭相同的資源。資源可能是螢幕的輸出或是資料庫的連線。我們不希望兩個以上的程序兢爭螢幕輸出資源,到時可能演變成一個程序輸出兩行而另一個程序再輸出兩行,這樣的輸出是不能看的。
為了解決這個問題,我們必須引入互斥機制,就要有關鍵區域(Critical Area)和信號機(Semaphore)的技術。
在 PHP 下,可以參考官方文件 Semaphore, Shared Memory and IPC Functions
要是以上幾個名詞都忘了的話,再溫習一下作業系統的書吧。
2.2 信號機的使用方式
2.2.1 建立信號機
使用sem_get()可以取得一個新的信號機。格式
int sem_get (int key [, int max_acquire[, int perm]])
參數
- key : 信號機的編號,要是一個還沒有用過的編號。通常使用 ftok() 用來取得
- max_acquire : 設定一個信號機可以讓多少程序取用,預設為1
- perm : 設定訪問權限
2.2 信號機的使用
2.2.1 建立信號機
使用sem_get()可以取得一個新的信號機。格式
int sem_get (int key [, int max_acquire[, int perm]])
參數
- key : 信號機的編號,要是一個還沒有用過的編號。通常使用 ftok() 用來取得
- max_acquire : 設定一個信號機可以讓多少程序取用,預設為1
- perm : 設定訪問權限
2.2.2 申請
使用 sem_acquire()
向信號機申請減少一個資源數,並且進入臨界區。格式
int sem_acquire (int sem_identifier)
參數
- sem_identifier:信號機的編號
2.2.3 釋放信號機
使用 sem_acquire() 通知信號機釋放一個資源數,並且離開臨界區。格式
int sem_release (int sem_identifier)
參數
- sem_identifier:信號機的編號
2_3 簡單的範例
<?php $semid=sem_get( 0xFF3, 1, 0666); sem_acquire($semid);//向編號為$semid信號機申請進入臨界區 /* 臨界區開始 */ /*這在裡對共用資源作操作 */ /* 臨界區結束 */ sem_release($semid);//釋放編號為$semid的信號機 ?>
2.4 信號機的程式範例
2.4.1 範例
<?php // 寫兩個子行程搶資源,用semapher做保護 $process_num = 3; print "老爸:我是老爸,我要生{$process_num}個小孩。\n"; $children = array(); $source_id = ftok('semaghor.php', 'w'); $sem = sem_get($source_id, 1); //取得一個semaphore,可以申請的只有一個 /* 以下要來生小孩 */ $i = 1; while($i <= $process_num) { $pid = pcntl_fork(); //生出一個子程序 if($pid == -1) { //要是 $pid 是 -1 那就是出錯了 exit(1); //離開,並且報告出錯 } else if ($pid != 0) { //若$pid不是0的話,那就是父行程 /*這是老爸專區*/ print "老爸:生了一個第{$i}個孩子,pid是{$pid}\n"; $children[] = $pid; } else { //子程序拿到的 $pid 是 0 /*這是小朋友區*/ break; //直接出迴圈 } $i++; } if($pid) { /* 老爸會進到這裡 */ $status = null; print "老爸:老爸會等大家玩好才離開\n"; foreach($children as $pid) { //要等每個孩子都離開才離開 pcntl_waitpid($pid, $status); print "老爸:pid是{$pid}的那個孩子,回去時他告訴我他的狀況是{$status}\n"; } print '老爸也要走了'."\n"; } else { /*以下是小朋友遊樂區*/ for($j=1;$j<3;$j++)>
2.4.2 執行結果
老爸:我是老爸,我要生3個小孩。 老爸:生了一個第1個孩子,pid是11480 我是第1個小朋友,我是第1次進入了臨界區,我要玩1秒 老爸:生了一個第2個孩子,pid是11481 老爸:生了一個第3個孩子,pid是11482 老爸:老爸會等大家玩好才離開 我是第1個小朋友,要離開臨界區了 我是第2個小朋友,我是第1次進入了臨界區,我要玩2秒 我是第2個小朋友,要離開臨界區了 我是第3個小朋友,我是第1次進入了臨界區,我要玩3秒 我是第3個小朋友,要離開臨界區了 我是第1個小朋友,我是第2次進入了臨界區,我要玩1秒 我是第1個小朋友,要離開臨界區了 我是第2個小朋友,我是第2次進入了臨界區,我要玩2秒 我是第1個小朋友,要走了 老爸:pid是11480的那個孩子,回去時他告訴我他的狀況是0 我是第2個小朋友,要離開臨界區了 我是第3個小朋友,我是第2次進入了臨界區,我要玩3秒 我是第2個小朋友,要走了 老爸:pid是11481的那個孩子,回去時他告訴我他的狀況是0 我是第3個小朋友,要離開臨界區了 我是第3個小朋友,要走了 老爸:pid是11482的那個孩子,回去時他告訴我他的狀況是0 老爸也要走了
沒有留言:
張貼留言