2014年12月17日 星期三

減少PHP-Serial的I/O等待時間

繼前篇 用php透過usb和rs232串連控制MPU電路板
dummy.php:
echo "\ntime 0:".round(microtime(true) * 1000);
include 'PhpSerial.php';

echo "\ntime 1:".round(microtime(true) * 1000);
`stty -F /dev/ttyUSB0 raw speed 9600 -crtscts cs8 -parenb -cstopb`;
echo "\ntime 2:".round(microtime(true) * 1000);
// Let's start the class
$serial = new PhpSerial();
echo "\ntime 3:".round(microtime(true) * 1000);
// First we must specify the device. This works on both linux and windows (if
// your linux serial device is /dev/ttyS0 for COM1, etc)
$serial->deviceSet("/dev/ttyUSB0");
echo "\ntime 4:".round(microtime(true) * 1000);
// We can change the baud rate, parity, length, stop bits, flow control
$serial->confBaudRate(9600);
echo "\ntime 5:".round(microtime(true) * 1000);
$serial->confParity("none");
echo "\ntime 6:".round(microtime(true) * 1000);
$serial->confCharacterLength(8);
echo "\ntime 7:".round(microtime(true) * 1000);
$serial->confStopBits(1);
echo "\ntime 8:".round(microtime(true) * 1000);
$serial->confFlowControl("none");
echo "\ntime 9:".round(microtime(true) * 1000);
// Then we need to open it
$serial->deviceOpen();

// To write into
echo "\ntime A:".round(microtime(true) * 1000);
$serial->sendMessage("O(00,02,1)E");

測試:
$ time sudo php -n dummy.php ( -n 是不走php.ini的設定,因為我之前browscap.ini設定太肥會delay)

time 0:1418786501622
time 1:1418786501623
time 2:1418786501890
time 3:1418786501890
time 4:1418786501890
time 5:1418786502156
time 6:1418786502423
time 7:1418786502690
time 8:1418786502956
time 9:1418786503223
time A:1418786503223
time B:1418786504957 # 後面sleep了一秒,讓燈關掉
real    0m3.373s
user    0m0.007s
sys     0m0.003s

在 PHP-Serial API的底層,每叫一次function ( new PhpSerial()、$serial->deviceSet、$serial->confBaudRate )都會用stty去檢查一次,每次stty檢查都會在IO上delay 0.3秒,所以我們現在假設你的裝置都連結配置好,將多餘的設定和stty檢查拿掉

更改PhpSerial.php:
+++ b/PhpSerial.php
@@ -32,22 +32,27 @@ class PhpSerial
      * @var bool
      */
     public $autoFlush = true;
+    public $_check_stty = true;
 
     /**
      * Constructor. Perform some checks about the OS and setserial
      *
      * @return PhpSerial
      */
-    public function PhpSerial()
+    public function PhpSerial($param)
     {
+        $this->_check_stty = (isset($param['check_stty']))? $param['check_stty'] : $this->_check
         setlocale(LC_ALL, "en_US");
 
         $sysName = php_uname();
         if (substr($sysName, 0, 5) === "Linux") {
             $this->_os = "linux";
+            if (!$this->_check_stty) {
+                register_shutdown_function(array($this, "deviceClose"));
+                return false;
+            }
@@ -86,9 +91,12 @@ class PhpSerial
      */
     public function deviceSet($device)
     {
+        if (!$this->_check_stty) {
+            $this->_device = $device;
+            $this->_dState = SERIAL_DEVICE_SET;
+            return false;
+        }

修改dummy.php
echo "\ntime 0:".round(microtime(true) * 1000);
include 'PhpSerial.php';

echo "\ntime 1:".round(microtime(true) * 1000);
echo "\ntime 2:".round(microtime(true) * 1000);
$serial = new PhpSerial(array('check_stty'=> false));
echo "\ntime 3:".round(microtime(true) * 1000);
$serial->deviceSet("/dev/ttyUSB0");
echo "\ntime 4:".round(microtime(true) * 1000);
$serial->deviceOpen();

echo "\ntime A:".round(microtime(true) * 1000);
$serial->sendMessage("O(00,02,1)E");

測試:
$ time sudo php -n dummy.php

time 0:1418787683165
time 1:1418787683165
time 2:1418787683165
time 3:1418787683165
time 4:1418787683165
time A:1418787683166
time B:1418787684896 # 後面sleep了一秒,讓燈關掉
real    0m1.774s
user    0m0.000s
sys     0m0.007s



沒有留言:

張貼留言