libz.so庫分析


from:http://blog.chinaunix.net/uid-12773189-id-84605.html

1、查看庫文件是由哪個軟件包提供的
空閑時打開/usr/lib目錄(因為我知道這個目錄下放着一些庫文件,是我們開發者可以利用的)想看看我的系統中有哪些庫。
看到一個libz.so,於是用命令查看:dpkg -S /usr/lib/libz.so

此命令輸出如下信息:zlib1g-dev: /usr/lib/libz.so

即我的系統中軟件包zlib1g-dev提供了libz.so這個庫文件。
2、查看軟件包的詳細信息
可以用下列命令查看此軟件包是干什么的:apt-cache show zlib1g-dev

輸出內容一部分為:Description: compression library - development
zlib is a library implementing the deflate compression method found
in gzip and PKZIP. This package includes the development support
files.
Bugs: mailto:ubuntu-users@lists.ubuntu.com
Origin: Ubuntu

顯然這個軟件包提供了用gzip和PKZIP壓縮算法進行開發的相關東西。

繼續用下面的命令查看zlib1g-dev軟件包的詳細信息:dpkg -L zlib1g-dev

此命令輸出如下信息:/.
/usr
/usr/lib
/usr/lib/libz.a
/usr/include
/usr/include/zlib.h
/usr/include/zconf.h
/usr/share
/usr/share/doc
/usr/share/doc/zlib1g-dev
/usr/share/doc/zlib1g-dev/examples
/usr/share/doc/zlib1g-dev/examples/example.c.gz
/usr/share/doc/zlib1g-dev/examples/contrib.tar.gz
/usr/share/doc/zlib1g-dev/examples/minigzip.c.gz
/usr/share/doc/zlib1g-dev/changelog.gz
/usr/share/doc/zlib1g-dev/FAQ.gz
/usr/share/doc/zlib1g-dev/README.gz
/usr/share/doc/zlib1g-dev/copyright
/usr/share/doc/zlib1g-dev/changelog.Debian.gz
/usr/share/doc/zlib1g-dev/algorithm.txt.gz
/usr/share/man
/usr/share/man/man3
/usr/share/man/man3/zlib.3.gz
/usr/lib/libz.so

從這里可以看出,zlib1g-dev軟件包提供了庫文件libz.a和libz.so,還提供了頭文件zlib.h和zconf.h,另外還在/usr/share/doc/zlib1g-dev目錄下提供關於此庫文件使用方法的文檔,甚至有例子在/usr/share/doc/zlib1g-dev/examples目錄下,比如example.c.gz就是一個完整的gzip壓縮/解壓縮例子。
如果把example.c.gz、minigzip.c.gz兩個例子程序完全弄懂了,你就肯定會自己寫程序進行壓縮和解壓縮工作了。
3、查看庫文件提供了哪些調用
如果我們不看上面的軟件包信息中提供的源代碼例子,也可以用nm命令自己查看庫文件提供了哪些調用。
比如我們用下面的nm命令查看libz.so庫文件提供哪些調用:nm -D /usr/lib/libz.so

此命令輸出如下:00001810 T adler32
00001ad0 T adler32_combine
00013b30 A __bss_start
U clearerr
00001c70 T compress
00001ba0 T compress2
00001b80 T compressBound
00001cd0 T crc32
00002320 T crc32_combine
w __cxa_finalize
00005da0 T deflate
00005150 T deflateBound
00004bb0 T deflateCopy
000107e0 R deflate_copyright
00004890 T deflateEnd
00005640 T deflateInit_
00005360 T deflateInit2_
00006b80 T deflateParams
00004810 T deflatePrime
000051c0 T deflateReset
00004fe0 T deflateSetDictionary
000047e0 T deflateSetHeader
00004850 T deflateTune
00010820 R _dist_code
00013b30 A _edata
00013b34 A _end
U __errno_location
U fclose
U fdopen
U feof
U ferror
U fflush
0000e784 T _fini
U fopen
U fprintf
U fputc
U fread
U free
U fseek
U ftell
U fwrite
00001cb0 T get_crc_table
w __gmon_start__
00002570 T gzclearerr
00002b50 T gzclose
00002550 T gzdirect
00003ba0 T gzdopen
00002520 T gzeof
000025b0 T gzerror
00002d40 T gzflush
000046c0 T gzgetc
00004640 T gzgets
00003c20 T gzopen
00002a10 T gzprintf
00002900 T gzputc
000028c0 T gzputs
00003c40 T gzread
00002950 T gzrewind
00004410 T gzseek
00002ab0 T gzsetparams
00004600 T gztell
000024d0 T gzungetc
000027d0 T gzwrite
0000a490 T inflate
0000c4e0 T inflateBack
0000c490 T inflateBackEnd
0000c390 T inflateBackInit_
0000a000 T inflateCopy
00012720 R inflate_copyright
00009f40 T inflateEnd
0000e1c0 T inflate_fast
00009fa0 T inflateGetHeader
00009f00 T inflateInit_
00009df0 T inflateInit2_
00009da0 T inflatePrime
00009d00 T inflateReset
0000a380 T inflateSetDictionary
0000c1a0 T inflateSync
00009fd0 T inflateSyncPoint
0000d770 T inflate_table
000013d0 T _init
w _Jv_RegisterClasses
00010a20 R _length_code
U malloc
U memcpy
U memset
U sprintf
U __stack_chk_fail
U strcat
U strcpy
U strerror
U strlen
00008390 T _tr_align
00009240 T _tr_flush_block
000074e0 T _tr_init
00008210 T _tr_stored_block
00007c10 T _tr_tally
00004710 T uncompress
U vsnprintf
00009cd0 T zcalloc
00009ca0 T zcfree
00013900 D z_errmsg
00009c70 T zError
00009c60 T zlibCompileFlags
00009c40 T zlibVersion

