溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

PHP中怎么使用DirectIO

發(fā)布時間:2021-07-13 15:36:05 來源:億速云 閱讀:110 作者:chen 欄目:編程語言

本篇內容主要講解“PHP中怎么使用DirectIO”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“PHP中怎么使用DirectIO”吧!

關于PHP的文件操作,我們也將是通過一系列的文章來進行學習。今天我們先學習的是一個很少人使用過,甚至很多人根本不知道的擴展,它與我們日常的文件操作有些許的不同。不過這些差別并不是我們肉眼所能直觀看到的,主要還是在于業(yè)務的需求與性能的平衡。

什么是Direct IO

Direct IO 其實是 Linux 操作系統(tǒng)中的一個概念。它的意思是直接操作文件流,為什么說是直接呢?其實在我們的操作系統(tǒng)進行文件操作的時候,并不是馬上直接就在磁盤上進行文件的讀寫,中間還有一層頁緩存。

既然是緩存,那么它當然是會帶來一定的性能提升,但這也并不是完全絕對的。而直接操作就是忽略掉這一層的緩存操作,直接對磁盤上的文件進行讀寫。我們都知道,磁盤,即使是固態(tài)硬盤,它和 CPU 以及內存的處理速度之間都是有著巨大的落差的,默認的頁緩存就是用來彌補這種差距。

但是頁緩存會加大 CPU 的運算操作以及占用內存,而直接操作則不會有這種問題,但是相對來說,它的速度并不能和帶緩存的文件讀取操作相媲美。

以上是關于 Direct IO 的一個簡單的理解,更詳盡的解釋大家可以參考文末參考文檔中第二條鏈接的內容并進行深入的學習。在 PHP 中,我們直接在 PECL 下載 Direct IO 擴展就可以按照擴展的正常安裝方式進行安裝使用。

創(chuàng)建寫入文件

既然是文件操作,那么我們首先還是來創(chuàng)建和寫入一些文件數(shù)據(jù)。

$fd = dio_open("./test", O_RDWR | O_CREAT);

echo dio_write($fd, "This is Test.I'm ZyBlog.Show me the money4i"), PHP_EOL;
// 43

print_r(dio_stat($fd));
// Array
// (
//     [device] => 64768
//     [inode] => 652548
//     [mode] => 35432
//     [nlink] => 1
//     [uid] => 0
//     [gid] => 0
//     [device_type] => 0
//     [size] => 43
//     [block_size] => 4096
//     [blocks] => 8
//     [atime] => 1602643459
//     [mtime] => 1602656963
//     [ctime] => 1602656963
// )

dio_close($fd);

和 f 系列的函數(shù)類似,我們需要使用一個 dio_open() 函數(shù)來打開一個文件,O_RDWR | O_CREAT 參數(shù)的意思是打開一個可讀寫文件,并且如果文件不存在的話,創(chuàng)建它。這兩個常量是與 Linux 中相關的直接操作文件的常量對應的,在文末的鏈接中也可以看到關于這些常量的解釋。

寫入操作也是同樣的使用一個 dio_write() 就能夠完成,它返回的內容是寫入的內容長度,這里我們寫入了 43 個字符。

dio_stat() 是返回當前文件句柄的一些信息,我們可以看到設備號 device 、uid 、 gid 、 atime 、 mtime 等一些信息,它們和我們在 Linux 中能夠看到的信息類似,其實就是這個文件的一些簡單的信息。

讀取文件

讀取文件使用非常簡單的使用一個函數(shù)就可以完成。

$fd = dio_open("./test", O_RDWR | O_CREAT);

echo dio_read($fd), PHP_EOL;
// This is Test.I'm ZyBlog.Show me the money4i

dio_close($fd);

dio_read() 函數(shù)還包含另外一個參數(shù),可以按指定的字節(jié)長度讀取內容,這個在后面我們還會看到相關的示例。

文件操作

