<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                # 15.1 php流的表象之下 # 15.1 php流的表象之下 對于給定的流實例, 比如文件流和網絡流, 它們的不同在于上一章你使用的流創建函數返回的php\_stream結構體中的ops成員. ``` typedef struct _php_stream { ... php_stream_ops *ops; ... } php_stream; ``` php\_stream\_ops結構體定義的是一個函數指針集合以及一個描述標記. ``` typedef struct _php_stream_ops { size_t (*write)(php_stream *stream, const char *buf, size_t count TSRMLS_DC); size_t (*read)(php_stream *stream, char *buf, size_t count TSRMLS_DC); int (*close)(php_stream *stream, int close_handle TSRMLS_DC); int (*flush)(php_stream *stream TSRMLS_DC); const char *label; int (*seek)(php_stream *stream, off_t offset, int whence, off_t *newoffset TSRMLS_DC); int (*cast)(php_stream *stream, int castas, void **ret TSRMLS_DC); int (*stat)(php_stream *stream, php_stream_statbuf *ssb TSRMLS_DC); int (*set_option)(php_stream *stream, int option,int value, void *ptrparam TSRMLS_DC); } php_stream_ops; ``` 當流訪問函數比如php\_stream\_read()被調用時, 流包裝層實際上解析調用了stream->ops中對應的函數, 這樣實際調用的就是當前流類型特有的read實現. 比如, 普通文件的流ops結構體中的read函數實現如下(實際的該實現比下面的示例復雜一點): ``` size_t php_stdio_read(php_stream *stream, char *buf, size_t count TSRMLS_DC) { php_stdio_stream_data *data = (php_stdio_stream_data*)stream->abstract; return read(data->fd, buf, count); } ``` 而compress.zlib流使用的ops結構體中則read則指向的是如下的函數: ``` size_t php_zlib_read(php_stream *stream, char *buf, size_t count TSRMLS_DC) { struct php_gz_stream_data_t *data = (struct php_gz_stream_data_t *) stream->abstract; return gzread(data->gz_file, buf, count); } ``` 這里第一點需要注意的是ops結構體指向的函數指針常常是對數據源真正的讀取函數的一個瘦代理. 在上面兩個例子中, 標準I/O流使用posix的read()函數, 而zlib流使用的是libz的gzread()函數. 你可能還注意到了, 這里使用了stream->abstract元素. 這是流實現的一個便利指針, 它可以被用于獲取各種相關的捆綁信息. 在上面的例子中, 指向自定義結構體的指針, 用于存儲底層read函數要使用的文件描述符. 還有一件你可能注意到的事情是php\_stream\_ops結構體中的每個函數都期望一個已有的流實例, 但是怎樣得到實例呢? abstract成員是怎樣設置的以及什么時候流指示使用哪個ops結構體? 答案就在你在上一章使用過的第一個打開流的函數(php\_stream\_open\_wrapper())中. 當這個函數被調用時, php的流包裝層嘗試基于傳遞的URL中的scheme://部分確定請求的是什么協議. 這樣它就可以在已注冊的php包裝器中查找對應的php\_stream\_wrapper項. 每個php\_stream\_wrapper結構體都可以取到自己的ops元素, 它指向一個php\_stream\_wrapper\_ops結構體: ``` typedef struct _php_stream_wrapper_ops { php_stream *(*stream_opener)(php_stream_wrapper *wrapper, char *filename, char *mode, int options, char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC); int (*stream_closer)(php_stream_wrapper *wrapper, php_stream *stream TSRMLS_DC); int (*stream_stat)(php_stream_wrapper *wrapper, php_stream *stream, php_stream_statbuf *ssb TSRMLS_DC); int (*url_stat)(php_stream_wrapper *wrapper, char *url, int flags, php_stream_statbuf *ssb, php_stream_context *context TSRMLS_DC); php_stream *(*dir_opener)(php_stream_wrapper *wrapper, char *filename, char *mode, int options, char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC); const char *label; int (*unlink)(php_stream_wrapper *wrapper, char *url, int options, php_stream_context *context TSRMLS_DC); int (*rename)(php_stream_wrapper *wrapper, char *url_from, char *url_to, int options, php_stream_context *context TSRMLS_DC); int (*stream_mkdir)(php_stream_wrapper *wrapper, char *url, int mode, int options, php_stream_context *context TSRMLS_DC); int (*stream_rmdir)(php_stream_wrapper *wrapper, char *url, int options, php_stream_context *context TSRMLS_DC); } php_stream_wrapper_ops; ``` 這里, 流包裝層調用wrapper->ops->stream\_opener(), 它將執行包裝器特有的操作創建流實例, 賦值恰當的php\_stream\_ops結構體, 綁定相關的抽象數據. dir\_opener()函數和stream\_opener()提供相同的基礎服務; 不過, 它是對php\_stream\_opendir()這個API調用的響應, 并且通常會綁定一個不同的php\_stream\_ops結構體到返回的實例. stat()和close()函數在這一層上是重復的, 這樣做是為了給包裝器的這些操作增加協議特有的邏輯. 其他的函數則允許執行靜態流操作而不用實際的創建流實例. 回顧這些流API調用, 它們并不實際返回php\_stream對象, 你馬上就會看到它們的細節. > 盡管在php 4.3中引入流包裝層時, url\_stat在內部作為一個包裝器的ops函數存在, 但直到php 5.0它才開始被使用. 此外, 最后的3個函數, rename(), stream\_mkdir()以及stream\_rmdir()一直到php 5.0才引入, 在這個版本之前, 它們并不在包裝器的ops結構中. ## links - [目錄](preface.md) - 15 [流的實現](15.html) - 15.2 [包裝器操作](15.2.html)
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看