openssl之BIO系列之15---記憶體(mem)類型BIO,openssl15---
mem類型BIO
---根據openssl doc\crypto\bio_s_mem.pod翻譯和自己的理解寫成
(作者:DragonKing, Mail: wzhah@263.net ,發佈於:http://gdwzh.126.com之open
ssl專業論壇)
記憶體(mem)類型BIO所定義的相關係列函數如下(openssl\bio.h):
BIO_METHOD * BIO_s_mem(void);
BIO_set_mem_eof_return(BIO *b,int v)
long BIO_get_mem_data(BIO *b, char **pp)
BIO_set_mem_buf(BIO *b,BUF_MEM *bm,int c)
BIO_get_mem_ptr(BIO *b,BUF_MEM **pp)
BIO *BIO_new_mem_buf(void *buf, int len);
記憶體型BIO是source/sink型BIO,它使用記憶體作為它的I/O。寫進該類型BIO的資料被
儲存在BUF_MEM結構中,該結構被定義為適合儲存資料的一種結構,其結構定義如下:
typedef struct buf_mem_st
{
int length; /* current number of bytes */
char *data;
int max; /* size of buffer */
} BUF_MEM;
可見,該結構定義了記憶體資料長度,資料存放區空間以及最大長度三個變數來表述一
段記憶體儲存資料。但值得注意的是,記憶體型BIO的記憶體是可以無限擴大的,也就是說,不
過你往裡面寫多少資料,都能成功執行。
一般來說,任何寫入記憶體型BIO的資料都能被讀出,除非該記憶體型BIO是唯讀類型的
,那麼,這時候如果對唯讀記憶體型BIO執行讀操作,那麼相關資料就會從該BIO刪除掉
(其實沒有刪掉,只是指標往後面移動,訪問不了了,如果調用BIO_reset就可以再訪問
)。
【BIO_s_mem】
該函數返回一個記憶體型的BIO_METHOD結構,期定義如下:
static BIO_METHOD mem_method=
{
BIO_TYPE_MEM,
"memory buffer",
mem_write,
mem_read,
mem_puts,
mem_gets,
mem_ctrl,
mem_new,
mem_free,
NULL,
};
BIO_write和BIO_read函數是支援的。對記憶體型BIO執行寫操作總是成功的,因為內
存型BIO的記憶體能夠無限擴大。任何一個對可讀寫的記憶體型BIO的讀操作都會在使用內部
拷貝操作從BIO裡面刪除該段資料,這樣一來,如果BIO裡面有大量的資料,而讀的卻只
是很小的一些片斷,那麼會導致操作非常慢。使用唯讀記憶體型BIO避免了這個問題。在
使用的時候,如果記憶體型BIO必須使用可讀寫的,那麼可以加一個Buffer型BIO到BIO鏈中
,這可以使操作速度更快。在以後的版本(該文檔所述版本為0.9.6a),可能會最佳化速度
操作的問題。
BIO_gets和BIO_puts操作在該類型BIO是支援的。
如果設定了BIO_CLOSE標誌,那麼記憶體型BIO被釋放的時候其底層的BUF_MEM型BIO也
同時被釋放。
BIO_reset函數被調用時,如果該BIO是可讀寫的,那麼該BIO所有資料都會被清空;
如果該BIO是唯讀,那麼該操作只會簡單將指標指向原始位置,裡面的資料可以再讀。
該文檔所述版本的(0.9.6a)的記憶體型BIO對讀寫入模式的BIO沒有提供一個可以將指標重
置但不破壞原有資料的方法,在以後的版本可能會增加的。
BIO_eof返回true,表明只時候BIO裡面沒有可讀資料。
BIO_ctrl_pending返回目前BIO裡面儲存的資料的位元組(byte)數。
【BIO_set_mem_eof_return】
該函數設定一個沒有資料的記憶體型BIO的執行讀動作的行為。如果參數v是0,那麼該
空的記憶體型BIO就會返回EOF,也就是說,這時候返回為0,如果調用BIO_should_retry就
會返回false。如果參數v為非零,那麼就會返回v,並且同時會設定重試標誌,也就是說
此時調用BIO_read_retry會返回true。為了跟正常的返回正值避免混淆,v應該設定為負
值,典型來說是-1。
【BIO_get_mem_data】
該函數是一個宏定義函數,它將參數pp的指標指向記憶體型BIO的資料開始處,返回所
有有效資料。
【BIO_set_mem_buf】
該函數將參數bm所代表的BUF_MEM結構作為該BIO的底層結構,並把關閉標誌設定為
參數c,c可以是BIO_CLOSE或BIO_NOCLOSE,該函數也是一個宏定義。
【BIO_get_mem_ptr】
該函數也是一個宏定義函數,它將底層的BUF_MEM結構放在指標pp中。
【BIO_new_mem_buf】
該函數建立一個記憶體型BIO,其資料為buf裡面長度為len的資料(單位為byte),如
果參數len是-1,那麼就預設buf是以null結束的,使用strlen解決長度。這時候BIO被
設定為唯讀,不能執行寫操作。它用於資料需要儲存在一塊靜態記憶體中並以BIO形式存
在的時候。所需要的資料是直接從記憶體中讀取的,而不是先要執行拷貝操作(讀寫方式
的記憶體BIO就是要先拷貝),這也就要求這塊記憶體是唯讀,不能改變,一直維持到BIO
被釋放。
【例子】
1.建立一個記憶體型BIO並寫入資料
BIO *mem = BIO_new(BIO_s_mem());
BIO_puts(mem, "Hello World\n");
2.建立一個唯讀記憶體型BIO
char data[] = "Hello World";
BIO *mem;
mem = BIO_new_mem_buf(data, -1);
3.把一個BUF_MEM結構從一個BIO中取出並釋放該BIO
BUF_MEM *bptr;
BIO_get_mem_ptr(mem, &bptr);
BIO_set_close(mem, BIO_NOCLOSE); /* BIO_free() 不釋放BUF_MEM結構 */
BIO_free(mem);