進程是一個具有獨立功能的程式關於某個資料集合的一次運行活動。換句話說就是,在系統調度多個cpu的時候,一個程式的基本單元。過程對大多數的語言都不是一個陌生的概念,作為"世界上最好的語言PHP"當然也例外。
環境
php中的進程是以擴展的形式來完成。透過這些擴展,我們能夠輕鬆的完成進程的一系列動作。
pcntl擴展:主要的進程擴展,完成進程創建於等待操作。
posix擴充:完成posix相容機通用api,如取得進程id,殺死進程等。
sysvmsg擴充:實作system v方式的進程間通訊之訊息佇列。
sysvsem擴充:實作system v方式的訊號量。
sysvshm擴充:實作system v方式的共享記憶體。
sockets擴充:實作socket通訊。
這些擴充功能只能在linux/mac中使用,window下是不支援。最後建議php版本為5.5+。
簡單的例子
一個簡單的PHP多進程例子,該例子中,一個子進程,一個父進程。子行程輸出5次,退出程式。
$parentPid = posix_getpid(); echo "parent progress pid:{$parentPid}\n"; $childList = array(); $pid = pcntl_fork(); if ( $pid == -1) { // 创建失败 exit("fork progress error!\n"); } else if ($pid == 0) { // 子进程执行程序 $pid = posix_getpid(); $repeatNum = 5; for ( $i = 1; $i <= $repeatNum; $i++) { echo "({$pid})child progress is running! {$i} \n"; $rand = rand(1,3); sleep($rand); } exit("({$pid})child progress end!\n"); } else { // 父进程执行程序 $childList[$pid] = 1; } // 等待子进程结束 pcntl_wait($status); echo "({$parentPid})main progress end!";
完美,終於創建了一個子進程,一個父進程。完了麼?沒有,各個進程之間相互獨立的,沒有任何交集,使用範圍嚴重受到現在。怎麼辦,哪就進程間通訊(interprogress communication)嗆。
四、進程間通訊(IPC)
通常linux中的進程通訊方式有:訊息佇列、信號量、共享記憶體、訊號、管道、socket。
1.訊息佇列
訊息佇列是存放在記憶體中的一個佇列。如下程式碼將建立3個生產者子進程,2個消費者子進程。這5個進程將透過訊息隊列通訊。
$parentPid = posix_getpid(); echo "parent progress pid:{$parentPid}\n";$childList = array(); // 创建消息队列,以及定义消息类型(类似于数据库中的库) $id = ftok(__FILE__,'m'); $msgQueue = msg_get_queue($id); const MSG_TYPE = 1; // 生产者 function producer(){ global $msgQueue; $pid = posix_getpid(); $repeatNum = 5; for ( $i = 1; $i <= $repeatNum; $i++) { $str = "({$pid})progress create! {$i}"; msg_send($msgQueue,MSG_TYPE,$str); $rand = rand(1,3); sleep($rand); } } // 消费者 function consumer(){ global $msgQueue; $pid = posix_getpid(); $repeatNum = 6; for ( $i = 1; $i <= $repeatNum; $i++) { $rel = msg_receive($msgQueue,MSG_TYPE,$msgType,1024,$message); echo "{$message} | consumer({$pid}) destroy \n"; $rand = rand(1,3); sleep($rand); } } function createProgress($callback){ $pid = pcntl_fork(); if ( $pid == -1) { // 创建失败 exit("fork progress error!\n"); } else if ($pid == 0) { // 子进程执行程序 $pid = posix_getpid(); $callback(); exit("({$pid})child progress end!\n"); }else{ // 父进程执行程序 return $pid; } } // 3个写进程 for ($i = 0; $i < 3; $i ++ ) { $pid = createProgress('producer'); $childList[$pid] = 1; echo "create producer child progress: {$pid} \n"; } // 2个写进程 for ($i = 0; $i < 2; $i ++ ) { $pid = createProgress('consumer'); $childList[$pid] = 1; echo "create consumer child progress: {$pid} \n"; } // 等待所有子进程结束 while(!empty($childList)){ $childPid = pcntl_wait($status); if ($childPid > 0){ unset($childList[$childPid]); } } echo "({$parentPid})main progress end!\n";
由於訊息佇列去資料是,只有一個行程可以去到,所以不需要額外的鎖定或訊號量。
2. 信號量與共享記憶體
信號量:是系統提供的一種原子操作,一個信號量,同時只有你個進程能操作。一個行程獲得了某個信號量,就必須被該行程釋放掉。
共享記憶體:是系統在記憶體中開闢的一塊公共的記憶體區域,任何一個進程都可以訪問,在同一時刻,可以有多個進程訪問該區域,為了保證資料的一致性,需要對該記憶體區域加鎖或信號量。
以下,建立多個進程修改記憶體中的同一個值。
$parentPid = posix_getpid(); echo "parent progress pid:{$parentPid}\n"; $childList = array(); // 创建共享内存,创建信号量,定义共享key $shm_id = ftok(__FILE__,'m'); $sem_id = ftok(__FILE__,'s'); $shareMemory = shm_attach($shm_id); $signal = sem_get($sem_id); const SHARE_KEY = 1; // 生产者 function producer(){ global $shareMemory; global $signal; $pid = posix_getpid(); $repeatNum = 5; for ( $i = 1; $i <= $repeatNum; $i++) { // 获得信号量 sem_acquire($signal); if (shm_has_var($shareMemory,SHARE_KEY)){ // 有值,加一 $count = shm_get_var($shareMemory,SHARE_KEY); $count ++; shm_put_var($shareMemory,SHARE_KEY,$count); echo "({$pid}) count: {$count}\n"; }else{ // 无值,初始化 shm_put_var($shareMemory,SHARE_KEY,0); echo "({$pid}) count: 0\n"; } // 用完释放 sem_release($signal); $rand = rand(1,3); sleep($rand); } } function createProgress($callback){ $pid = pcntl_fork(); if ( $pid == -1) { // 创建失败 exit("fork progress error!\n"); } else if ($pid == 0) { // 子进程执行程序 $pid = posix_getpid(); $callback(); exit("({$pid})child progress end!\n"); }else{ // 父进程执行程序 return $pid; } } // 3个写进程 for ($i = 0; $i < 3; $i ++ ) { $pid = createProgress('producer'); $childList[$pid] = 1; echo "create producer child progress: {$pid} \n"; } // 等待所有子进程结束 while(!empty($childList)){ $childPid = pcntl_wait($status); if ($childPid > 0){ unset($childList[$childPid]); } } // 释放共享内存与信号量 shm_remove($shareMemory); sem_remove($signal); echo "({$parentPid})main progress end!\n";
3.訊號
訊號是一種系統呼叫。通常我們用的kill指令就是發送某個訊號給某個行程的。具體有哪些訊號可以在liunx/mac中執行kill -l檢視。下面這個範例中,父行程等待5秒鐘,向子程序發送sigint訊號。子進程捕獲訊號,掉訊號處理函數處理。
$parentPid = posix_getpid(); echo "parent progress pid:{$parentPid}\n"; // 定义一个信号处理函数 function sighandler($signo) { $pid = posix_getpid(); echo "{$pid} progress,oh no ,I'm killed!\n"; exit(1); } $pid = pcntl_fork(); if ( $pid == -1) { // 创建失败 exit("fork progress error!\n"); } else if ($pid == 0) { // 子进程执行程序 // 注册信号处理函数 declare(ticks=10); pcntl_signal(SIGINT, "sighandler"); $pid = posix_getpid(); while(true){ echo "{$pid} child progress is running!\n"; sleep(1); } exit("({$pid})child progress end!\n"); }else{ // 父进程执行程序 $childList[$pid] = 1; // 5秒后,父进程向子进程发送sigint信号. sleep(5); posix_kill($pid,SIGINT); sleep(5); } echo "({$parentPid})main progress end!\n";
4.管道(有名管道)
管道是比較常用的多進程通訊手段,管道分為無名管道與有名管道,無名管道只能用於具有親緣關係的進程間通信,而有名管道可以用於同一主機上任意進程。這裡只介紹有名管道。下面的例子,子進程寫入數據,父進程讀取數據。
// 定义管道路径,与创建管道 $pipe_path = '/data/test.pipe'; if(!file_exists($pipe_path)){ if(!posix_mkfifo($pipe_path,0664)){ exit("create pipe error!"); } } $pid = pcntl_fork(); if($pid == 0){ // 子进程,向管道写数据 $file = fopen($pipe_path,'w'); while (true){ fwrite($file,'hello world'); $rand = rand(1,3); sleep($rand); } exit('child end!'); }else{ // 父进程,从管道读数据 $file = fopen($pipe_path,'r'); while (true){ $rel = fread($file,20); echo "{$rel}\n"; $rand = rand(1,2); sleep($rand); } }
相關推薦:
以上是PHP進程間通訊詳解的詳細內容。更多資訊請關注PHP中文網其他相關文章!

使用數據庫存儲會話的主要優勢包括持久性、可擴展性和安全性。 1.持久性:即使服務器重啟,會話數據也能保持不變。 2.可擴展性:適用於分佈式系統,確保會話數據在多服務器間同步。 3.安全性:數據庫提供加密存儲,保護敏感信息。

在PHP中實現自定義會話處理可以通過實現SessionHandlerInterface接口來完成。具體步驟包括:1)創建實現SessionHandlerInterface的類,如CustomSessionHandler;2)重寫接口中的方法(如open,close,read,write,destroy,gc)來定義會話數據的生命週期和存儲方式;3)在PHP腳本中註冊自定義會話處理器並啟動會話。這樣可以將數據存儲在MySQL、Redis等介質中,提升性能、安全性和可擴展性。

