[英]PHP won't open fifo for writing
我正在圍繞一個從命名文件獲取輸入的復雜二進制文件編寫一個小包裝器(在 PHP 7.0.33 中)。 由於這將處理機密,我不想將數據提交到文件系統,因此使用 FIFO 而不是傳統文件。 二進制文件將愉快地從 FIFO 中讀取其數據(使用 2 個 shell 會話進行測試 - 在其中一個我創建了 fifo 並啟動了二進制文件,在第二個中我將一個文件放入了 fifo)。
但是在 PHP 中,無論我指定 w、a 還是 c,對 fopen() 的調用都會阻塞
if (posix_mkfifo("myfifo", 0600)) {
$writer=fopen("myfifo", 'w'); // this blocks
`binary myfifo`;
fputs($writer, $mydata);
}
雖然如果沒有任何內容讀取數據,我希望寫入會阻塞,但我沒想到 fopen() 會阻塞。
它似乎確實可以使用“w +”工作(執行繼續,並且二進制文件啟動)但是二進制文件失敗了
QIODevice::read (QFile, "filename"): device not open
為了進一步調查,我為二進制文件編寫了一個簡單的替換。 當我將文件放入 FIFO 時,這同樣有效:
$in='';
$fh=fopen($argv[1],'r');
if (is_resource($fh)) {
print "File opened\n";
while (!feof($fh)) {
$in.=fgets($fh);
}
} else {
print "failed to open file\n";
}
file_put_contents("output", $in);
但是當我從 PHP 代碼寫入 FIFO 時......
fopen(import): failed to open stream: No such file or directory in ...
默認情況下,打開 FIFO 將阻塞,直到至少有一個讀寫器。 這樣做的理由是,如果沒有進程可以使用 kernel ,則沒有地方存儲 pipe 數據。 fifo的手冊頁:
... FIFO 特殊文件在文件系統上沒有內容,文件系統條目僅用作參考點,以便進程可以使用文件系統中的名稱訪問 pipe。
對於由至少一個進程打開的每個 FIFO 特殊文件,kernel 只維護一個 pipe object。 FIFO 必須在兩端(讀取和寫入)都打開,才能傳遞數據。 通常,打開 FIFO 會阻塞,直到另一端也打開。
不過,您可以繞過此行為。 一種方法就像您所做的那樣 - 通過自己打開讀寫端。 另一種是在打開文件時設置O_NONBLOCK
標志(您可以在之后將其設置回阻止)。 AFAIK 你不能用 fopen 做到這一點。 帶有dio
庫的示例:
<?php
echo "Opening\n";
$writer = dio_open("myfifo", O_CREAT | O_WRONLY | O_NONBLOCK) or die("Could not create FIFO\n");
echo "Open. Writing\n";
dio_write($writer, "DATA");
echo "Done\n";
這樣做的警告是,如果沒有讀取器,上述過程將寫入數據,然后立即退出,然后數據將永遠丟失。
為了任何在 Google 中找到這個問題並尋求比對 semisecure 的答案發表評論更詳細的解決方案的人的利益:
if (pcntl_fork()) {
`binary myfifo`;
} else {
$fh=fopen('myfifo', 'w');
fputs($fh, $data);
fclose($fh);
}
(但您可能還想在編寫器上添加一個 SIGALRM 以防“二進制”不執行/刷新管道)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.