1. php的二進位安全 binary-safe
php的內建函式在操作位元據時能保證達到預期的結果,例如 str_replace、stristr、strcmp 等函數,我們就說這些函數是二進位安全的。
下面通過 c 語言 和 php 的對比 來看 他們對位元據的處理
#include "stdio.h"#include "string.h"int main(){char a[] = "aa\0b";char b[] = "aa\0c";printf("%d\n", strcmp(a, b));printf("%ld\n", strlen(a));}/* 0 2 */
可以看出來 c語言 "\0" 是字串結束,所以認為 "aa\0b' 和 "aa\0c" 是一樣的,長度為2 拋棄了 "\0b" 和 "\0c" .
<?php/** * Created by PhpStorm. * User: leon * Date: 17/11/6 * Time: 上午10:24 */ $a = "aa\0b"; $b = "aa\0c"; $c = "\0\0"; $d = 'a'; $e = 'a'; var_dump(strcmp($a, $b)); var_dump(strcmp($c, $d)); var_dump(strlen($a)); var_dump(strlen($c));# res : int(-1) int(0) int(4) int(2)
php "aa\0b" 和 "aa\0c" 是不同的 ,並且長度為4
2. php實現二進位安全的原理
PHP中字串通過 zend_string 表示:
PHP中 變數 zend_value 表示:
gc: 變數引用資訊,比如當前value的引用數,所有用到引用計數的變數類型都會有這個結構,3.1節會詳細分析
h: 雜湊值,數組中計算索引時會用到
len: 字串長度,通過這個值保證二進位安全
val: 字串內容,變長struct,分配時按len長度申請記憶體
len: 字串長度,通過這個值保證二進位安全 ,它不需要像C 一樣用喲 ‘\0’ 結尾符來判斷字串的結束,而是通過len
3.SDS
C : 以 ’\0’ 為結束符,所以c的字串不能包含文本,圖片、音頻、視頻、壓縮檔這樣的位元據。
Php : 記錄 len
SDS : simple dynamic string 簡單動態字串的抽象類別型,應用到字元表示:
SDS 資料結構:
struct sdshdr { # 記錄 buf 數組中已使用位元組的數量 # 等於 SDS 所儲存字串的長度 int len; # 記錄 buf 數組中未使用位元組的數量 int free; # 位元組數組,用於儲存字串 char buf[];};
redis 的結構定義中也記錄了SDS所儲存字串的長度,通過這個值保證二進位安全,SDS 的 API 都會用 字串的len 屬性來判斷字串是否結束。