Direct IO とは
Direct IO は、実際には Linux オペレーティング システムの概念です。ファイルストリームを直接操作することを意味しますが、なぜ直接と言われるのでしょうか?実際、オペレーティング システムがファイル操作を実行するとき、ディスク上のファイルを直接読み書きするのではなく、中間にページ キャッシュの層が存在します。これはキャッシュであるため、確かに一定のパフォーマンスの向上をもたらしますが、これは完全に絶対的なものではありません。直接操作では、この層のキャッシュ操作を無視して、ディスク上のファイルを直接読み書きします。ディスク (ソリッド ステート ドライブであっても) と CPU およびメモリの処理速度の間には大きなギャップがあることは誰もが知っていますが、このギャップを埋めるためにデフォルトのページ キャッシュが使用されます。ただし、ページ キャッシュは CPU の計算処理を増加させ、メモリを占有します。一方、直接処理にはこの問題はありませんが、相対的に言えば、その速度はキャッシュされたファイルの読み取り処理に匹敵しません。
上記は Direct IO について簡単に理解したものですが、より詳細な説明については、記事末尾の参考資料の 2 番目のリンクを参照して詳しく学習してください。 PHP では、Direct IO 拡張機能を PECL から直接ダウンロードし、拡張機能の通常のインストール方法に従ってインストールします。
ファイルの作成と書き込み
これはファイル操作なので、最初にファイル データを作成して書き込みましょう。
$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 シリーズ関数と同様に、ファイルを開くには dio_open() 関数を使用する必要があります。O_RDWR | O_CREAT パラメータは、読み書き可能なファイルを開き、ファイルが存在しない場合は作成することを意味します。 . .これら 2 つの定数は、Linux のファイルの直接操作に関連する定数に対応しており、記事の最後にあるリンクでこれらの定数の説明を参照できます。
書き込み操作は dio_write() を使用して完了することもできます。返される内容は、書き込まれた内容の長さです。ここでは 43 文字を書き込みました。
dio_stat() は、現在のファイル ハンドルに関する情報を返します。デバイス番号 device、uid、gid、atime、mtime などの情報が表示されます。これらは、Linux で表示される情報と似ています。 . 実際、これはこのファイルに関する簡単な情報です。
ファイルの読み取り
ファイルの読み取りは、関数を使用して非常に簡単に行うことができます。
$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() 関数には、指定されたバイト長に従ってコンテンツを読み取ることができる別のパラメーターも含まれています。関連する例は後で説明します。
ファイル操作
ファイルの読み取りプロセス中に、コンテンツの一部だけを読み取る必要がある場合や、ファイルのコンテンツを特定の位置から読み取り始める必要がある場合があります。次の操作関数は、これら 2 つの場合に使用します。側面が機能します。
$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 に指定すると、最初の 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() 関数は、C 関数ライブラリの fcntl 関数と呼ばれます。目的は、ファイル記述子に対して指定された操作を実行することです。この操作はいくつかの修正でも修正されていますはい、ここでは F_SETFL を使用します。これは、ファイル記述子フラグを指定された値に設定することを意味します。この O_SYNC は、この記述子が設定されている場合、ファイルの書き込み操作はデータが書き込まれるまで待機することを意味します。ディスクに保存されるまで終了します。もちろん、この関数は他の多くの演算子でも設定できますので、詳しくは PHP の公式ドキュメントを参照してください。
dio_tcsetattr() は、開いているファイルの端末属性とボーレートを設定するために使用されます。 baud はボーレートを表し、bits はビットを表し、stop はストップビットを表し、parity はパリティビットを表します。このあたりは「コンピュータの構成原理」や「オペレーティングシステム」の知識が必要ですが、私にはよく分からないので詳しい説明は省略します。ここからも大学の授業における基礎科目が非常に重要であることが分かりますが、この専門基礎科目を学んだ学生ならすぐにこの機能の役割を理解できると思います。
最後に、dio_read()の第二引数を使ってバイト長に応じてファイルの内容を読み込むと、読み取った内容が4文字単位でセグメント単位で出力されることが分かります。
总结
函数的学习还是比较简单的,核心的还是要知道这个扩展在什么业务场景下更适合使用。在文章开头的介绍中我们已经说明了直接操作文件与普通文件操作的一些区别,在自缓存应用或者需要传输非常大的数据时,直接操作对于 CPU 和 内存 更加地友好。而其它情况,我们还是使用系统默认的文件操作方式就可以了。其实在大部分情况下,我们基本看不出来它们的显著区别。所以在实际应用中,还是那句话,结合业务实际情况,选择最佳的方案。
测试代码: https://github.com/zhangyue0503/dev-blog/blob/master/php/202010/source/4.PHP中DirectIO直操作文件扩展的使用.php 参考文档: https://www.php.net/manual/zh/book.dio.php https://www.ibm.com/developerworks/cn/linux/l-cn-directio/
推荐学习:《PHP视频教程》