php 缓冲区

php 缓冲区

php输出数据到页面上,比如echo "11111111";然后程序中还有其他的输出,如果没有开启缓冲区,就是有echo , print ==一系列的打印方法,就会往浏览器器上输出,但是有了缓冲区之后就不一样了。先填充缓冲区,缓冲区填满了再输出到页面上,我在网上找了一些相关的介绍,记录下来...........

buffer是一个内存地址空间,Linux系统默认大小一般为4096(4kb),即一个内存页。主要用于存储速度不同步的设备或者优先级不同的设备之间传办理数据的区域。通过buffer,可以使进程这间的相互等待变少。这里说一个通俗一点的例子,你打开文本编辑器编辑一个文件的时候,你每输入一个字符,操作系统并不会立即把这个字符直接写入到磁盘,而是先写入到buffer,当写满了一个buffer的时候,才会把buffer中的数据写入磁盘,当然当调用内核函数flush()的时候,强制要求把buffer中的脏数据写回磁盘。

同样的道理,当执行echo,print的时候,输出并没有立即通过tcp传给客户端浏览器显示, 而是将数据写入php buffer。php output_buffering机制,意味在tcp buffer之前,建立了一新的队列,数据必须经过该队列。当一个php buffer写满的时候,脚本进程会将php buffer中的输出数据交给系统内核交由tcp传给浏览器显示。所以,数据会依次写到这几个地方echo/pring -> php buffer -> tcp buffer -> browser

output_buffering

在php.ini里面, output_buffering默认是开启的,默认值是4096字节,就是4kb,

; Default Value: On
; Development Value: 4096
; Production Value: 4096
; http://php.net/output-buffering

如果配置里面设置成 output_buffering = Off ,在程序中可以用ob_start()来开启缓冲区

另外还有一个配置

; Implicit flush tells PHP to tell the output layer to flush itself
; automatically after every output block. This is equivalent to calling the
; PHP function flush() after each and every call to print() or echo() and each
; and every HTML block. Turning this option on has serious performance
; implications and is generally recommended for debugging purposes only.
; http://php.net/implicit-flush
; Note: This directive is hardcoded to On for the CLI SAPI
implicit_flush = Off

Off 每次输出后不会调用flush(),需要等到server buffering满了才会输出.
On 表示每次输出(如echo,print)后自动调用flush()函数后,直接输出

php的输出顺序(网上看到的,拿到csdn去问,别人说是正确的,所以就按这么理解了)

1.打开了php输出缓存: echo,print -> php output_buffring -> server buffering -> browser buffering -> browser display

2.未打开php输出缓存: echo,print -> server buffering -> browser buffering -> browser display

与缓冲区相关的几个函数
  • ob_start

    Turn on output buffering

    打开输出缓冲区

    配置里面是关闭缓冲区的,或者认为的关闭了缓冲区,可以用该函数打开缓冲区

  • ob_get_contents

    Gets the contents of the output buffer without clearing it

    得到缓冲区的数据,但是不清空缓冲区,如果缓冲区没有激活,返回false

  • ob_get_clean

    Get current buffer contents and delete current output buffer

    得到缓冲区的数据,同时清空缓冲区

  • ob_get_length

    This will return the length of the contents in the output buffer

    返回缓冲区内容的长度,没有激活,返回false

  • ob_get_status

    ob_get_status() returns status information on either the top level output buffer or all active output buffer levels if full_status is set to TRUE.

    返回最顶层输出缓冲区的状态信息;或者如果full_status设为TRUE,返回所有有效的输出缓冲级别

    这个不大懂, 关于缓冲区级别是什么样子的

  • ob_clean

    Clean (erase) the output buffer

  • ob_end_clean

    Clean (erase) the output buffer and turn off output buffering

    关闭缓冲区,并且清空缓冲区

  • ob_end_flush

    Flush (send) the output buffer and turn off output buffering

    关闭缓冲区,并且输出缓冲区(应该是将php的buffer输出到server的buffer )

  • ob_flush

    Flush (send) the output buffer

    输出缓冲区(php的buffer输出到server的buffer)

  • flush

    刷新PHP程序的缓冲,而不论PHP执行在何种情况下(CGI ,web服务器等等)。该函数将当前为止程序的所有输出发送到用户的浏览器。

    取出Server buffering的数据,放入browser buffering

php的ob函数还有好几个,都没怎么用到,也不大懂是什么意思.........

例子帮助理解 或者在工作中遇到的问题.......

以前看session的时候,有说在session_start()之前不能有任何的输出,不然会报告错误,但是我怎么也调试不出来,就是在session_start之前echo,不报错.当时别人告诉我是缓冲区开启了的原因,悲剧的是 我都不知道缓冲区是啥

ob_end_clean();
echo "1111111";
session_start();

Warning: session_start() [function.session-start]: Cannot send session cache limiter - headers already sent

在就是设置header头之前能有任何输出,其实这个也很好理解,输出表示请求和响应已经完成了,这是时候响应头也完毕,在去修改响应就不可能了

一个例子,看网上很举这个例子,来理解缓冲区

    ob_start();
    $i=10;
    while($i>=0){
        echo ($i--)."<br>";
        sleep(1);
    }

可以看到大概经过了10多秒,一下子将全部的数据打印到页面上的


在一个例子

	ob_end_clean();
	$i=10;
	while($i>=0){
		echo ($i--)."<br>";		
		sleep(1);
	}

还是一次性输出在页面上

为啥?因为server还是有缓冲区的,当server端的缓冲区满了,才会向brower发送,所以要加上flush函数



在试试

	ob_end_clean();
	$i=10;
	while($i>=0){
		echo ($i--)."<br>";		
		flush();
		sleep(1);
	}

结果在我的浏览器上面还是一次性全部输出的

为啥?我也不知道为啥,网上看到的解释,也不是理解的很清楚 个别web服务器程序,特别是Win32下的web服务器程序,在发送结果到浏览器之前,仍然会缓存脚本的输出,直到程序结束为止。有些Apache的模块,比如mod_gzip,可能自己进行输出缓存,这将导致 flush()函数产生的结果不会立即被发送到客户端浏览器。甚至浏览器也会在显示之前,缓存接收到的内容。例如 Netscape 浏览器会在接受到换行或 html 标记的开头之前缓存内容,并且在接受到 </table> 标记之前,不会显示出整个表格。


根据前辈们的经验,ob_flush,flush同时使用,可以讲一段一段的输出到页面上

	$i=10;
	while($i>=0){
		echo ($i--)."<br>";
		ob_flush();
		flush();
		sleep(1);
	}

我也看了有些技术blog的介绍,有些blog上说的跟我不一样,可能跟环境有关,反正我不懂的东西太多了
https://www.surfchen.org/archives/125
http://www.perfgeeks.com/?p=344
http://www.cnblogs.com/zemliu/archive/2012/05/11/2495293.html   (这位兄弟些的个  和我测试的结果差不多)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值