Swoole筆記(四)

Process

Process是swoole內置的進程管理模塊,用來替代PHP的pcntl擴展。php

swoole_process支持重定向標準輸入和輸出,在子進程內echo不會打印屏幕,而是寫入管道,讀鍵盤輸入能夠重定向爲管道讀取數據。html

配合swoole_event模塊,建立的PHP子進程能夠異步的事件驅動模式。react

建立子進程

函數原型:git

int swoole_process::__construct(mixed $function, $redirect_stdin_stdout = false, $create_pipe = true);
  • $function,子進程建立成功後要執行的函數,底層會自動將函數保存到對象的callback屬性上。
  • 若是但願更改執行的函數,可賦值新的函數到對象的callback屬性。
  • $redirect_stdin_stdout,重定向子進程的標準輸入和輸出。啓用此選項後,在進程內echo將不是打印屏幕,而是寫入到管道。讀取鍵盤輸入將變爲從管道中讀取數據。默認爲阻塞讀取。
  • $create_pipe,是否建立管道,啓用$redirect_stdin_stdout後,此選項將忽略用戶參數,強制爲true 若是子進程內沒有進程間通訊,能夠設置爲false。
  • 1.7.22或更高版本容許設置管道的類型,默認爲SOCK_STREAM流式
    參數$create_pipe爲2時,管道類型將設置爲SOCK_DGRAM
<?php
$process = new swoole_process(function(swoole_process $worker){
    while (true){
        $cmd = $worker->read();
        passthru($cmd);
    }   
}, true, 2);
$process->start();

$process->write('ls -l');//將參數傳入子進程內
echo $data = $process->read();//獲取執行結果

實例:web版本的shell
https://github.com/52fhy/swoole_demo/blob/master/swoole_shell_server.phpgithub

EventLoop

swoole還提供了直接操做底層epoll/kqueue事件循環的接口。可將其餘擴展建立的socket,PHP代碼中stream/socket擴展建立的socket等加入到Swoole的EventLoop中。web

swoole_event_add函數用於將一個socket加入到swoole的reactor事件監聽中。 函數原型:shell

bool swoole_event_add(int $sock, mixed $read_callback, mixed $write_callback = null, int `$flags` = null);
  • $sock支持文件描述符、stream資源、sockets資源。
  • $read_callback爲可讀回調函數。
  • $write_callback爲可寫事件回調。
  • $flags爲事件類型的掩碼,可選擇關閉/開啓可讀可寫事件,如SWOOLE_EVENT_READSWOOLE_EVENT_WRITE,或者SWOOLE_EVENT_READ | SWOOLE_EVENT_WRITE

在Server程序中使用,能夠理解爲在worker/taskworker進程中將此socket註冊到epoll事件中。swoole

在Client程序中使用,能夠理解爲在客戶端進程中將此socket註冊到epoll事件中。異步

示例:socket

<?php
$fp = stream_socket_client("tcp://www.52fhy.com:80", $errno, $errstr, 30);
fwrite($fp, "GET / HTTP/1.1\r\nHost: www.52fhy.com\r\n\r\n");

swoole_event_add($fp, function($fp) {

    echo $resp = fread($fp, 1024);
    //socket處理完成後,從epoll事件中移除socket
    swoole_event_del($fp);
    fclose($fp);
});
echo "Finish\n";  //swoole_event_add不會阻塞進程,這行代碼會順序執行

對比一下,下面這個會阻塞進程:

<?php
$fp  =  stream_socket_client ( "tcp://www.52fhy.com:80" ,  $errno ,  $errstr ,  30 );
if (! $fp ) {
    echo  " $errstr  ( $errno )<br />\n" ;
} else {
     fwrite ( $fp ,  "GET / HTTP/1.1\r\nHost: www.52fhy.com\r\n\r\n" );
    while (! feof ( $fp )) {
        echo  fgets ( $fp ,  1024 );
    }
     fclose ( $fp );
}

echo "Finish\n";
相關文章
相關標籤/搜索