這些輸出中的第一列是這個庫libz.so提供的調用的值,第二列是調用的類型,第三列是調用的名稱(可理解為我們常說的函數名)。
關於nm的詳細用法可以參考man nm手冊,我們在這里先只關心一下第二列為T的,即類型為T的,這是我們的應用程序可以調用的。
/************關於本文檔********************************************
*filename: 我是這樣學習Linux下C語言編程的-自我學會利用Linux系統上已有的開發庫
*purpose: 說明怎樣利用Linux中已有的庫文件進行開發
*wrote by: zhoulifa(zhoulifa@163.com) 周立發(http://zhoulifa.bokee.com)
Linux愛好者 Linux知識傳播者 SOHO族 開發者 最擅長C語言
*date time:2007-02-06 20:00
*Note: 任何人可以任意復制代碼並運用這些文檔,當然包括你的商業用途
* 但請遵循GPL
*Thanks to:Google
*Hope:希望越來越多的人貢獻自己的力量,為科學技術發展出力
* 科技站在巨人的肩膀上進步更快!感謝有開源前輩的貢獻!
*********************************************************************/
同時由於我們只關心gzip壓縮和解壓縮方法的使用,我們可以用命令過濾一下:nm -D /usr/lib/libz.so | grep gz

此命令輸出如下:00002570 T gzclearerr
00002b50 T gzclose
00002550 T gzdirect
00003ba0 T gzdopen
00002520 T gzeof
000025b0 T gzerror
00002d40 T gzflush
000046c0 T gzgetc
00004640 T gzgets
00003c20 T gzopen
00002a10 T gzprintf
00002900 T gzputc
000028c0 T gzputs
00003c40 T gzread
00002950 T gzrewind
00004410 T gzseek
00002ab0 T gzsetparams
00004600 T gztell
000024d0 T gzungetc
000027d0 T gzwrite

顯然,如果你有在Linux下用C語言編程操作過文件,對上面出現的函數名,應該很熟悉吧?把前面的gz換成f,是不是多數都是你熟悉的stdio.h提供的文件操作函數?如果直接去掉gz,是不是就是fcntl.h提供的所有文件操作函數?
4、查看函數的定義
打開/usr/include/zlib.h,搜索上面出現的這些函數,你很快會找gzopen的說明的:ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode));
/*
Opens a gzip (.gz) file for reading or writing. The mode parameter
is as in fopen ("rb" or "wb") but can also include a compression level
("wb9") or a strategy: 'f' for filtered data as in "wb6f", 'h' for
Huffman only compression as in "wb1h", or 'R' for run-length encoding
as in "wb1R". (See the description of deflateInit2 for more information
about the strategy parameter.)

gzopen can be used to read a file which is not in gzip format; in this
case gzread will directly read from the file without decompression.

gzopen returns NULL if the file could not be opened or if there was
insufficient memory to allocate the (de)compression state; errno
can be checked to distinguish the two cases (if errno is zero, the
zlib error is Z_MEM_ERROR). */

看到了吧?用gzopen函數就可以直接打開或創建一個壓縮文件*.gz的,使用方法在這里講得比較清楚了。
同樣,我們會看到上面所有函數的說明:ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len));
ZEXTERN int ZEXPORT gzwrite OF((gzFile file, voidpc buf, unsigned len));
ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush));
ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file, z_off_t offset, int whence));
ZEXTERN int ZEXPORT gzclose OF((gzFile file));
……

5、使用庫
有了上面這些信息,我們就可以自己寫程序來使用庫文件提供的所有東西了。比如下面的代碼:#include <zlib.h> /* 因為 gz 相關的函數在這個頭文件中定義的 */
#include <zconf.h>
#include <stdio.h> /* 因為 printf 相關的函數在這個頭文件中定義的 */
#include <errno.h> /* 因為 errno 相關的函數在這個頭文件中定義的 */
#include <stdlib.h> /* 因為 exit 函數在這個頭文件中定義的 */
#include <string.h> /* 因為 strlen 函數在這個頭文件中定義的 */

int main(int argc, char **argv)
{
        gzFile mygzfp;

        mygzfp = gzopen(argv[1], "w");
        if(mygzfp == NULL) {
                printf("以寫方式打開文件'%s'出錯,錯誤信息:%s", argv[1], strerror(errno));
                exit(0);
        }
        gzwrite(mygzfp, argv[2], strlen(argv[2]));
        gzclose(mygzfp);
        return 0;
}


編譯此程序用這個命令:
gcc gzfile.c -lz
注意:為了引用libz.so這個庫
文件,我們必須用-lz。
運行這個命令:
./a.out mygzfile.gz "hello, 這是一個自己生成壓縮文件的測試程序。"
將在當前目錄下生成一個文件名為mygzfile.gz的壓縮文件。
你可以打開此壓縮文件看看,里面是不是你自己寫進去的信息呢?


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM