使用 Event 和 DIO 讀取串列埠
** 事件擴充套件當前無法識別 DIO 流。沒有乾淨的方法來獲取封裝在 DIO 資源中的檔案描述符。但有一個解決方法:
- 用
fopen()
開啟埠流; - 使用
stream_set_blocking()
使流無阻塞 ; - 使用
EventUtil::getSocketFd()
從流中獲取數字檔案描述符 ; - 將數字檔案描述符傳遞給
dio_fdopen()
(當前未記錄)並獲取 DIO 資源; - 新增一個帶有回撥的
Event
,用於監聽檔案描述符上的讀取事件; - 在回撥中排出可用資料並根據應用程式的邏輯對其進行處理。
dio.php
<?php
class Scanner {
protected $port; // port path, e.g. /dev/pts/5
protected $fd; // numeric file descriptor
protected $base; // EventBase
protected $dio; // dio resource
protected $e_open; // Event
protected $e_read; // Event
public function __construct ($port) {
$this->port = $port;
$this->base = new EventBase();
}
public function __destruct() {
$this->base->exit();
if ($this->e_open)
$this->e_open->free();
if ($this->e_read)
$this->e_read->free();
if ($this->dio)
dio_close($this->dio);
}
public function run() {
$stream = fopen($this->port, 'rb');
stream_set_blocking($stream, false);
$this->fd = EventUtil::getSocketFd($stream);
if ($this->fd < 0) {
fprintf(STDERR, "Failed attach to port, events: %d\n", $events);
return;
}
$this->e_open = new Event($this->base, $this->fd, Event::WRITE, [$this, '_onOpen']);
$this->e_open->add();
$this->base->dispatch();
fclose($stream);
}
public function _onOpen($fd, $events) {
$this->e_open->del();
$this->dio = dio_fdopen($this->fd);
// Call other dio functions here, e.g.
dio_tcsetattr($this->dio, [
'baud' => 9600,
'bits' => 8,
'stop' => 1,
'parity' => 0
]);
$this->e_read = new Event($this->base, $this->fd, Event::READ | Event::PERSIST,
[$this, '_onRead']);
$this->e_read->add();
}
public function _onRead($fd, $events) {
while ($data = dio_read($this->dio, 1)) {
var_dump($data);
}
}
}
// Change the port argument
$scanner = new Scanner('/dev/pts/5');
$scanner->run();
測試
在終端 A 中執行以下命令:
$ socat -d -d pty,raw,echo=0 pty,raw,echo=0
2016/12/01 18:04:06 socat[16750] N PTY is /dev/pts/5
2016/12/01 18:04:06 socat[16750] N PTY is /dev/pts/8
2016/12/01 18:04:06 socat[16750] N starting data transfer loop with FDs [5,5] and [7,7]
輸出可能不同。使用前幾行中的 PTY(特別是/dev/pts/5
和/dev/pts/8
)。
在終端 B 中執行上述指令碼。你可能需要 root 許可權:
$ sudo php dio.php
在終端 C 中,將字串傳送到第一個 PTY:
$ echo test > /dev/pts/8
輸出
string(1) "t"
string(1) "e"
string(1) "s"
string(1) "t"
string(1) "
"