摘要:多進(jìn)程通信之一命名管道。多進(jìn)程通信之三信號(hào)量與共享內(nèi)存。共享內(nèi)存是最快是進(jìn)程間通信方式,因?yàn)閭€(gè)進(jìn)程之間并不需要數(shù)據(jù)復(fù)制,而是直接操控同一份數(shù)據(jù)。的一些書籍中甚至不建議新手輕易使用這種進(jìn)程間通信的方式,因?yàn)檫@是一種極易產(chǎn)生死鎖的解決方案。
[原文地址:https://blog.ti-node.com/blog...]
往往開啟多進(jìn)程的目的是為了一起干活加速效率,前面說(shuō)了不同進(jìn)程之間的內(nèi)存空間都是相互隔離的,也就說(shuō)進(jìn)程A是無(wú)法讀或?qū)戇M(jìn)程B中的任何數(shù)據(jù)內(nèi)容的,反之亦然。但是,有些時(shí)候,多個(gè)進(jìn)程之間必須要有相互通知的機(jī)制,用職場(chǎng)上的話來(lái)說(shuō)就叫“及時(shí)溝通”。大家都在一起做同一件事情的不同部分,彼此之間“及時(shí)溝通”是很重要的。
于是進(jìn)程間通信就誕生了,英文縮寫IPC,全稱InterProcess Communication。
常見(jiàn)的進(jìn)程間通信方式有:管道(分無(wú)名和有名兩種)、消息隊(duì)列、信號(hào)量、共享內(nèi)存和socket,最后一種方式今天不提,放到后面的php socket編程中去說(shuō),重點(diǎn)說(shuō)前四種方式。
管道是*NIX上常見(jiàn)的一個(gè)東西,大家平時(shí)使用linux的時(shí)候也都在用,簡(jiǎn)單理解就是|,比如ps -aux|grep php這就是管道,大概意思類似于ps進(jìn)程和grep進(jìn)程兩個(gè)進(jìn)程之間用|完成了通信。管道是一種半雙工(現(xiàn)在也有系統(tǒng)已經(jīng)支持全雙工的管道)的工作方式,也就是說(shuō)數(shù)據(jù)只能沿著管道的一個(gè)方向進(jìn)行傳遞,不可以在同一個(gè)管道上反向傳數(shù)據(jù)。管道分為兩種,一種叫做未命名的管道,另一種叫做命名管道,未命名管道只能在擁有公共祖先的兩個(gè)進(jìn)程之間使用,簡(jiǎn)單理解就是只能用于父進(jìn)程和和其子進(jìn)程之間的通信,但是命名管道則可以用于任何兩個(gè)毫無(wú)關(guān)連的進(jìn)程之間的通信(一會(huì)兒將要演示的將是這種命名管道)。
需要特殊指出的是消息隊(duì)列、信號(hào)量和共享內(nèi)存這三種IPC同屬于XSI IPC(XSI可以認(rèn)為是POSIX標(biāo)準(zhǔn)的超集,簡(jiǎn)單粗暴理解為C++之于C)。這三種IPC在*NIX中一般都有兩個(gè)“名字”來(lái)為其命名,一個(gè)叫做標(biāo)志符,一個(gè)叫做鍵(key)。標(biāo)志符是一個(gè)非負(fù)整數(shù),每當(dāng)一個(gè)IPC結(jié)構(gòu)被創(chuàng)建然后又被銷毀后,標(biāo)志符便會(huì)+1一直加到整數(shù)的最大整數(shù)數(shù)值,而后又從0開始重新計(jì)算。既然是為了多進(jìn)程通信使用,那么多進(jìn)程在使用XSI IPC的時(shí)候就需要使用一個(gè)名字來(lái)找到相應(yīng)的IPC,然后才能對(duì)其進(jìn)行讀寫(術(shù)語(yǔ)叫做多個(gè)進(jìn)程在同一個(gè)IPC結(jié)構(gòu)上匯聚),所以POSIX建議是無(wú)論何時(shí)創(chuàng)建一個(gè)IPC結(jié)構(gòu),都應(yīng)指定一個(gè)鍵(key)與之關(guān)聯(lián)。一句話總結(jié)就是:標(biāo)志符是XSI IPC的內(nèi)部名稱,鍵(key)是XSI IPC的外部名稱。
使多個(gè)進(jìn)程在XSI IPC上匯聚的方法大概有如下三種:
使用指定鍵IPC_PRIVATE來(lái)創(chuàng)建一個(gè)IPC結(jié)構(gòu),然后將返回的標(biāo)志符保存到一個(gè)文件中,然后進(jìn)程之間通過(guò)讀取這個(gè)文件中的標(biāo)志符進(jìn)行通信。使用公共的頭文件。這么做的缺點(diǎn)是多了IO操作。
將共同認(rèn)同的鍵寫入到公共頭文件中。這么做的缺點(diǎn)這個(gè)鍵可能已經(jīng)與一個(gè)IPCi結(jié)構(gòu)關(guān)聯(lián),這樣在使用這個(gè)鍵創(chuàng)建結(jié)構(gòu)的時(shí)候就可能會(huì)出錯(cuò),然后必須刪除已有的IPC結(jié)構(gòu)再重新創(chuàng)建。
認(rèn)同一個(gè)文件路徑名和項(xiàng)目ID,然后使用ftok將這兩個(gè)參數(shù)轉(zhuǎn)換成一個(gè)鍵。這將是我們使用的方式。
XSI IPC結(jié)構(gòu)有一個(gè)與之對(duì)應(yīng)的權(quán)限結(jié)構(gòu),叫做ipc_perm,這個(gè)結(jié)構(gòu)中定義了IPC結(jié)構(gòu)的創(chuàng)建者、擁有者等。
多進(jìn)程通信之一:命名管道。 在php中,創(chuàng)建一個(gè)管道的函數(shù)叫做posix_mkfifo(),管道創(chuàng)建完成后其實(shí)就是一個(gè)文件,然后就可以用任何與讀寫文件相關(guān)的函數(shù)對(duì)其進(jìn)行操作了,代碼大概演示一下:
0 ) { // 在父進(jìn)程中 // 打開命名管道,然后讀取文本 $file = fopen( $pipe_file, "r" ); // 注意此處fread會(huì)被阻塞 $content = fread( $file, 1024 ); echo $content.PHP_EOL; // 注意此處再次阻塞,等待回收子進(jìn)程,避免僵尸進(jìn)程 pcntl_wait( $status ); }
運(yùn)行結(jié)果如下:
多進(jìn)程通信之二:消息隊(duì)列。這個(gè)怕是很多人都聽過(guò),不過(guò)印象往往停留在kafka、rabbitmq之類的用于服務(wù)器解耦網(wǎng)絡(luò)消息隊(duì)列軟件上。消息隊(duì)列是消息的鏈接表(一種常見(jiàn)的數(shù)據(jù)結(jié)構(gòu)),但是這種消息隊(duì)列存儲(chǔ)于系統(tǒng)內(nèi)核中(不是用戶態(tài)),一般我們外部程序使用一個(gè)key來(lái)對(duì)消息隊(duì)列進(jìn)行讀寫操作。在PHP中,是通過(guò)msg_*系列函數(shù)完成消息隊(duì)列操作的。
0 ) { // 在父進(jìn)程中 // 使用msg_receive()函數(shù)獲取消息 msg_receive( $queue, 0, $msgtype, 1024, $message ); echo $message.PHP_EOL; // 用完了記得清理刪除消息隊(duì)列 msg_remove_queue( $queue ); pcnlt_wait( $status ); } else if( 0 == $pid ) { // 在子進(jìn)程中 // 向消息隊(duì)列中寫入消息 // 使用msg_send()向消息隊(duì)列中寫入消息,具體可以參考文檔內(nèi)容 msg_send( $queue, 1, "helloword" ); exit; }
運(yùn)行結(jié)果如下:
但是,值得大家繼續(xù)深入研究的是msg_send()和msg_receive()兩個(gè)函數(shù),這兩個(gè)的每一個(gè)參數(shù)都是非常值得深入研究和嘗試的。篇幅問(wèn)題,這里就不再詳細(xì)描述。
多進(jìn)程通信之三:信號(hào)量與共享內(nèi)存。共享內(nèi)存是最快是進(jìn)程間通信方式,因?yàn)閚個(gè)進(jìn)程之間并不需要數(shù)據(jù)復(fù)制,而是直接操控同一份數(shù)據(jù)。實(shí)際上信號(hào)量和共享內(nèi)存是分不開的,要用也是搭配著用。*NIX的一些書籍中甚至不建議新手輕易使用這種進(jìn)程間通信的方式,因?yàn)檫@是一種極易產(chǎn)生死鎖的解決方案。共享內(nèi)存顧名思義,就是一坨內(nèi)存中的區(qū)域,可以讓多個(gè)進(jìn)程進(jìn)行讀寫。這里最大的問(wèn)題就在于數(shù)據(jù)同步的問(wèn)題,比如一個(gè)在更改數(shù)據(jù)的時(shí)候,另一個(gè)進(jìn)程不可以讀,不然就會(huì)產(chǎn)生問(wèn)題。所以為了解決這個(gè)問(wèn)題才引入了信號(hào)量,信號(hào)量是一個(gè)計(jì)數(shù)器,是配合共享內(nèi)存使用的,一般情況下流程如下:
當(dāng)前進(jìn)程獲取將使用的共享內(nèi)存的信號(hào)量
如果信號(hào)量大于0,那么就表示這塊兒共享資源可以使用,然后進(jìn)程將信號(hào)量減1
如果信號(hào)量為0,則進(jìn)程進(jìn)入休眠狀態(tài)一直到信號(hào)量大于0,進(jìn)程喚醒開始從1
一個(gè)進(jìn)程不再使用當(dāng)前共享資源情況下,就會(huì)將信號(hào)量減1。這個(gè)地方,信號(hào)量的檢測(cè)并且減1是原子性的,也就說(shuō)兩個(gè)操作必須一起成功,這是由系統(tǒng)內(nèi)核來(lái)實(shí)現(xiàn)的。
在php中,信號(hào)量和共享內(nèi)存先后一共也就這幾個(gè)函數(shù):
其中,sem_是信號(hào)量相關(guān)函數(shù),shm_是共享內(nèi)存相關(guān)函數(shù)。
0 ) { $child_pid[] = $pid; } } while( !empty( $child_pid ) ){ foreach( $child_pid as $pid_key => $pid_item ){ pcntl_waitpid( $pid_item, $status, WNOHANG ); unset( $child_pid[ $pid_key ] ); } } // 休眠2秒鐘,2個(gè)子進(jìn)程都執(zhí)行完畢了 sleep( 2 ); echo "最終結(jié)果".shm_get_var( $shm_id, SHM_VAR ).PHP_EOL; // 記得刪除共享內(nèi)存數(shù)據(jù),刪除共享內(nèi)存是有順序的,先remove后detach,順序反過(guò)來(lái)php可能會(huì)報(bào)錯(cuò) shm_remove( $shm_id ); shm_detach( $shm_id );
運(yùn)行結(jié)果如下:
確切說(shuō),如果不用sem的話,上述的運(yùn)行結(jié)果在一定概率下就會(huì)產(chǎn)生1而不是2。但是只要加入sem,那就一定保證100%是2,絕對(duì)不會(huì)出現(xiàn)其他數(shù)值。
[原文地址:https://blog.ti-node.com/blog...]
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/29368.html
摘要:因?yàn)樽舆M(jìn)程一定不會(huì)是組長(zhǎng)進(jìn)程,所以子進(jìn)程可以調(diào)用。主進(jìn)程退出子進(jìn)程繼續(xù)執(zhí)行啦啦啦,啦啦啦,啦啦啦,已經(jīng)變成啦,開心一般服務(wù)器軟件都有寫配置項(xiàng),比如以模式運(yùn)行還是以模式運(yùn)行。 [原文地址:https://blog.ti-node.com/blog...] 其實(shí)前面是談過(guò)一次daemon進(jìn)程的,但是并涉及過(guò)多原理,但是并不影響使用。今天打算說(shuō)說(shuō)關(guān)于daemon進(jìn)程更多的二三事,本質(zhì)上說(shuō),如...
摘要:原文地址正如標(biāo)題所言,顫顫抖抖開篇。于是只能是你自己,把單子上的個(gè)快遞逐次和收到的對(duì)比一遍,然后對(duì)比完畢后再把這個(gè)單子給了阿梅,然后阿梅繼續(xù)等。剃光頭前的阿梅,就是,不敢正眼看老板娘一眼。剃光頭后的阿梅,就是,可徒手接魔鬼隊(duì)的死亡之球。 [原文地址:https://blog.ti-node.com/blog...] 正如標(biāo)題所言,顫顫抖抖開篇epoll。顫顫抖抖的原因大概也就是以前幾乎...
摘要:傳統(tǒng)的網(wǎng)頁(yè)編程采用的三劍客來(lái)實(shí)現(xiàn),在微信小程序中同樣有三劍客。觀察者模式不難實(shí)現(xiàn),重點(diǎn)是如何在微信小程序中搭配其特有的生命周期來(lái)使用。交互事件傳統(tǒng)的事件傳遞類型有冒泡型與捕獲型,微信小程序中自然也有。 本文由作者鄒永勝授權(quán)網(wǎng)易云社區(qū)發(fā)布。 簡(jiǎn)介為了更好的展示我們即時(shí)通訊SDK強(qiáng)悍的能力,網(wǎng)易云信IM SDK微信小程序DEMO的開發(fā)就提上了日程。用產(chǎn)品的話說(shuō)就是: 云信 IM 小程序 S...
閱讀 2318·2021-11-24 10:18
閱讀 2761·2021-11-19 09:59
閱讀 1737·2019-08-30 15:53
閱讀 1219·2019-08-30 15:53
閱讀 1093·2019-08-30 14:19
閱讀 2508·2019-08-30 13:14
閱讀 3045·2019-08-30 13:00
閱讀 1994·2019-08-30 11:11