文章目录
zlib
1. zlib库介绍
- zlib是一套通用的解压缩开源库,提供了内存(in-memory)压缩和解压函数,能检测解压出来的数据完整性,zlib 也支持读写 gzip (.gz) 格式的文件,可以阅读:zlib库介绍三:gzip(.gz格式)文件读写
- 默认且目前仅使用deflate算法压缩data部分;deflate是一种压缩算法,是huffman编码的一种加强。
2. zlib库的应用
数以万计的应用程序直接或间接依靠zlib压缩函式库,包括:
- FFmpeg:以zlib读写Matroska等以DEFLATE算法压缩的多媒体串流格式。
- OpenSSH、OpenSSL:以zlib达到最佳化加密网络传输。
- Linux核心:使用zlib以实作网络协定的压缩、档案系统的压缩以及开机时解压缩自身的核心。
- libpng,用于PNG图形格式的一个实现,对bitmap数据规定了DEFLATE作为流压缩方法。
- 略、、、、
参考博文:zlib库介绍一:zlib简介
3. 下载地址
4. 函数使用教程
zlib 在 examples 路径下提供了许多使用zlib的例子:
在README.examples 有介绍各个example的作用。
4.1 compress 与 uncompress
compress和uncompress是zlib最基本的两个函数了。他们分别用于压缩和解压数据。 原型如下:
int compress(unsigned char* dest,
unsigned long*destLen,
const unsigned char* source,
unsigned long sourceLen);
int compress2(unsigned char* dest,
unsigned long*destLen,
const unsigned char* source,
unsigned long sourceLen,
int level);
参数:
- dest:压缩之后的数据缓冲区。
- desLen:压缩之后的数据缓冲区长度。
- source:原始数据缓冲区(压缩之前的数据内容)。
- sourceLen:原始数据长度。
- level:level:压缩比例,压缩级别取值:0 - 9。0压缩速度最快,9压缩速度最慢,压缩率最大。0表示不进行压缩。【compress2才有】
返回值:
- Z_OK:成功。
- Z_MEM_ERROR:没有足够的内存。
- Z_BUF_ERROR:输出的缓冲区没有足够的空间。
- Z_STREAM_ERROR:level参数设置不正确。【compress2才有】
int uncompress(unsigned char* dest,
unsigned long* destLen,
unsigned char* source,
unsigned long sourceLen);
int uncompress2(unsigned char* dest,
unsigned long* destLen,
unsigned char* source,
unsigned long* sourceLen);
参数:
-
dest:解缩之后的数据缓冲区
-
desLen:解缩之后的数据缓冲区长度
-
source:要解压的数据缓冲区
-
sourceLen:要解压的数据长度
返回值:
-
Z_OK:成功。
-
Z_MEM_ERROR:没有足够的内存。
-
Z_BUF_ERROR:输出的缓冲区没有足够的空间。
-
Z_DATA_ERROR:输入的原始数据(source)被损坏了,或不完整。
uncompress2函数相比于uncompress函数,原始数据长度采用指针进行表示。
4.3 使用过程解析
- 压缩、解压过程 方案一
压缩:deflateInit() ->deflate() ->deflateEnd();
解压:inflateInit() -> inflate() -> inflateEnd();
- 压缩、解压过程 方案二
压缩:deflateInit2() ->deflate() ->deflateEnd();
解压:inflateInit2() -> inflate() -> inflateEnd();
ZEXTERN int ZEXPORT compress OF((Bytef *dest, uLongf *destLen,
const Bytef *source, uLong sourceLen));
ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen,
const Bytef *source, uLong sourceLen));
参数类型
- Bytef表示字节流,它与字符串有所不同,字节流没有结束符,因而需要配备长度信息,处理字符串的时候需要把结束符也当成一个普通的字节。
- uLongf则用于指明长度信息了, 其实相当于unsigned long。
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <zlib.h>
int main(int argc, char *argv[])
{
char inbuf[] = "Hello, This is a demo for compress and uncompress interface!\n"
"Written by windeal.li\n"
"email: 2378264731@qq.com\n";
uLong inlen = sizeof(inbuf);
char *outbuf = NULL;
uLong outlen;
outlen = compressBound(inlen);
printf("in_len: %ld\n", inlen);
printf("out_len: %ld\n", outlen);
if ((outbuf = (char *)malloc(sizeof(char) * outlen)) == NULL){
fprintf(stderr, "Failed to malloc memory for outbuf!\n");
return -1;
}
/* compress */
if (compress(outbuf, &outlen, inbuf, inlen) != Z_OK) {
fprintf(stderr, "Compress failed!\n");
return -1;
}
printf("Compress Sucess!\n");
printf("\routlen:%ld, outbuf:%s\n", outlen, outbuf);
memset(inbuf, 0, sizeof(inbuf));
/* Uncompress */
if (uncompress(inbuf, &inlen, outbuf, outlen) != Z_OK){
fprintf(stderr, "Uncompress failed!\n");
return -1;
}
printf("Uncompress Success!\n");
printf("\rinlen:%ld, inbuf:%s\n", inlen, inbuf);
/* free memory */
if (outbuf != NULL){
free(outbuf);
outbuf = NULL;
}
return 0;
}
4.2 infate、deflate、z_stream
这里infate 和defate 其实是指两组函数
- deflateInit() + deflate() + deflateEnd()用于完成流的压缩
- inflateInit() + inflate() + inflateEnd()用于完成解压缩功能
int deflateInit (z_streamp strm, int level); //初始化压缩状态,关联相关的z_stream数据结构和压缩比例
int deflate (z_streamp strm, int flush); //压缩数据, flush表示以何种方式将压缩的数据写到缓冲区中。
int deflateEnd (z_streamp strm); //压缩结束
int inflateInit (z_streamp strm);
int inflate (z_streamp strm, int flush);
int inflateEnd (z_streamp strm);
z_stream是上面两组函数中用到的,用来表示流的数据结构。
typedef struct z_stream_s {
z_const Bytef *next_in; // 将要压缩数据的首地址
uInt avail_in; // 将要压缩数据的长度
uLong total_in; // 将要压缩数据缓冲区的长度
Bytef *next_out; // 压缩后数据保存位置。
uInt avail_out; // 压缩后数据的长度
uLong total_out; // 压缩后数据缓冲区的大小
z_const char *msg; // 存放最近的错误信息,NULL表示没有错误
struct internal_state FAR *state; /* not visible by applications */
alloc_func zalloc; /* used to allocate the internal state */
free_func zfree; /* used to free the internal state */
voidpf opaque; /* private data object passed to zalloc and zfree */
int data_type; // 表示数据类型,文本或者二进制
uLong adler; /* adler32 value of the uncompressed data */
uLong reserved; /* reserved for future use */
} z_stream;
关于这两组函数的具体使用, zlib-1.2.11/examples/zpipe.c或zlib-1.2.11/test/example.c,可以直接参考。
参考博文:
5. 交叉编译zlib库
linux主机:ubuntu-18.04
交叉编译器:arm-buildroot-linux-gnueabihf
开发板kernel:Linux 5.4.0-150-generic x86_64
开发板:100ASK_STM32MP157_PRO开发板
zlib版本:zlib-1.2.11.tar.gz
下载
解压
tar xvf zlib-1.2.11.tar.gz
引入交叉编译器【zlib的configure不支持设置–host项】
export CC=/home/book/100ask_stm32mp157_pro-sdk/ToolChain/arm-buildroot-linux-gnueabihf_sdk-buildroot/bin/arm-buildroot-linux-gnueabihf-gcc
除了上面的引入交叉编译器,也可以手动更改Makefile,vim命令打开Makefile文件,将其中的CC、AR、RANLIB等都修改为arm-linux交叉编译器的相关参数
配置configure,指定安装后的文件在install文件夹里面
./configure --prefix=$PWD/install
编译
make
安装
sudo make install
由于前面运行configure文件的时候指定了安装的路径
cd install/lib
lib库里面包含静态库和动态库,注意软连接
book@100ask:~/Desktop/zlib/zlib-1.2.11/install/lib$ ls -lath
total 248K
drwxrwxr-x 5 book book 4.0K Jun 18 21:46 ..
drwxrwxr-x 2 book book 4.0K Jun 18 21:46 pkgconfig
drwxrwxr-x 3 book book 4.0K Jun 18 21:46 .
lrwxrwxrwx 1 book book 14 Jun 18 21:46 libz.so -> libz.so.1.2.11
lrwxrwxrwx 1 book book 14 Jun 18 21:46 libz.so.1 -> libz.so.1.2.11
-rwxr-xr-x 1 book book 120K Jun 18 21:46 libz.so.1.2.11
-rw-r--r-- 1 book book 113K Jun 18 21:46 libz.a
检查编译结果
file libz.so.1.2.11
使用zlib的接口,只需在 链接命令后加-lz /usr/llocal/lib/libz.a
即可。
gcc -o zpipe.o -c zpipe.c
gcc -o zpipe zpipe.o -lz /usr/local/lib/libz.a