Android培訓班 100 核心解壓過程13

2021-08-26 20:02:00 字數 2742 閱讀 1809

有了檔案的格式,就可以按圖索驥,也就是根據檔案的格式來分析壓縮資料了。但檔案格式只是一種儲存的格式,還需要演算法才可以把資料解壓出來,下面就來理解gzip的壓縮演算法。gzip使用deflate的壓縮演算法來進行壓縮資料,這是一種無損的壓縮演算法,主要組合lz77和huffman的壓縮演算法。

lz77演算法是基於這樣的思路:當一串字元中,如果後面的字串已經在前面出現,那麼後面的字串只需要使用前面的位置和長度就表達相同的字串,從而達到字串使用最少的空間。現在看乙個簡單的例子,如下的字串:

aababbbabaababbbabbabb

在這個串中可以這樣表示,第乙個塊a寫作(0,a),第二個塊ab,就可以表達為索引和字母的方式(1,b),依這樣的編碼,就可以得到下面的**:

索引 塊 壓縮後表示

1 a (0,a)

2 ab (1,b)

3 abb (2,b)

4 b (0,b)

5 aba (2,a)

6 abab (5,b)

7 bb (4,b)

8 abba (3,a)

9 bb (7,0)

通過這樣壓縮處理後,就可以減少原來字串的大小,並且沒有資料損失。

huffman演算法是基於這樣的思路:當一串字元中,如果某個字元出現的頻率越高就使用最短的編碼記號,頻率越低的就使用最長的編碼記號,經過這樣編碼後達到壓縮的目的。可見huffman演算法是基於統計學來壓縮的,因此存在碼表和統計的過程。不過,huffman演算法也可以採用比較常見的預先定製靜態碼表來使用,這樣就不需要統計的過程了,這種演算法叫做靜態huffman演算法,反之叫做動態huffman演算法。

有了上面的基礎,就可以來學習gunzip

函式的**了,這個函式的**如下:

/**do the uncompression!

*/staticint init gunzip(void)

這段**是判斷是否gzip格式。

/* we only support method #8,deflated */

if (method != 8)

這段**是判斷是否為deflated壓縮方式。

flags = (uch)get_byte();

if ((flags & encrypted) != 0)

if ((flags & continuation) != 0)

if ((flags & reserved) != 0)

這段**是判斷是否使用特殊的標誌壓縮,如果有用就不能執行,因為這裡解壓**比較簡單。

nextbyte(); /* get timestamp */

nextbyte();

nextbyte();

nextbyte();

這段**跳過四個壓縮資料時的時間。

(void)nextbyte(); /* ignore extraflags for the moment */

(void)nextbyte(); /* ignore os typefor the moment */

這段**是跳過額外的標誌和作業系統型別。

if ((flags & extra_field) != 0)

這段**把所有額外欄位跳過,不作任何處理。

/* get original file name if it wastruncated */

if ((flags & orig_name) != 0)

這段**跳過原來壓縮檔案的名稱。

/* discard file comment if any */

if ((flags & comment) != 0)

這段**是跳過所有注釋的字元。

/* decompress */

if ((res = inflate()))

return -1;

}這段**是呼叫inflate來進行資料解壓。

/* get the crc and original length */

/* crc32 (see algorithm.doc)

* uncompressed input size modulo 2^32

*/ orig_crc = (ulg) nextbyte();

orig_crc |= (ulg) nextbyte() <<8;

orig_crc |= (ulg) nextbyte() <<16;

orig_crc |= (ulg) nextbyte() <<24;

這段**是獲取原來的crc32檢驗碼,以便跟解壓出來的資料計算的crc32檢驗碼比較。

orig_len = (ulg) nextbyte();

orig_len |= (ulg) nextbyte() <<8;

orig_len |= (ulg) nextbyte() <<16;

orig_len |= (ulg) nextbyte() <<24;

這段**是獲取壓縮之前資料長度。

/* validate decompression */

if (orig_crc != crc_value)

if (orig_len != bytes_out)

這段**是檢查crc32是否對,解壓後長度與壓縮前的長度是否一致。

return 0;

underrun: /* nextbyte() goto's hereif needed */

error("out of input data");

return -1;

}

Android培訓班 95 核心解壓過程8

核心在上面處理完關閉中斷,並且確認進入系統模式後,就需要解決第乙個問題 解決自己到底在那裡執行的問題。這個問題,就好比乙個人在大海浬航行而沒有指南針,根本找不到北在那裡,急切地想知道方向在那裡。如果在白天還可以靠大陽就知道了方向,在晚上可以靠北斗星,在核心裡是否也有這樣的大自然的指示呢?在核心裡沒有...

Android培訓班 96 核心解壓過程9

前面已經把定位的資料通重載入 lc0結構來載入到暫存器裡,已經具備了定位的條件。那麼核心進行重定位主要做些什麼事情呢?要了解整個過程,當然要學習編譯原理,因為進行重定位之後,主要是為了建立 c語言的執行環境的需求。由於 c語言是基於棧式的語言,又有全域性變數,說明記憶體結構至少有兩個,乙個是全域性資...

Android培訓班 97 核心解壓過程10

經過上面開啟 mmu 之後,就進入了另乙個主要環節,就是把壓縮的核心 解壓出來,變換回原來可執行 的模樣,這樣才可以讓 cpu理解並執行相應的指令。由於載入壓縮的核心就占用了一定的記憶體空間,如果這個壓縮的核心比較大,而物理記憶體比較小,那麼解壓後的核心就會把未解壓部份的核心資料覆蓋,否則就可以採用...