结合php ob函数理解缓冲机制
对于一个刚刚入门的php程序员来说,php缓冲区是几乎透明的。在他们心目中,一个echo print_r 函数,数据便会‘嗖’的一声飞到浏览器上,显示出来。我也一直如此单纯地认为。 其实,在技术的世界里,向来都是由简单到复杂,也许那些技术开发者开始单纯如你我,但是面对残酷的现实,不得不调整策略,以期提高机器运行效率,最后想到了那些让我们赞叹的idea。
说到缓冲,也就是buffer,这里必须要和缓存做一下比较,单纯地比较定义是无意义的,莫不如看看它们做什么。缓存解决的是如何快速查找利用数据,节省cpu消耗问题,而缓冲解决的是高速cpu与低速I/O设备不匹配的问题。
再说下本文的另一个主角,ob函数,ob是output_buffering的简写。既然ob函数是php扩展函数,那么ob函数主要操作的也就是php buffer了。
简单说完本文两个主角,我们还必须回归开头的主题,echo print_r函数输出的数据是怎么到达浏览器让用户看到的呢?实际上的历程是这样的:
echo、print_r=>php output_buffering=>webServer buffer=>browser buffer=>browser display
我们可以清楚地看到,从echo、print_r函数到发送信息给客户端经历了两个缓冲区,在客户端还经历了一个浏览器缓冲区。我们本文主要讨论的是php output_buffering。
未使用ob函数时缓冲区的使用情况
我们的代码很多时候是根本不使用ob函数的,那么它们使用缓冲区了吗?这要看php设置情况。缓冲区是通过php.ini中的output_buffering变量控制的。其默认值是off,可以设置为on来打开buffer。打来buffer后,即便程序中没有用ob函数,实际上代码也是使用了缓冲区的。另外,不管php.ini中output_buffering的设置,cli模式下的php始终默认是关闭的。
为什么要是缓冲区呢?简单来说,高速的cpu早早处理完自己的数据,想通过线路传递给用户,但是线路太窄了,一下输送不过去。如果引入缓冲区,cpu可以将快速将生成的数据放入缓冲区,然后自己哪儿凉快儿哪儿呆着这歇着去了。缓冲区根据指令适时将数据输出。这个样就合理解决了高速cpu与低速I/O设备的矛盾了。
缓冲区的数据什么时候输出呢?1,当缓冲区满了的时候,缓冲是有容量大小的,到达极限则会自动输出内容。2,脚本执行完毕。很多小程序输出内容没那么多,总不能等到缓冲区满了再输出吧~这一点再自然不过。
使用ob函数时缓冲区的使用情况
ob_start()
打开输出缓冲。这个函数是我们调用最多的一个函数之一。在output_buffering设置为on或者x k的情况下,这个函数与其说是打开输出缓冲,还不如说将输出缓冲扩充到很大。当然在output_buffering设置为off的条件下,ob_start会起到打开buffer的作用。ob_start()还可以传递一个可选参数 output_callback 函数,php官方手册有详细说明。
ob_get_contents()
只是得到输出缓冲区的内容,但不清除它。
ob_end_clean()与ob_clean()
这两个函数从字面意思上就可以看出其区别。前者清除缓冲区内容并且关闭,后者仅仅是做清除工作。需要注意的是,使用了这两个函数,在前面使用了echo、print_r等函数不会输出内容。
笔者曾经试图通过print_r打印出ob_get_contents()的内容,然后调用ob_clean()清除缓冲区,以免影响后面对缓冲区的操作,屡屡失败。仔细想想,print_r的内容再次写入缓冲区,而后面做了ob_clean()的操作,自然不会有任何输出。在ob_clean操作之前调用ob_flush()函数便可达到预想的效果。
ob_flush()与flush()
ob_flush()送出缓冲区的内容并且丢弃内容。因而在此函数之前最好采用ob_get_contents()获得缓冲区内容。flush()刷出服务器端缓冲,并且发往客户端。因而从流程上来说,应该是先调用ob_flush()而后再调用flush函数。
另外说明下再Apache buffer flush()的工作原理:在apache module的sapi下,flush会通过调用sapi_module()的flush成员函数指针,间接使用apache的api::ap_rflush刷新apache的输出缓冲区。当然apache其他模块比如mod_gzip可能改变这个动作的结果,可能自己进行输出缓冲区,这将导致flush()函数产生的结果不会立即被送到客户端浏览器。
ob_get_clean()
如果你已经熟练掌握ob_get_contents()和ob_clean(),那这个函数就很简单了。因为它是前两者的结合体。它主要是得到当前缓冲区的内容并删除当前输出缓冲区。
ob函数还有很多,但大部分用法比较简单,理解较为容易。大家可以参照php手册 ,里面会有详细的解释。本文列出了笔者开始并不是很理解的一些函数,当然今后还会有新的问题出现,想到问题并且解决问题,生活的乐趣也许就在此处吧。
结合php ob函数理解缓冲机制的更多相关文章
- Printf的缓冲机制
转:https://blog.csdn.net/qq_25424545/article/details/78772959 今天用fork()写程序时候,突然发现自己对Printf的缓冲机制还是有些不够 ...
- Qt5双缓冲机制与实例
1. 双缓冲机制 所谓双缓冲机制,是指在绘制控件时,首先将要绘制的内容绘制在一个图片中,再将图片一次性地绘制到控件上. 在早期的Qt版本中,若直接在控件上进行绘制工作,则在控件重绘时会产生闪烁的现象, ...
- C++中的虚函数(表)实现机制以及用C语言对其进行的模拟实现
tfref 前言 C++对象的内存布局 只有数据成员的对象 没有虚函数的对象 拥有仅一个虚函数的对象 拥有多个虚函数的对象 单继承且本身不存在虚函数的继承类的内存布局 本身不存在虚函数(不严谨)但存在 ...
- paip.函数方法回调机制跟java php python c++的实现
paip.函数方法回调机制跟java php python c++的实现 作者Attilax 艾龙, EMAIL:1466519819@qq.com 来源:attilax的专栏 地址:http:// ...
- php基础知识【函数】(7)url和ob函数
一.URl函数 1.urlencode -- 编码 URL 字符串 2.urldecode -- 解码已编码的 URL 字符串 3.rawurlencode -- 按照 RFC 1738 对 URL ...
- 深入剖析C/C++函数的参数传递机制
2014-07-29 20:16 深入剖析C/C++函数的参数传递机制 C语言的函数入口参数,可以使用值传递和指针传递方式,C++又多了引用(reference)传递方式.引用传递方式在使用上类 ...
- malloc实现机制、缓冲机制、文件操作、mmap虚拟地址(day06)
一.malloc的实现机制(缓冲机制) 库函数跟系统调用之间的关系 什么是缓冲? 内存分配的原理. 封装 函数A的实现代码中调用了函数B.函数B的功能是函数A主要的功能,这样就说函数A封装了函数B. ...
- java : 包装类 缓冲机制的使用(转载)
摘要: 八种基本数据类型和其包装类中 Integer valueOf(int i).Byte valueOf(byte b).Short valueOf(short s).Long valueOf(l ...
- GO语言练习:channel 缓冲机制
1.代码 2.运行 3.解析 1.代码 buffer.go package main import ( "fmt" "time" ) func readThre ...
随机推荐
- C# 日志框架的添加
.NET中 记录日志的比较好的主要是Log4Net和Enterprise Library的Logging 复杂一点的还可以实现自动化Log日志 教程 首先是第二种方式 1.需要添加以下几个DLL 下 ...
- 01_蚂蚁感冒(第五届蓝桥预赛本科B组第8题 nyoj 990)
问题来源:第五届蓝桥预赛本科B组第8题 问题描述:有在一条定长(100cm)的直杆上有n(1<n<50)只蚂蚁(每只蚂蚁的起点都不一样),他们都以相同的速度(1cm/s)向左或者向右爬, ...
- hdu 4607 Park Visit 求树的直径
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4607 题目大意:给你n个点,n-1条边,将图连成一棵生成树,问你从任意点为起点,走k(k<=n) ...
- linux内核宏container_of前期准备之gcc扩展关键字typeof
typeof基本介绍 typeof(x) 这是它的使用方法,x可以是数据类型或者表达式.它的作用时期和sizeof类似,就是它是在编译器从高级语言(如C语言)翻译成汇编语言时起作用,这个很重要,稍后会 ...
- builder.properties
请加上这句话: javacDefaultEncoding.. = UTF-8
- git版本控制工具(二)----本地版本库的常用操作
[声明] 欢迎转载,但请保留文章原始出处→_→ 生命壹号:http://www.cnblogs.com/smyhvae/ 文章来源:http://www.cnblogs.com/smyhvae/p/ ...
- 验证码生成的c语言库
http://www.open-open.com/lib/view/open1324534929968.html
- PHP简单post验证绕过
if($_POST[user] && $_POST[pass]) { $conn = mysql_connect("*******", "****&quo ...
- swift代理使用
代理声明: //oc调用代理 @objc(NurseListCellDelegate) protocol NurseListCellDelegate : NSObjectProtocol{ func ...
- 错题726-java
class Car extends Vehicle { public static void main (String[] args) { new Car(). run(); } private fi ...