php的二進位安全_PHP教程

來源:互聯網
上載者:User

php的二進位安全


本文主要從三個角度來闡述php的二進位安全:1. 什麼叫php的二進位安全;2. 什麼結構確保了php的二進位安全;3. 這種結構還有哪些其它方面的應用?

做到知其然,也知其所以然。

一句話解釋:

php的內建函式在操作位元據時能保證達到預期的結果,例如str_replace、stristr、strcmp等函數,我們就說這些函數是二進位安全的。

舉個列子:

我們來對比一下C和php下的strcmp函數。

C代碼如下

main(){    char ab[] = "aa\0b";    char ac[] = "aa\0c";    printf("%d\n", strcmp(ab, ac));    printf("%d\n", strlen(ab)); }

結果:

0

2

解讀:

也就是說C語言認為ab和ac這兩個字串是相等的,而且ab的長度為2.


php代碼如下


結果:

int(-1)

int(4)

解讀:

也就是php語言認為ab和ac這兩個字串是相等的,而且ab的長度為4。

聰明的你,應該已經發現問題在哪了吧,不錯,對於c語言‘\0’是字串的結束符,所以在C語言中對於字串“aa\0b”,它讀到'\0'就會預設字元讀取已經結束,而拋掉後面的字串'b',導致我們看到strlen(“aa\0b”)的值為2

那問題又來了,php都是C來開發的,為什麼php做到了二進位安全呢?

先來看看php的變數儲存zval結構


php會根據type的值來決定訪問value的哪個成員,為字串時,我們會訪問紅框標識的str結構,這便是底層字串的儲存結構,它有兩個值,一個是指向字串的指標val,另一個是記錄字串長度的len值,就是因為有len這個值,導致了php是二進位安全的:因為它不需要像C一樣通過是否遇到'\0'結尾符來判斷整個字串是否讀取完畢,而是通過len這個值指定的長度進行讀取。


可見一個小小的資料結構改進,為我們帶來了更多想象的空間,可謂是 結構的一小步,功能的一大步

拓展:

這麼好用的結構,顯然會被到處使用,我們常用的redis,在底層儲存資料時就用到了這種結構,Redis 沒有直接使用 C 語言傳統的字串表示(以Null 字元結尾的字元數組),而是自己構建了一種名為簡單動態字串(simple dynamic string,SDS)的抽象類別型,並將 SDS 用作 Redis 的預設字串表示

看下SDS的結構定義
struct sdshdr {    // 記錄 buf 數組中已使用位元組的數量    // 等於 SDS 所儲存字串的長度    int len;    // 記錄 buf 數組中未使用位元組的數量    int free;    // 位元組數組,用於儲存字串    char buf[];};
可以看到,我們又見到了熟悉的len值,又是它保證了redis的儲存是二進位安全的

以下內容足以闡明這一點:(摘自http://redisbook.com/preview/sds/different_between_sds_and_c_string.html#id6)

C 字串中的字元必須符合某種編碼(比如 ASCII),並且除了字串的末尾之外,字串裡面不能包含Null 字元,否則最先被程式讀入的Null 字元將被誤認為是字串結尾 ——這些限制使得 C 字串只能儲存文本資料,而不能儲存像圖片、音頻、視頻、壓縮檔這樣的位元據。

舉個例子,如果有一種使用Null 字元來分割多個單詞的特殊資料格式, 2-17 所示,那麼這種格式就不能使用 C 字串來儲存,因為 C 字串所用的函數只會識別出其中的"Redis" ,而忽略之後的 "Cluster"

雖然資料庫一般用於儲存文本資料,但使用資料庫來儲存位元據的情境也不少見,因此,為了確保 Redis 可以適用於各種不同的使用情境,SDS 的 API 都是二進位安全的(binary-safe):所有 SDS API 都會以處理二進位的方式來處理 SDS 存放在buf 數組裡的資料,程式不會對其中的資料做任何限制、過濾、或者假設 ——資料在寫入時是什麼樣的,它被讀取時就是什麼樣。

這也是我們將 SDS 的 buf 屬性稱為位元組數組的原因 ——Redis 不是用這個數組來儲存字元,而是用它來儲存一系列位元據。

比如說,使用 SDS 來儲存之前提到的特殊資料格式就沒有任何問題,因為 SDS 使用 len 屬性的值而不是Null 字元來判斷字串是否結束, 2-18 所示。

buf"]; buf [label = " { 'R' | 'e' | 'd' | 'i' | 's' | '\\0' | 'C' | 'l' | 'u' | 's' | 't' | 'e' | 'r' | '\\0' | '\\0' } "]; // sdshdr:buf -> buf;}">

通過使用二進位安全的 SDS ,而不是 C 字串,使得 Redis 不僅可以儲存文本資料,還可以儲存任意格式的位元據。



http://www.bkjia.com/PHPjc/925226.htmlwww.bkjia.comtruehttp://www.bkjia.com/PHPjc/925226.htmlTechArticlephp的二進位安全 本文主要從三個角度來闡述php的二進位安全:1. 什麼叫php的二進位安全;2. 什麼結構確保了php的二進位安全;3. 這種結構還...

  • 聯繫我們

    該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

    如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.