buffer ---- flush()

buffer是一个内存地址空间,Linux系统默认大小一般为4096(1kb),即一个内存页。主要用于存储速度不同步的设备或者优先级不同的 设备之间传办理数据的区域。通过buffer,可以使进程这间的相互等待变少。这里说一个通俗一点的例子,你打开文本编辑器编辑一个文件的时候,你每输入 一个字符,操作系统并不会立即把这个字符直接写入到磁盘,而是先写入到buffer,当写满了一个buffer的时候,才会把buffer中的数据写入磁 盘,当然当调用内核函数flush()的时候,强制要求把buffer中的脏数据写回磁盘。
同样的道理,当执行echo,print的时候,输出并没有立即通过tcp传给客户端浏览器显示, 而是将数据写入php buffer。php output_buffering机制,意味在tcp buffer之前,建立了一新的队列,数据必须经过该队列。当一个php buffer写满的时候,脚本进程会将php buffer中的输出数据交给系统内核交由tcp传给浏览器显示。所以,数据会依次写到这几个地方echo/print -> php buffer -> tcp buffer -> browser

php output_buffering --- ob_flush()

默认情况下,php buffer是开启的,而且该buffer默认值是4096,即1kb。你可以通过在php.ini配置文件中找到output_buffering配置.当echo,print等输出用户数据的时候,输出数据都会写入到php output_buffering中,直到output_buffering写满,会将这些数据通过tcp传送给浏览器显示。你也可以通过 ob_start()手动激活php output_buffering机制,使得即便输出超过了1kb数据,也不真的把数据交给tcp传给浏览器,因为ob_start()将php buffer空间设置到了足够大 。只有直到脚本结束,或者调用ob_end_flush函数,才会把数据发送给客户端浏览器。

这两个函数的使用怕是很多人最迷惑的一个问题,手册上对两个函数的解释也语焉不详,没有明确的指出它们的区别,似乎二者的功能都是刷新输出缓存。但在我们文章一开始的代码中如果讲fush()替换成ob_flush(),程序就再不能正确执行了。显然,它们是有区别的,否则也手册中直接说明其中一个是另外一个函数的别名即可了,没必要分别说明。那么它们的区别到底是什么呢?

在没有开启缓存时,脚本输出的内容都在服务器端处于等待输出的状态 ,flush()可以将等待输出的内容立即发送到客户端。

开启缓存后,脚本输出的内容存入了输出缓存中 ,这时没有处于等待输出状态的内容,你直接使用flush()不会向客户端发出任何内容。而 ob_flush()的作用就是将本来存在输出缓存中的内容取出来,设置为等待输出状态,但不会直接发送到客户端 ,这时你就需要先使用 ob_flush()再使用flush(),客户端才能立即获得脚本的输出。

一. flush和ob_flush的正确顺序,正确应是,先ob_flush再flush,如下: 
ob_flush();
flush();
如果Web服务器的操作系统是windows系统,那顺序颠倒或者不使用ob_flush()也不会出现问题。[有待求证 ] 但是在Linux系统上就无法刷新输出缓冲。

output buffering函数
1.bool ob_start ([ callback $output_callback [, int $chunk_size [, bool $erase ]]] )
激活output_buffering机制。一旦激活,脚本输出不再直接出给浏览器,而是先暂时写入php buffer内存区域。
php默认开启output_buffering机制,只不过,通过调用ob_start()函数据output_buffering值扩展到足够 大 。也可以指定$chunk_size来指定output_buffering的值。$chunk_size默认值是0,表示直到脚本运行结束,php buffer中的数据才会发送到浏览器。如果你设置了$chunk_size的大小 ,则表示只要buffer中数据长度达到了该值,就会将buffer中 的数据发送给浏览器。
当然,你可以通过指定$ouput_callback,来处理buffer中的数据。比如函数ob_gzhandler,将buffer中的数据压缩后再传送给浏览器。
第三个参数:是否擦除缓存,可选,默认是true,如果设置为false,则在脚本执行结束前,缓存都不会被清除。
2.ob_get_contents
获取一份php buffer中的数据拷贝。值得注意的是,你应该在ob_end_clean()函数调用前调用该函数,否则ob_get_contents()返回一个空字符中。