在文件的讀取過程中,我們有可能只需要讀取一部分的內容,或者從某一位置開始讀取文件內容,下面的操作函數(shù)就是針對這兩個方面進行操作的。

$fd = dio_open("./test", O_RDWR | O_CREAT);

var_dump(dio_truncate ($fd , 20)); 
// bool(true)
echo dio_read($fd), PHP_EOL;
// This is Test.I'm ZyB

dio_seek($fd, 3); 

echo dio_read($fd), PHP_EOL;
// s is Test.I'm ZyB

dio_close($fd);

其實從名稱就可以看出 dio_truncate() 就是用于截斷文件內容的。在這里我們從第 20 個字符進行截斷,然后再使用 dio_read() 讀取的內容就只是前 20 個字符的內容了。

dio_seek() 則是指定從哪一個字符開始讀取內容,我們指定開始字符位置為 3 之后,前面三個字符就不會被讀取到了。需要注意的是,dio_truncate() 會修改原始文件的內容,而 dio_seek() 則不會修改。

其它設置

$fd = dio_open('./test', O_RDWR | O_NOCTTY | O_NONBLOCK);

dio_fcntl($fd, F_SETFL, O_SYNC);

dio_tcsetattr($fd, array(
  'baud' => 9600,
  'bits' => 8,
  'stop'  => 1,
  'parity' => 0
));

while (($data = dio_read($fd, 4))!=false) {
    echo $data, PHP_EOL;
}
// This
//  is
// Test
// .I'm
//  ZyB

dio_close($fd);

dio_fcntl() 函數(shù)是調用的 c 函數(shù)庫中的 fcntl 函數(shù),目的是對文件描述符執(zhí)行指定的一些操作,這個操作也是以一些常量進行固定的,在這里我們使用的是 F_SETFL ,它的意思是將文件描述符標志設置為指定的值,這個 O_SYNC 表示的是如果設置了這個描述符,則對該文件的寫操盤會等到數(shù)據(jù)被寫到磁盤上才結束。當然,這個函數(shù)還可以設置很多別的操作符,大家可以參考 PHP 的官方文檔進行深入的學習。

dio_tcsetattr() 用于設置打開文件的終端屬性和波特率。 baud 表示的就是波特率,bits 表示的是位,stop 表示的是停止位,parity 表示的是奇偶校驗位。

關于這方面的內容需要 《計算機組成原理》 及 《操作系統(tǒng)》 中的一些知識,我也并不十分地清楚,所以也就不詳細的解釋了。從這里就可以看出,大學課堂上的那些基礎課程真的是非常地重要,相信好好學過這些專業(yè)基礎課程的同學一定能馬上明白這個函數(shù)的作用。

最后,我們在 dio_read() 中使用了第二個參數(shù)來根據(jù)字節(jié)長度讀取文件內容,可以看到讀取出來的內容是一段一段的以 4 個字符長度為單位的輸出。

總結

函數(shù)的學習還是比較簡單的,核心的還是要知道這個擴展在什么業(yè)務場景下更適合使用。在文章開頭的介紹中我們已經(jīng)說明了直接操作文件與普通文件操作的一些區(qū)別,在自緩存應用或者需要傳輸非常大的數(shù)據(jù)時,直接操作對于 CPU 和 內存 更加地友好。

而其它情況,我們還是使用系統(tǒng)默認的文件操作方式就可以了。其實在大部分情況下,我們基本看不出來它們的顯著區(qū)別。所以在實際應用中,還是那句話,結合業(yè)務實際情況,選擇最佳的方案。

測試代碼:

https://github.com/zhangyue0503/dev-blog/blob/master/php/202010/source/4.PHP中DirectIO直操作文件擴展的使用.php

到此,相信大家對“PHP中怎么使用DirectIO”有了更深的了解,不妨來實際操作一番吧!這里是億速云網(wǎng)站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續(xù)學習!

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權內容。

php
AI