摘要:在中,進程通信的方法有,消息隊列,共享內存,信號量這些的相關方法默認是不開啟的,如果需要,則要再編譯安裝的時候打開管道和消息隊列以及信號量是內核級的共享信息的方式。然后就是多進程間通信了。
在php中,進程通信的方法有FIFO,System V消息隊列,SystemV共享內存,System V信號量
這些System V的相關方法默認是不開啟的,如果需要,則要再編譯安裝的時候打開
--enable-sysvsem --enable --sysvshm --enable-sysvmsg
管道和System V消息隊列以及System V信號量是內核級的共享信息的方式。兩個或多個進程共享駐留在內核中的某些信息。訪問共享信息的每次操作涉及對內核的一次系統調用。
消息隊列中的每個消息相關聯的類型字段提供了兩個特性
類型字段可以用于標識消息,從而允許多個進程在單個隊列上復用(multiplex)消息。 例如,類型字段的某個值用于標識從各個客戶到服務器的消息,對于每一個客戶均為唯一的另外某個值用于標識從服務器到各個客戶的消息。每個客戶的進程ID自然可以用作對于每個客戶均為唯一的類型字段。
類型字段可以用作優先級字段。這允許接受者以不同于先進先出FIFO的某個順序讀出各個消息。這點不同于管道或FIFO,使用管道時,數據必須是以寫入的順序讀出。使用System V消息隊列時,消息能夠以任意順序讀出,之喲啊跟消息類型關聯的值一致就行。而且我們可以指定MSG_IPC_NOWAIT標志調用msg_receive從某個隊列中讀出某個給定類型的任意消息,但是沒有給定類型的消息存在,那就立即返回。
本文主要記錄一下php利用消息隊列進行通信的方法和心得。
// 生成一個消息隊列的key // 生成一個消息隊列的key $msgKey = ftok(__FILE__,"w"); /** msg_get_queue() returns an id that can be used to access the System V message queue with the given {key}. The first call creates the message queue with the optional {perms}. A second call to msg_get_queue() for the same {key} will return a different message queue identifier, but both identifiers access the same underlying message queue. */ // 產生一個消息隊列 $msgQueue = msg_get_queue($msgKey,0666); // 檢查一個隊列是否存在 $status = msg_queue_exists($msgKey); var_dump($status); // 查看當前消息的一些詳細信息 /** * msg_perm.uid The uid of the owner of the queue. * msg_perm.gid The gid of the owner of the queue. * msg_perm.mode The file access mode of the queue. * msg_stime The time that the last message was sent to the queue. * msg_rtime The time that the last message was received from the queue. * msg_ctime The time that the queue was last changed. * msg_qnum The number of messages waiting to be read from the queue. * msg_qbytes The maximum number of bytes allowed in one message queue. On Linux, this value may be read and modified via /proc/sys/kernel/msgmnb. * msg_lspid The pid of the process that sent the last message to the queue. * msg_lrpid The pid of the process that received the last message from the queue. * */ $msgStat = msg_stat_queue($msgQueue); print_r($msgStat); // 把數據加入消息隊列,默認數據會被序列化 msg_send($msgQueue,1,"hahha,1"); msg_send($msgQueue,2,"ooooo,2"); msg_send($msgQueue,1,"xxxxx,3"); // 從消息隊列中讀取一條消息 msg_receive($msgQueue,1, $message_type, 1024, $message1); msg_receive($msgQueue,1, $message_type, 1024, $message2); //msg_receive($msgQueue,1, $message_type, 1024, $message3,true,MSG_IPC_NOWAIT); msg_receive($msgQueue,2, $message_type, 1024, $message3); $msgStat = msg_stat_queue($msgQueue); print_r($msgStat); msg_remove_queue($msgQueue); echo $message1.PHP_EOL; echo $message2.PHP_EOL; echo $message3.PHP_EOL;
結果如下:
Array ( [msg_perm.uid] => 0 [msg_perm.gid] => 0 [msg_perm.mode] => 438 [msg_stime] => 0 [msg_rtime] => 0 [msg_ctime] => 1492759388 [msg_qnum] => 0 [msg_qbytes] => 16384 [msg_lspid] => 0 [msg_lrpid] => 0 ) Array ( [msg_perm.uid] => 0 [msg_perm.gid] => 0 [msg_perm.mode] => 438 [msg_stime] => 1492759388 [msg_rtime] => 1492759388 [msg_ctime] => 1492759388 [msg_qnum] => 0 [msg_qbytes] => 16384 [msg_lspid] => 23336 [msg_lrpid] => 23336 ) hahha,1 xxxxx,3 ooooo,2
手冊中對msg_send和msg_receive這兩個定義如下。
bool msg_send ( resource $queue , int $msgtype , mixed $message [, bool $serialize = true [, bool $blocking = true [, int &$errorcode ]]] ) msg_send() sends a message of type msgtype (which MUST be greater than 0) to the message queue specified by queue. bool msg_receive ( resource $queue , int $desiredmsgtype , int &$msgtype , int $maxsize , mixed &$message [, bool $unserialize = true [, int $flags = 0 [, int &$errorcode ]]] ) msg_receive() will receive the first message from the specified queue of the type specified by desiredmsgtype.
msg_receive的第二個參數desiredmsgtype ,指定從隊列中獲取什么樣的消息。
如果desiredmsgtype等于0,那么就返回改隊列中的第一個消息。每一個消息隊列都是作為一個先進先出的鏈表維護,因此type為0,返回該隊列中最早的消息。(但是這個情況下,會出現阻塞,$flags要設置為MSG_IPC_NOWAIT)
如果desiredmsgtype 大于0,那就返回其類型值為desiredmsgtype的第一個消息。
如果desiredmsgtype 小于0,那就返回其類型值小于或等于desiredmsgtype參數的絕對值的消息中類型最小的第一個消息。(但是這個情況下,會出現阻塞,$flags要設置為MSG_IPC_NOWAIT)
如果你要讀取的那類消息不存在,程序就會阻塞,直到有對應類型的消息寫入到隊列里。當然,可以通過設置$flags = MSG_IPC_NOWAIT來設置為非阻塞。
然后就是多進程間通信了。代碼如下:
// 獲取消息隊列key $key = ftok(__FILE__,"w"); // 創建一個消息隊列 $queue = msg_get_queue($key); $child = []; $num = 5; $result = []; for($i=0;$i<$num;$i++){ $pid = pcntl_fork(); if($pid == -1) { die("fork failed"); } else if ($pid > 0) { $child[] = $pid; } else if ($pid == 0) { $sleep = rand(1,4); msg_send($queue,2,array("name" => $i."~".$sleep)); sleep($sleep); exit(0); } } while(count($child)){ foreach($child as $k => $pid) { $res = pcntl_waitpid($pid,$status,WNOHANG); if ($res == -1 || $res > 0 ) { unset($child[$k]); msg_receive($queue,2,$message_type,1024,$data); $result[] = $data; } } } msg_remove_queue($queue); print_r($result);
結果如下:
Array ( [0] => Array ( [name] => 1~3 ) [1] => Array ( [name] => 0~3 ) [2] => Array ( [name] => 3~2 ) [3] => Array ( [name] => 4~4 ) [4] => Array ( [name] => 2~4 ) )
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/22826.html
摘要:接受不到消息消息隊列通過指定而被創建后,任意一方銷毀了該隊列,都會導致其他發送或接收方失敗。用法場景進程,中代碼段要用到中代碼段的結果。完成了進程間同步問題此外進程間通信采用的方式是共享內存。 參考文章 深刻理解Linux進程間通信(IPC) 進程間通信(IPC)介紹 php高級應用之進程控制及進程間通訊 workman 作者發布 PHP 相關進程間通信擴展 -- System V ...
摘要:擴展完成兼容機通用如獲取進程殺死進程等。擴展實現方式的進程間通信之消息隊列。四進程間通信通常中的進程通信方式有消息隊列信號量共享內存信號管道。下面這個例子中,父進程等待秒鐘,向子進程發送信號。子進程捕獲信號,掉信號處理函數處理。 一、引言 進程是一個具有獨立功能的程序關于某個數據集合的一次運行活動。換句話說就是,在系統調度多個cpu的時候,一個程序的基本單元。進程對于大多數的語言都不是...
閱讀 2458·2021-09-27 13:36
閱讀 2163·2019-08-29 18:47
閱讀 2129·2019-08-29 15:21
閱讀 1394·2019-08-29 11:14
閱讀 1979·2019-08-28 18:29
閱讀 1623·2019-08-28 18:04
閱讀 568·2019-08-26 13:58
閱讀 3206·2019-08-26 12:12