以上是关于 Direct IO 的一个大略的理解,更详尽的阐明大家可以参考文末参考文档中第二条链接的内容并进行深入的学习。在 PHP 中,我们直接在 PECL 下载 Direct IO 扩展就可以按照扩展的正常安装办法进行安装利用。
创建写入文件既然是文件操作,那么我们首先还是来创建和写入一些文件数据。
$fd=dio_open("./test",O_RDWR|O_CREAT);echodio_write($fd,"ThisisTest.I'mZyBlog.Showmethemoney4i"),PHP_EOL;//43print_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 参数的意思是打开一个可读写文件,并且如果文件不存在的话,创建它。这两个常量是与 Linux 中干系的直接操作文件的常量对应的,在文末的链接中也可以看到关于这些常量的阐明。

写入操作也是同样的利用一个 dio_write() 就能够完成,它返回的内容是写入的内容长度,这里我们写入了 43 个字符。
dio_stat() 是返回当前文件句柄的一些信息,我们可以看到设备号 device 、uid 、 gid 、 atime 、 mtime 等一些信息,它们和我们在 Linux 中能够看到的信息类似,实在便是这个文件的一些大略的信息。
读取文件读取文件利用非常大略的利用一个函数就可以完成。
$fd=dio_open("./test",O_RDWR|O_CREAT);echodio_read($fd),PHP_EOL;//ThisisTest.I'mZyBlog.Showmethemoney4idio_close($fd);
dio_read() 函数还包含其余一个参数,可以按指定的字节长度读取内容,这个在后面我们还会看到干系的示例。
文件操作在文件的读取过程中,我们有可能只须要读取一部分的内容,或者从某一位置开始读取文件内容,下面的操作函数便是针对这两个方面进行操作的。
$fd=dio_open("./test",O_RDWR|O_CREAT);var_dump(dio_truncate($fd,20));//bool(true)echodio_read($fd),PHP_EOL;//ThisisTest.I'mZyBdio_seek($fd,3);echodio_read($fd),PHP_EOL;//sisTest.I'mZyBdio_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//ZyBdio_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/