SessionID是網絡應用程序中用來跟踪用戶會話狀態的機制。 1.它是一個隨機生成的字符串,用於在用戶與服務器之間的多次交互中保持用戶的身份信息。 2.服務器生成並通過cookie或URL參數發送給客戶端,幫助在用戶的多次請求中識別和關聯這些請求。 3.生成通常使用隨機算法保證唯一性和不可預測性。 4.在實際開發中,可以使用內存數據庫如Redis來存儲session數據,提升性能和安全性。

在無狀態環境如API中管理會話可以通過使用JWT或cookies來實現。 1.JWT適合無狀態和可擴展性,但大數據時體積大。 2.Cookies更傳統且易實現,但需謹慎配置以確保安全性。

要保護應用免受與會話相關的XSS攻擊,需採取以下措施:1.設置HttpOnly和Secure標誌保護會話cookie。 2.對所有用戶輸入進行輸出編碼。 3.實施內容安全策略(CSP)限制腳本來源。通過這些策略,可以有效防護會話相關的XSS攻擊,確保用戶數據安全。

优化PHP会话性能的方法包括:1.延迟会话启动,2.使用数据库存储会话,3.压缩会话数据,4.管理会话生命周期,5.实现会话共享。这些策略能显著提升应用在高并发环境下的效率。

