PHP扩展开发及内核应用第十四章第一节

全文共字,阅读需要11分钟

14流式访问

PHP用户空间中所有的文件I/O处理都是通过php4.3引入的PHP流包装层处理的。在内部,扩展代码可以选择使用stdio或posix文件处理和本地文件系统或伯克利域套接字进行通信,或者也可以调用和用户空间流I/O相同的API。

14.1流的概览

通常,直接的文件描述符相比调用流包装层消耗更少的CPU和内存;然而,这样会将实现某个特定协议的所有工作都堆积到作为扩展开发者的你身上.通过挂钩到流包装层,你的扩展代码可以透明的使用各种内建的流包装,比如HTTP,FTP,以及它们对应的SSL版本,另外还有gzip和bzip2压缩包装.通过include特定的PEAR或PECL模块,你的代码还可以访问其他协议,比如SSH2,WebDav,甚至是Gopher!

本章将介绍内部基于流工作的基础API.后面到第16章”有趣的流”中,我们将看到诸如应用过滤器,使用上下文选项和参数等高级概念.

打开流

尽管是一个统一的API,但实际上依赖于所需的流的类型,有四种不同的路径去打开一个流.从用户空间角度来看,这四种不同的类别如下(函数列表只代表示例,不是完整列表):

?PHP/*fopen包装*操作文件/URI方式指定远程文件类资源*/$fp=fopen($url,$mode);$data=file_get_contents($url);file_put_contents($url,$data);$lines=file($url);/*传输*基于套接字的顺序I/O*/$fp=fsockopen($host,$port);$fp=stream_socket_client($uri);$fp=stream_socket_server($uri,$options);/*目录流*/$dir=opendir($url);$files=scandir($url);$obj=dir($url);/*"特殊"的流*/$fp=tmpfile();$fp=popen($cmd);proc_open($cmd,$pipes);

无论你打开的是什么类型的流,它们都存储在一个公共的结构体PHP_stream中.

fopen包装

我们首先从实现fopen()函数开始.现在你应该已经对创建扩展骨架很熟悉了,如果还不熟悉,请回到第5章”你的第一个扩展”复习一下,下面是我们实现的fopen()函数:

PHP_FUNCTION(sample5_fopen){PHP_stream*stream;char*path,*mode;intpath_len,mode_len;intoptions=ENFORCE_SAFE_MODE

REPORT_ERRORS;if(zend_parse_parameters(ZEND_NUM_ARGS()TSRMLS_CC,"ss",path,path_len,mode,mode_len)==FAILURE){return;}stream=php_stream_open_wrapper(path,mode,options,NULL);if(!stream){RETURN_FALSE;}PHP_stream_to_zval(stream,return_value);}

PHP_stream_open_wrapper()的目的应该是完全绕过底层.path指定要读写文件名或URL,读写行为依赖于mode的值.

options是位域的标记值集合,这里是设置为下面介绍的一组固定值:

USE_PATH将php.ini文件中的include_path应用到相对路径上.内建函数fopen()在指定第三个参数为TRUE时将会设置这个选项.STREAM_USE_URL设置这个选项后,将只能打开远端URL.对于php://,file://,zlib://,bzip2://这些URL包装器并不认为它们是远端URL.ENFORCE_SAFE_MODE尽管这个常量这样命名,但实际上设置这个选项后仅仅是启用了安全模式(PHP.ini文件中的safe_mode指令)的强制检查.如果没有设置这个选项将导致跳过safe_mode的检查(不论INI设置中safe_mode如何设置)REPORT_ERRORS在指定的资源打开过程中碰到错误时,如果设置了这个选项则将产生错误报告.STREAM_MUST_SEEK对于某些流,比如套接字,是不可以seek的(随机访问);这类文件句柄,只有在特定情况下才可以seek.如果调用作用域指定这个选项,并且包装器检测到它不能保证可以seek,将会拒绝打开这个流.STREAM_WILL_CAST如果调用作用域要求流可以被转换到stdio或posix文件描述符,则应该给open_wrapper函数传递这个选项,以保证在I/O操作发生之前就失败STREAM_ONLY_GET_HEADERS标识只需要从流中请求元数据.实际上这是用于







































北京治疗白癜风那好
北京中科白癜风医院路线



转载请注明:http://www.guyukameng.com/aspnet/2016-11-24/1771.html