可以使用ob_get_contents()以字符串形式获取服务端缓存的数据,
使用ob_end_flush()则会输出被缓存起来的数据,并关闭缓存。
而使用ob_end_clean()则会静默的清除服务端缓存的数据,而不会有任何数据或其他行为。
服务端的缓存是堆叠起来的,也就是说你在开启了ob_start()后,关闭之前,在其内部还 可以开启另外一个缓存ob_start()。

不过你也要务必保证关闭缓存的操作和开启缓存的操作数量一样多。 
ob_start() 可以指定一个回调函数来处理缓存数据,如果一个ob_start()内部嵌套了另一个ob_start(),我们假定,外层的ob_start(),编号是A,内层的ob_start()编号是B,它们各自制定了一个回调函数分别是functionA和functionB,那么在缓存B中的数据输出时,它会先辈funcitonB回调函数处理,再交给外层的functionA回调函数处理,之后才能输出到客户端。

另外,手册说,对于某些web服务器,比如apache,在使用回调函数有可能会改变程序当前的工作目录,解决方法是在回调函数中自行手动把工作目录修改回来,用chdir函数,这点似乎不常遇到,遇到的时候记得去查手册吧。

3.ob_end_flush与ob_end_clean
这二个函数有点相似,都会关闭ouptu_buffering机制。但不同的是,ob_end_flush只是把php buffer中的数据冲(flush/send)到客户端浏览器,而ob_clean_clean将php bufeer中的数据清空(erase),但不发送给客户端浏览器。

ob_end_flush调用之前 ,php buffer中的数据依然存在,ob_get_contents()依然可以获取php buffer中的数据拷贝。

而ob_end_flush()调用之后 ob_get_contents()取到的是空字符串,同时浏览器也接收不到输出,即没有任何输出。

可以使用ob_get_contents()以字符串形式获取服务端缓存的数据,使用ob_end_flush()则会输出被缓存起来的数据,并关闭缓存。
而使用ob_end_clean()则会静默的清除服务端缓存的数据,而不会有任何数据或其他行为。
服务端的缓存是堆叠起来的,也就是说你在开启了ob_start()后,关闭之前,在其内部还可以开启另外一个缓存ob_start()。不过你也要务必保证关闭缓存的操作和开启缓存的操作数量一样多。
ob_start() 可以指定一个回调函数来处理缓存数据,如果一个ob_start()内部嵌套了另一个ob_start(),我们假定,外层的ob_start(),编号是A,内层的ob_start()编号是B,它们各自制定了一个回调函数分别是functionA和functionB,那么在缓存B中的数据输出时,它会先辈funcitonB回调函数处理,再交给外层的functionA回调函数处理,之后才能输出到客户端。

另外,手册说,对于某些web服务器,比如apache,在使用回调函数有可能会改变程序当前的工作目录,解决方法是在回调函数中自行手动把工作目录修改回来,用chdir函数,这点似乎不常遇到,遇到的时候记得去查手册吧。

