Ⅰ php多線程
以下都是轉載, 簡單說下, php是不支持多線程的。。。。
PHP語言本身是不支持多線程的. 總結了一下網上關於PHP模擬多線程的方法, 總的來說, 都是利用了PHP的好夥伴們本身所具有的多線程能力. PHP的好夥伴指的就是linux和APACHE啦, LAMP嘛.
另外, 既然是模擬的, 就不是真正的多線程. 其實只是多進程. 進程和線程是兩個不同的概念. 好了, 以下方法都是從網上找來的.
1. 利用LINUX操作系統
<?php
for ($i=0;$i<10;$i++) {
echo $i;
sleep(5);
}
?>
上面存成test.php, 然後寫一段SHELL代碼
#!/bin/bash
for i in 1 2 3 4 5 6 7 8 9 10
do
php -q test.php &
done
2. 利用fork子進程(其實同樣是利用LINUX操作系統)
<?php
declare(ticks=1);
$bWaitFlag = FALSE; /// 是否等待進程結束
$intNum = 10; /// 進程總數
$pids = array(); /// 進程PID數組
echo ("Startn");
for($i = 0; $i < $intNum; $i++) {
$pids[$i] = pcntl_fork();/// 產生子進程,而且從當前行之下開試運行代碼,而且不繼承父進程的數據信息
if(!$pids[$i]) {
// 子進程進程代碼段_Start
$str="";
sleep(5+$i);
for ($j=0;$j<$i;$j++) {$str.="*";}
echo "$i -> " . time() . " $str n";
exit();
// 子進程進程代碼段_End
}
}
if ($bWaitFlag)
{
for($i = 0; $i < $intNum; $i++) {
pcntl_waitpid($pids[$i], $status, WUNTRACED);
echo "wait $i -> " . time() . "n";
}
}
echo ("Endn");
?>
3. 利用WEB SERVER, PHP不支持多線程, APACHE可是支持的, 呵呵.
假設我們現在運行的是a.php這個文檔. 但是我在程式中又請求WEB伺服器運行另一個b.php
那麼這兩個文檔將是同時執行的.
<?php
function runThread()
{
$fp = fsockopen('localhost', 80, $errno, $errmsg);
fputs($fp, "GET /a.php?act=brnrn");
fclose($fp);
}
function a()
{
$fp = fopen('result_a.log', 'w');
fputs($fp, 'Set in ' . Date('h:i:s', time()) . (double)microtime() . "rn");
fclose($fp);
}
function b()
{
$fp = fopen('result_b.log', 'w');
fputs($fp, 'Set in ' . Date('h:i:s', time()) . (double)microtime() . "rn");
fclose($fp);
}
if(!isset($_GET['act'])) $_GET['act'] = 'a';
if($_GET['act'] == 'a')
{
runThread();
a();
}
else if($_GET['act'] == 'b') b();
?>
當然啦,也可以把需要多線程處理的部分交給java去處理, 然後在PHP里調用, 哈哈.
<?php
system('java multiThread.java');
?>
Ⅱ php-fpm的工作機制
概括來說,fpm 的實現就是創建一個 master 進程,在 master 進程中創建並監聽 socket,然後 fork 出多個子進程,這些子進程各自 accept 請求,子進程的處理非常簡單,它在啟動後阻塞在 accept 上,有請求到達後開始讀取請求數據,讀取完成後開始處理然後再返回,在這期間是不會接收其它請求的,也就是說 fpm 的子進程同時只能響應一個請求,只有把這個請求處理完成後才會 accept 下一個請求,這一點與 nginx 的事件驅動有很大的區別,nginx 的子進程通過 epoll 管理套接字,如果一個請求數據還未發送完成則會處理下一個請求,即一個進程會同時連接多個請求,它是非阻塞的模型,只處理活躍的套接字。
fpm 的 master 進程與 worker 進程之間不會直接進行通信,master 通過共享內存獲取 worker 進程的信息,比如 worker 進程當前狀態、已處理請求數等,當 master 進程要殺掉一個 worker 進程時則通過發送信號的方式通知 worker 進程。
fpm 可以同時監聽多個埠,每個埠對應一個 worker pool,而每個 pool 下對應多個 worker 進程,類似 nginx 中 server 概念。
在 php-fpm.conf 中通過[pool name]聲明一個 worker pool:
啟動 fpm 後查看進程:
具體實現上 worker pool 通過fpm_worker_pool_s這個結構表示,多個 worker pool 組成一個單鏈表
接下來看下 fpm 的啟動流程,從main()函數開始:
fpm_init()主要有以下幾個關鍵操作:
(1) fpm_conf_init_main():
解析 php-fpm.conf 配置文件,分配 worker pool 內存結構並保存到全局變數中:fpm_worker_all_pools,各 worker pool 配置解析到fpm_worker_pool_s->config中。
(2)fpm_scoreboard_init_main():
分配用於記錄 worker 進程運行信息的共享內存,按照 worker pool 的最大 worker 進程數分配,每個 worker pool 分配一個fpm_scoreboard_s結構,pool 下對應的每個 worker 進程分配一個fpm_scoreboard_proc_s結構。
(3)fpm_signals_init_main():
這里會通過socketpair()創建一個管道,這個管道並不是用於 master 與 worker 進程通信的,它只在 master 進程中使用,具體用途在稍後介紹 event 事件處理時再作說明。另外設置 master 的信號處理 handler,當 master 收到 SIGTERM、SIGINT、SIGUSR1、SIGUSR2、SIGCHLD、SIGQUIT 這些信號時將調用sig_handler()處理:
(4)fpm_sockets_init_main()
創建每個 worker pool 的 socket 套接字。
(5)fpm_event_init_main():
啟動 master 的事件管理,fpm 實現了一個事件管理器用於管理 IO、定時事件,其中 IO 事件通過 kqueue、epoll、poll、select 等管理,定時事件就是定時器,一定時間後觸發某個事件。
在fpm_init()初始化完成後接下來就是最關鍵的fpm_run()操作了,此環節將 fork 子進程,啟動進程管理器,另外 master 進程將不會再返回,只有各 worker 進程會返回,也就是說fpm_run()之後的操作均是 worker 進程的。
在 fork 後 worker 進程返回了監聽的套接字繼續 main() 後面的處理,而 master 將永遠阻塞在fpm_event_loop(),接下來分別介紹 master、worker 進程的後續操作。
fpm_run()執行後將 fork 出 worker 進程,worker 進程返回main()中繼續向下執行,後面的流程就是 worker 進程不斷 accept 請求,然後執行 PHP 腳本並返回。整體流程如下:
worker 進程一次請求的處理被劃分為 5 個階段:
worker 處理到各個階段時將會把當前階段更新到fpm_scoreboard_proc_s->request_stage,master 進程正是通過這個標識判斷 worker 進程是否空閑的。
接下來我們來看下 master 是如何管理 worker 進程的,首先介紹下三種不同的進程管理方式:
前面介紹到在fpm_run()中 master 進程將進入fpm_event_loop():
這就是 master 整體的處理,其進程管理主要依賴注冊的幾個事件,接下來我們詳細分析下這幾個事件的功能。
(1)sp[1]管道可讀事件:
在 fpm_init() 階段 master 曾創建了一個全雙工的管道:sp,然後在這里創建了一個 sp[0] 可讀的事件,當 sp[0] 可讀時將交由 fpm_got_signal() 處理,向 sp[1] 寫數據時 sp[0] 才會可讀,那麼什麼時機會向 sp[1] 寫數據呢?前面已經提到了:當 master 收到注冊的那幾種信號時會寫入 sp[1] 端,這個時候將觸發 sp[0] 可讀事件。
這個事件是 master 用於處理信號的,我們根據 master 注冊的信號逐個看下不同用途:
具體處理邏輯在 fpm_got_signal() 函數中,這里不再羅列。
(2)fpm_pctl_perform_idle_server_maintenance_heartbeat():
這是進程管理實現的主要事件,master 啟動了一個定時器,每隔 1s 觸發一次,主要用於 dynamic、ondemand 模式下的 worker 管理,master 會定時檢查各 worker pool 的 worker 進程數,通過此定時器實現 worker 數量的控制,處理邏輯如下:
(3)fpm_pctl_heartbeat():
這個事件是用於限制 worker 處理單個請求最大耗時的,php-fpm.conf 中有一個request_terminate_timeout的配置項,如果 worker 處理一個請求的總時長超過了這個值那麼 master 將會向此 worker 進程發送kill -TERM信號殺掉 worker 進程,此配置單位為秒,默認值為 0 表示關閉此機制,另外 fpm 列印的 slow log 也是在這里完成的。
除了上面這幾個事件外還有一個沒有提到,那就是 ondemand 模式下 master 監聽的新請求到達的事件,因為 ondemand 模式下 fpm 啟動時是不會預創建 worker 的,有請求時才會生成子進程,所以請求到達時需要通知 master 進程,這個事件是在fpm_children_create_initial()時注冊的,事件處理函數為fpm_pctl_on_socket_accept(),具體邏輯這里不再展開,比較容易理解。
原文出處: https://www.fanhao.com/2017/10/internal-php-fpm.html
Ⅲ php中pcntl_fork是什麼意思,pcntl_fork創建子進程如何進行的
一、php中pcntl_fork函數概述
pcntl_fork()函數是php中用於創建子進程的一個函數,返回創建的子進程的pid。
該函數創建子進程具體fork的過程:
(1)調用該函數即創建一個子進程,創建成功父進程返回子進程的pid,子進程返回0;
(2)創建子進程實際上對父進程的一個拷貝,共享代碼空間,拷貝父進程的數據,也就是說父進程改變父進程的數據,子進程改變子進程
二、示例代碼分析
1.代碼示例:
<?php
$curr_pid=posix_getpid();//獲取當前的進程id
//將當前進程的id寫入文件中
echo'當前進程:'.$curr_pid.PHP_EOL;
//開始創建子進程
$son_pid=pcntl_fork();//返回子進程的id
//查看當前進程
echo'創建子進程之後當前的進程為:'.posix_getpid().PHP_EOL;
//創建了子進程之後
if($son_pid>0){
echo'子進程id:'.$son_pid.PHP_EOL;
}
2.以上代碼執行後結果為:
3.示例代碼分析:
(1)發現創建了子進程之後,系統會切換到子進程中,而子進程中的代碼是從含有pcntl_fork函數的那行執行的
(2)創建子進程之後,子進程的代碼段是拷貝pcntl_fork函數及之後的代碼段,之前的代碼段並不拷貝,但是具體的數據變數子進程仍然會拷貝
(3)可見,fork之後程序會分叉執行,即子進程執行
三、pcntl_fork的業務場景舉例
1.php的多進程中,常用pcntl_fork來實現並發,多用於一些簡單工具的實現。
2.例如監控工具,想要監控幾個不同指標的情形,可以使用主進程監控各指標的配置變化,然後對每個指標分別fork一個子進程來監控其具體的情形,當主進程發現指標的配置改變則kill掉之前的子進程重新創建子進程進行監控。
3.主進程進行業務分發操作,子進程進行具體的業務邏輯執行。(BY三人行慕課)
Ⅳ php fpm 進程數和並發數是什麼關系
首先,需要預估項目在生產環境能有多少並發產生,根據預估設置初始fpm進程數配置,具體可以參考PHP文檔
對於FPM的監控
建議開啟php-fpm.conf中pm.status_path設置,可以通過url請求獲取當前時刻fpm的進程狀態,支持html,josn,xml等數據格式返回,結合定時任務,可以做成一個fpm狀態監控,通過url獲取的數據中,'listen queue' 表示請求等待隊列,這個參數如果不為0,就表示當前進程數被使用完了,新的請求過來必須進入等待隊列,所以,通過這個參數,就可以判斷是否應該增加進程數或加強伺服器配置
Ⅳ 用php程序自動讀取遠程文件並更新到本地,每天一次,如何做
windows:
准備:
1.將 php.exe 的路徑加入 windows 的環境變數
2.編寫文件:
D:\fileGeter.php
<?php
$filelist = Array(
"http://**********/a.txt",
"http://**********/b.txt",
);
$saveas="D:\\" ;
$endl = ".txt"
function getfile(){
foreach( $filelist as $k => $file )
file_put_contents( $saveas . $k . $endl , file_get_contents( $file ) ) ;
}
getfile();
?>
3.執行cmd命令
at 11:20 /every:1,2,3,4,5,6,7 "php D:\fileGeter.php"
linux 更方便
直接把此文件包含進 你要寫的程序里就OK了,
fileGeter.php:
<?php
...
...
$saveas = "./";
...
..
?>
index.php:
<?php
require_once("fileGeter.php");
//and so on .....
.....
....
....
?>
Ⅵ 如何從php程序讀取pdf文檔中的文本信息
PHP程序pdf格式文件函數庫
本函數庫共有65個函數
PDF是Adobe所發展的可攜式文件格式,它的文件可以在網路上傳輸、瀏覽,甚至使用印表機印出,或使用其它輸出裝置輸出,都可以保存原來的文字及圖片的編排。詳細的信息可以參考 Adobe 的網站。參考其中有關 PDF 或 Acrobat 的部份。
在 UNIX 系統中,可以使用 Thomas Merz 開發的 PDF 函數庫。將它編譯安裝完成後,再編譯 PHP 程序方可供 PHP 使用 pdflib。編譯時可能要 JPEG library 及 TIFF library。
除了用這個函數庫可以建立 PDF 文件外,FastIO 公司發展的產品 ClibPDF 也可以處理 PDF 文件。
以下為處理 PDF 文件的範例,本例對 test.pdf 加工後等待用戶讀取。
<?php
$fp = fopen("test.pdf", "w");
$pdf = PDF_open($fp);
pdf_set_info_author($pdf, "Uwe Steinmann");
PDF_set_info_title($pdf, "Test for PHP wrapper of PDFlib 2.0");
PDF_set_info_author($pdf, "Name of Author");
pdf_set_info_creator($pdf, "See Author");
pdf_set_info_subject($pdf, "Testing");
PDF_begin_page($pdf, 595, 842);
PDF_add_outline($pdf, "Page 1");
pdf_set_font($pdf, "Times-Roman", 30, 4);
pdf_set_text_rendering($pdf, 1);
PDF_show_xy($pdf, "Times Roman outlined", 50, 750);
pdf_moveto($pdf, 50, 740);
pdf_lineto($pdf, 330, 740);
pdf_stroke($pdf);
PDF_end_page($pdf);
PDF_close($pdf);
fclose($fp);
echo "<A HREF=getpdf.php3>finished</A>";
?>
上例中的 gettest.php3 可能像下面的樣子
<?php
$fp = fopen("test.pdf", "r");
header("Content-type: application/pdf");
fpassthru($fp);
fclose($fp);
?>
PDF_get_info: 返迴文件信息。
PDF_set_info_creator: 配置建檔者字元串。
PDF_set_info_title: 配置文件標題。
PDF_set_info_subject: 配置文件主題。
PDF_set_info_keywords: 配置文件的關鍵字。
PDF_set_info_author: 配置文件作者。
PDF_open: 建立新的 PDF 檔。
PDF_close: 關閉 PDF 檔。
PDF_begin_page: 啟始 PDF 文件頁面。
PDF_end_page: 關閉 PDF 文件頁面。
PDF_show: 輸出字元串到 PDF 文件。
PDF_show_xy: 輸出字元串到指定坐標。
PDF_set_font: 配置使用的字型及大小。
PDF_set_leading: 配置行距。
PDF_set_text_rendering: 配置文字表現方式。
PDF_set_horiz_scaling: 配置文字水平間距。
PDF_set_text_rise: 配置文字高度。
PDF_set_text_matrix: 配置文字矩陣。
PDF_set_text_pos: 配置文字位置。
PDF_set_char_spacing: 配置字元間距。
PDF_set_word_spacing: 配置字間距。
PDF_continue_text: 輸出文字。
PDF_stringwidth: 計算字元串的寬度。
PDF_save: 儲存環境變數。
PDF_restore: 還原環境變數。
PDF_translate: 移動原點。
PDF_scale: 縮放類。
PDF_rotate: 旋轉類。
PDF_setflat: 配置平滑值。
PDF_setlinejoin: 配置連接參數。
PDF_setlinecap: 配置 linecap 參數。
PDF_setmiterlimit: 配置斜邊界限。
PDF_setlinewidth: 配置線寬。
PDF_setdash: 配置虛線樣式。
PDF_moveto: 配置處理的坐標點。
PDF_curveto: 繪貝氏曲線。
PDF_lineto: 繪直線。
PDF_circle: 繪圓。
PDF_arc: 繪弧。
PDF_rect: 繪長方形。
PDF_closepath: 形成封閉的向量形狀。
PDF_stroke: 沿向量繪線。
PDF_closepath_stroke: 形成封閉的向量形狀並沿向量繪線。
PDF_fill: 填滿目前的向量。
PDF_fill_stroke: 填滿目前的向量並沿向量繪線。
PDF_closepath_fill_stroke: 形成封閉的向量形狀沿向量繪線並填滿。
PDF_endpath: 關閉目前向量。
PDF_clip: 組合所有向量。
PDF_setgray_fill: 指定填入的顏色為灰階。
PDF_setgray_stroke: 指定繪圖的顏色為灰階。
PDF_setgray: 指定繪圖的顏色為灰階並填入。
PDF_setrgbcolor_fill: 指定填入的顏色為彩色。
PDF_setrgbcolor_stroke: 指定繪圖的顏色為彩色。
PDF_setrgbcolor: 指定繪圖的顏色為彩色並填入。
PDF_add_outline: 目前頁面加入書簽。
PDF_set_transition: 配置頁的轉換。
PDF_set_ration: 配置二頁的切換時間。
PDF_open_gif: 打開 GIF 圖檔。
PDF_open_memory_image: 打開內存圖檔。
PDF_open_jpeg: 打開 JPEG 圖檔。
PDF_close_image: 關閉圖檔。
PDF_place_image: 放置圖片到 PDF 檔指定位置。
PDF_put_image: 放置圖片到 PDF 檔。
PDF_execute_image: 放置 PDF 檔中圖片到指定位置。
PDF_add_annotation: 加入注釋。
Ⅶ 易語言中,取運行目錄命令,取的是什麼目錄那取當前目錄命令呢兩個有什麼區別
易語言取運行目錄,是取得正在程序正在運行的目錄,比如保存在桌面,他就會取得桌面的路徑。操作方法如下:
1、首先打開易語言新建一個windows程序,進入下圖界面。