PHP中DirectIO操作文件擴(kuò)展的用法大全
關(guān)于 PHP 的文件操作,我們也將是通過(guò)一系列的文章來(lái)進(jìn)行學(xué)習(xí)。今天我們先學(xué)習(xí)的是一個(gè)很少人使用過(guò),甚至很多人根本不知道的擴(kuò)展,它與我們?nèi)粘5奈募僮饔行┰S的不同。不過(guò)這些差別并不是我們?nèi)庋鬯苤庇^看到的,主要還是在于業(yè)務(wù)的需求與性能的平衡。
什么是Direct IO
Direct IO 其實(shí)是 Linux 操作系統(tǒng)中的一個(gè)概念。它的意思是直接操作文件流,為什么說(shuō)是直接呢?其實(shí)在我們的操作系統(tǒng)進(jìn)行文件操作的時(shí)候,并不是馬上直接就在磁盤上進(jìn)行文件的讀寫,中間還有一層頁(yè)緩存。既然是緩存,那么它當(dāng)然是會(huì)帶來(lái)一定的性能提升,但這也并不是完全絕對(duì)的。而直接操作就是忽略掉這一層的緩存操作,直接對(duì)磁盤上的文件進(jìn)行讀寫。我們都知道,磁盤,即使是固態(tài)硬盤,它和 CPU 以及內(nèi)存的處理速度之間都是有著巨大的落差的,默認(rèn)的頁(yè)緩存就是用來(lái)彌補(bǔ)這種差距。但是頁(yè)緩存會(huì)加大 CPU 的運(yùn)算操作以及占用內(nèi)存,而直接操作則不會(huì)有這種問(wèn)題,但是相對(duì)來(lái)說(shuō),它的速度并不能和帶緩存的文件讀取操作相媲美。
以上是關(guān)于 Direct IO 的一個(gè)簡(jiǎn)單的理解,更詳盡的解釋大家可以參考文末參考文檔中第二條鏈接的內(nèi)容并進(jìn)行深入的學(xué)習(xí)。在 PHP 中,我們直接在 PECL 下載 Direct IO 擴(kuò)展就可以按照擴(kuò)展的正常安裝方式進(jìn)行安裝使用。
創(chuàng)建寫入文件
既然是文件操作,那么我們首先還是來(lái)創(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ù)類似,我們需要使用一個(gè) dio_open() 函數(shù)來(lái)打開(kāi)一個(gè)文件,O_RDWR | O_CREAT 參數(shù)的意思是打開(kāi)一個(gè)可讀寫文件,并且如果文件不存在的話,創(chuàng)建它。這兩個(gè)常量是與 Linux 中相關(guān)的直接操作文件的常量對(duì)應(yīng)的,在文末的鏈接中也可以看到關(guān)于這些常量的解釋。
寫入操作也是同樣的使用一個(gè) dio_write() 就能夠完成,它返回的內(nèi)容是寫入的內(nèi)容長(zhǎng)度,這里我們寫入了 43 個(gè)字符。
dio_stat() 是返回當(dāng)前文件句柄的一些信息,我們可以看到設(shè)備號(hào) device 、uid 、 gid 、 atime 、 mtime 等一些信息,它們和我們?cè)?Linux 中能夠看到的信息類似,其實(shí)就是這個(gè)文件的一些簡(jiǎn)單的信息。
讀取文件
讀取文件使用非常簡(jiǎn)單的使用一個(gè)函數(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ù)還包含另外一個(gè)參數(shù),可以按指定的字節(jié)長(zhǎng)度讀取內(nèi)容,這個(gè)在后面我們還會(huì)看到相關(guān)的示例。
文件操作
在文件的讀取過(guò)程中,我們有可能只需要讀取一部分的內(nèi)容,或者從某一位置開(kāi)始讀取文件內(nèi)容,下面的操作函數(shù)就是針對(duì)這兩個(gè)方面進(jìn)行操作的。
$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);
其實(shí)從名稱就可以看出 dio_truncate() 就是用于截?cái)辔募?nèi)容的。在這里我們從第 20 個(gè)字符進(jìn)行截?cái)啵缓笤偈褂?dio_read() 讀取的內(nèi)容就只是前 20 個(gè)字符的內(nèi)容了。
dio_seek() 則是指定從哪一個(gè)字符開(kāi)始讀取內(nèi)容,我們指定開(kāi)始字符位置為 3 之后,前面三個(gè)字符就不會(huì)被讀取到了。需要注意的是,dio_truncate() 會(huì)修改原始文件的內(nèi)容,而 dio_seek() 則不會(huì)修改。
其它設(shè)置
$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ù)是調(diào)用的 c 函數(shù)庫(kù)中的 fcntl 函數(shù),目的是對(duì)文件描述符執(zhí)行指定的一些操作,這個(gè)操作也是以一些常量進(jìn)行固定的,在這里我們使用的是 F_SETFL ,它的意思是將文件描述符標(biāo)志設(shè)置為指定的值,這個(gè) O_SYNC 表示的是如果設(shè)置了這個(gè)描述符,則對(duì)該文件的寫操盤會(huì)等到數(shù)據(jù)被寫到磁盤上才結(jié)束。當(dāng)然,這個(gè)函數(shù)還可以設(shè)置很多別的操作符,大家可以參考 PHP 的官方文檔進(jìn)行深入的學(xué)習(xí)。
dio_tcsetattr() 用于設(shè)置打開(kāi)文件的終端屬性和波特率。 baud 表示的就是波特率,bits 表示的是位,stop 表示的是停止位,parity 表示的是奇偶校驗(yàn)位。關(guān)于這方面的內(nèi)容需要 《計(jì)算機(jī)組成原理》 及 《操作系統(tǒng)》 中的一些知識(shí),我也并不十分地清楚,所以也就不詳細(xì)的解釋了。從這里就可以看出,大學(xué)課堂上的那些基礎(chǔ)課程真的是非常地重要,相信好好學(xué)過(guò)這些專業(yè)基礎(chǔ)課程的同學(xué)一定能馬上明白這個(gè)函數(shù)的作用。
最后,我們?cè)?dio_read() 中使用了第二個(gè)參數(shù)來(lái)根據(jù)字節(jié)長(zhǎng)度讀取文件內(nèi)容,可以看到讀取出來(lái)的內(nèi)容是一段一段的以 4 個(gè)字符長(zhǎng)度為單位的輸出。
總結(jié)
函數(shù)的學(xué)習(xí)還是比較簡(jiǎn)單的,核心的還是要知道這個(gè)擴(kuò)展在什么業(yè)務(wù)場(chǎng)景下更適合使用。在文章開(kāi)頭的介紹中我們已經(jīng)說(shuō)明了直接操作文件與普通文件操作的一些區(qū)別,在自緩存應(yīng)用或者需要傳輸非常大的數(shù)據(jù)時(shí),直接操作對(duì)于 CPU 和 內(nèi)存 更加地友好。而其它情況,我們還是使用系統(tǒng)默認(rèn)的文件操作方式就可以了。其實(shí)在大部分情況下,我們基本看不出來(lái)它們的顯著區(qū)別。所以在實(shí)際應(yīng)用中,還是那句話,結(jié)合業(yè)務(wù)實(shí)際情況,選擇最佳的方案。
測(cè)試代碼:
參考文檔:
https://www.php.net/manual/zh/book.dio.php
https://www.ibm.com/developerworks/cn/linux/l-cn-directio/
到此這篇關(guān)于PHP中DirectIO直操作文件擴(kuò)展的使用的文章就介紹到這了,更多相關(guān)php擴(kuò)展的使用內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
ThinkPHP的模版中調(diào)用session數(shù)據(jù)的方法
這篇文章主要介紹了ThinkPHP的模版中調(diào)用session數(shù)據(jù)的方法,需要的朋友可以參考下2014-07-07php的array數(shù)組和使用實(shí)例簡(jiǎn)明教程(容易理解)
最近在教一個(gè)朋友php,他沒(méi)有其他語(yǔ)言的基礎(chǔ)。對(duì)array的理解和用法有些模糊。所以寫了個(gè)教程,需要的朋友可以參考下2014-03-03解決laravel-admin 自己新建頁(yè)面里 js 需要刷新一次的問(wèn)題
今天小編就為大家分享一篇解決laravel-admin 自己新建頁(yè)面里 js 需要刷新一次的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-10-10iOS自定義提示彈出框?qū)崿F(xiàn)類似UIAlertView的效果
最近在學(xué)習(xí)iOS開(kāi)發(fā),在牛刀小試的時(shí)候發(fā)現(xiàn)系統(tǒng)的UIAlertView有點(diǎn)不喜歡,然后就自己自定義了一個(gè)UIAlertView,基本上實(shí)現(xiàn)了系統(tǒng)的UIAlertView,可以根據(jù)項(xiàng)目的需求修改UIAlertView的顏色。有需要的朋友們可以參考借鑒,也可以多多指導(dǎo),下面來(lái)一起看看吧。2016-11-11Thinkphp搜索時(shí)首頁(yè)分頁(yè)和搜索頁(yè)保持條件分頁(yè)的方法
這篇文章主要介紹了Thinkphp搜索時(shí)首頁(yè)分頁(yè)和搜索頁(yè)保持條件分頁(yè)的方法,以兩種不同的方式詳細(xì)分析了實(shí)現(xiàn)搜索時(shí)分頁(yè)情況下保持搜索條件的方法,是非常具有實(shí)用價(jià)值的技巧,需要的朋友可以參考下2014-12-12關(guān)于laravel后臺(tái)模板laravel-admin select框的使用詳解
今天小編就為大家分享一篇關(guān)于laravel后臺(tái)模板laravel-admin select框的使用詳解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-10-10PHP實(shí)現(xiàn)的簡(jiǎn)單三角形、矩形周長(zhǎng)面積計(jì)算器分享
這篇文章主要介紹了PHP實(shí)現(xiàn)的簡(jiǎn)單三角形、矩形周長(zhǎng)面積計(jì)算器分享,本文的實(shí)現(xiàn)相對(duì)較簡(jiǎn)單,同時(shí)提供了代碼文件下載,需要的朋友可以參考下2014-11-11