最详细的PHP flush()与ob的更多相关文章

  1. 最详细的PHP flush()与ob_flush()的区别详解

    buffer ---- flush()buffer是一个内存地址空间,Linux系统默认大小一般为4096(1kb),即一个内存页.主要用于存储速度不同步的设备或者优先级不同的 设备之间传办理数据的区 ...

  2. PHP - 输出缓存 - 关于ob系列函数和flush函数

    偶然机会看到了flush().知道他的神奇功能可以用在异步传输的comet 模式之后,于是我去试了试这个方法.然后翻手册去看了看什么意思.发现它神奇的和ob类函数在一起.有点好奇,先放一放,来说flu ...

  3. FAILOVER详细步骤

    FAILOVER详细步骤 1.Flush主库任何未传输的redo到目标备库 如果primary可以mount,则可以flush任何主库的未传输redo到备库,如果操作成功返回,则可以保证failove ...

  4. lphp输出控制output controll(header, ob_xxx)

    关于php的output controll参考文档: http://gywbd.github.io/posts/2015/1/php-output-buffer-in-deep.html http:/ ...

  5. Php output buffering缓存及程序缓存

       在php中有时为了控制程序的输出显示顺序,提供了output buffering缓存(php自身缓存机制). 若Ob缓存开启,需要输出的就先存在ob缓存里,再到程序缓存里.若没有开启,则直接进入 ...

  6. 输出读入优化——QAQ

    #include<bits/stdc++.h> const int RN=1e5; ],*ip=ib+RN,ob[RN+],*op=ob; inline int gc(){ ip==ib+ ...

  7. Linux网络——配置网络之iproute家族命令

    Linux网络——配置网络之iproute家族命令 摘要:本文主要学习了iproute家族用来配置网络的命令. ip命令 ip命令用于查看和管理IP地址.接口.路由.隧道等.用来取代ifconfig命 ...

  8. HBase写入性能及改造——multi-thread flush and compaction(续:详细测试数据)[转]

    转载:http://blog.csdn.net/kalaamong/article/details/7290192 接上文啊: 测试机性能 CPU 16* Intel(R) Xeon(R) CPU   ...

  9. FC 与 FB 与 OB 的区别,时间标记冲突与一致性检查 有详细的步骤

    关键字1 组织块的程序是由用户自己编写. 关键字2 时间标记冲突与一致性检查 有详细的步骤. 关键字3 FC 与 FB 与 OB 的区别?   (一)功能 功能块 区别 ? FB 和FC均为 用户编写 ...

随机推荐

  1. eclipse No projects are found to import

    导入报:No projects are found to import 新建同名项目,然后删掉 然后:右键项目 根据需要创建资源目录: 最后复制包文件夹分别到这两个资源文件夹里:

  2. jQuery:多个AJAX/JSON请求相应单个回调

    原文链接:jQuery: Multiple AJAX and JSON Requests, One Callback 原文日期: 2014年4月15日 翻译日期: 2014年4月22日 翻译人员: 铁 ...

  3. Spark1.0.0 编程模型

    Spark Application能够在集群中并行执行,其关键是抽象出RDD的概念(详见RDD 细解),也使得Spark Application的开发变得简单明了.下图浓缩了Spark的编程模型. w ...

  4. jQuery 全选 正反选

    <script src="http://code.jquery.com/jquery-1.4.4.min.js" type="text/javascript&quo ...

  5. javaSE中的输入输出流---一个读取流,相应多个输出流。并且生成的碎片文件都有有序的编号

    <span style="font-size:18px;">package com.io.other.split; import java.io.File; impor ...

  6. 在LoadRunner脚本中实现随机ThinkTime

    一般情况下,我们都是通过Run-Time Settings来设置Think Time(思考时间),可以设置回放脚本时忽略思考时间,或者是设置回放随机的一段思考时间. By default, when ...

  7. lodash 工具库

    lodash是一套工具库,内部封装了很多字符串.数组.对象等常见数据类型的处理函数. 1.lodash的引用 import _ from 'lodash' 用一个数组遍历来说明为什么要使用lodash ...

  8. SAP query传输以后须要又一次生成程序

    近期有个需求,须要改动一个Query,在DEV改动好并測试通过后.传输到QAS,可是报表还是没变化,着实郁闷了一下,这是万能的google帮上忙了,原来传到其它系统以后还须要generate prog ...

  9. Oracle转化成为百分比

    两种方式都行: ),)||'%' 百分比 from dual; ),'99D99')||'%' 百分比 from dual 第一种方式通过round可以自己选择精确到位数.

  10. 基于MaterialDesign设计风格的妹纸app的简单实现

    代码地址如下:http://www.demodashi.com/demo/11644.html *今天看了郭神的第二行代码,深深的被MaterialDesign的设计风格所吸引,然后就照例做了一个小D ...