theSession.gc_maxlifetimesettinginphpdeterminesthelifespanofsessiondata,setInSeconds.1)它'sconfiguredinphp.iniorviaini_set().2)abalanceisesneededeededeedeedeededto toavoidperformance andunununununexpectedLogOgouts.3)

在PHP中,可以使用session_name()函數配置會話名稱。具體步驟如下:1.使用session_name()函數設置會話名稱,例如session_name("my_session")。 2.在設置會話名稱後,調用session_start()啟動會話。配置會話名稱可以避免多應用間的會話數據衝突,並增強安全性,但需注意會話名稱的唯一性、安全性、長度和設置時機。


熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

MinGW - Minimalist GNU for Windows
這個專案正在遷移到osdn.net/projects/mingw的過程中,你可以繼續在那裡關注我們。 MinGW:GNU編譯器集合(GCC)的本機Windows移植版本,可自由分發的導入函式庫和用於建置本機Windows應用程式的頭檔;包括對MSVC執行時間的擴展,以支援C99功能。 MinGW的所有軟體都可以在64位元Windows平台上運作。

mPDF
mPDF是一個PHP庫,可以從UTF-8編碼的HTML產生PDF檔案。原作者Ian Back編寫mPDF以從他的網站上「即時」輸出PDF文件,並處理不同的語言。與原始腳本如HTML2FPDF相比,它的速度較慢,並且在使用Unicode字體時產生的檔案較大,但支援CSS樣式等,並進行了大量增強。支援幾乎所有語言,包括RTL(阿拉伯語和希伯來語)和CJK(中日韓)。支援嵌套的區塊級元素(如P、DIV),

Dreamweaver Mac版
視覺化網頁開發工具

PhpStorm Mac 版本
最新(2018.2.1 )專業的PHP整合開發工具

MantisBT
Mantis是一個易於部署的基於Web的缺陷追蹤工具,用於幫助產品缺陷追蹤。它需要PHP、MySQL和一個Web伺服器。請查看我們的演示和託管服務。