naobe @ ウィキ

apr(Apatch Portable Runtime)

最終更新:

Bot(ページ名リンク)

- view
管理者のみ編集可
Apacheに戻る

参考URL


概要

OS(Unix,Windows,beos,netware,os2,AIX,os360)に関係なく、Cのruntimeを統一したインタフェースで扱えるようにしたライブラリ。すべてのOSについて完全には使えない。オープンソースなので、不足しているところは使用者にまかせるスタンス。
メモリ、スレッド、文字列、ファイル、ハッシュ、ロックなどのインタフェースがある。

メモリ管理

 メモリプールを作成してその中から必要なメモリを供給する。メモリが必要になったら、apr_pallocを呼ぶ。apr_pallocを呼ぶとallocatorに保管しているメモリを返す(apr_pool_destroyを使ってpoolを開放するとallocatorにメモリを保管する)。allocatorにメモリがない場合は、4KBでアラインした領域をmallocしてpoolにリンクして返す。apr_pool_destroyを使ってメモリを開放してもデフォルトでは、OSにまったく返却しない。返却したプールは、アロケータに保管して必要になったときに再使用する。
 4KB(たぶんページサイズ)区切りで大き目にメモリをmallocするため、フラグメントを軽減する。またallocatorに保管して再利用するためシステムコールを発行する回数が減る。

 以下の関数でアロケータの持つ最大メモリ容量を設定しておくと、allocatorに返却したメモリの合計が最大メモリ容量を超えたら、それ以後はOSにfreeして返す。allocatorからメモリを獲得するとallocatorの空き容量が増えて、その分はOSに返却しないでallocatorに保管する。

void apr_allocator_max_free_set 	( 	apr_allocator_t *allocator,	apr_size_t size )

sizeは、要求メモリサイズを4KBで割ったもの

メモリの返却は、pool単位で明示的に行わなければならない。 JavaのGCのように自動的に返却するものではい。

【ソース解読】
ApachePortableRuntime.xls

array

C言語の配列は、あらかじめサイズを決めておいてその範囲内で使う。aprのarrayは、サイズが不足すると内部で自動的にサイズを拡張する。スタックとしても使える。

 apr_array_header_t* apr_array_make(apr_pool_t *p, int nelts, int elt_size 	) 	
配列を作成する。pはプール、neltsは配列の初期サイズ。初期サイズを超えて要素を追加すると、内部で自動的にサイズを増やす(サイズを倍にする)。elt_sizeは要素のサイズ。

 struct apr_array_header_t {
   /** The pool the array is allocated out of */
   apr_pool_t *pool;
   /** The amount of memory allocated for each element of the array */
   int elt_size;
   /** The number of active elements in the array */
   int nelts;
   /** The number of elements allocated in the array */
   int nalloc;
   /** The elements in the array */
   char *elts;
 };
戻り値のapr_array_header_tは、配列本体。neltsは、登録した要素の数。nallocは配列の容量(要素の数)、要素を格納するために取得したメモリの数(単位は、elt_size)。eltsは配列の先頭ポインタ。直接eltsを操作して要素を取得する。

 void* apr_array_push(apr_array_header_t *arr)
配列に要素を格納するために使用する。配列の次の登録位置を返す。

 void* apr_array_pop(apr_array_header_t *arr)
配列の末尾要素の位置を返す。また登録要素数をデクリメントする。

要素の削除。更新機能はない。裸で配列をさらしているので、自由に操作してということか。


【サンプルプログラム】
 #include <stdlib.h>
 
 #include <apr_file_io.h>
 #include <apr_strings.h>
 #include <apr_tables.h>
 
 // 配列初期サイズ
 #define INIT_ARRAY_SIZE 3
 
 static apr_file_t *apr_stdout, *apr_stdin, *apr_stderr;
 
 int main(int argc, const char * const *argv) {
 	apr_pool_t *p;
 	int i;
 
 	apr_app_initialize(&argc, &argv, NULL);
 	apr_pool_create(&p, NULL);
 
 	apr_file_open_stdout(&apr_stdout, p);
 	apr_file_open_stdin(&apr_stdin, p);
 	apr_file_open_stderr(&apr_stderr, p);
 
 	// array作成
 	apr_array_header_t *arr =
 			apr_array_make(p, INIT_ARRAY_SIZE, sizeof(char *));
 
 	//  要素追加
 	*(const char **) apr_array_push(arr) = apr_pstrdup(p, "aaa");
 	*(const char **) apr_array_push(arr) = apr_pstrdup(p, "bbb");
 	*(const char **) apr_array_push(arr) = apr_pstrdup(p, "ccc");
 	APR_ARRAY_PUSH(arr, const char *) = apr_pstrdup(p, "ddd");
 	APR_ARRAY_PUSH(arr, const char *) = apr_pstrdup(p, "eee");
 
 	apr_file_printf(apr_stdout, "配列サイズ:%d\n", arr->nelts);
 
 	//  一覧表示
 	for (i = 0; i < arr->nelts; i++) {
 		char *ptr = ((char **)arr->elts)[i];
 		apr_file_printf(apr_stdout, "push element:%s\n", ptr);
 	}
 
 	apr_file_printf(apr_stdout, "\n");
 
 	// pop
 	char **elm;
 	while(elm = apr_array_pop(arr)) {
 		apr_file_printf(apr_stdout, "pop element:%s\n", *elm);
 	}
 
 	apr_file_printf(apr_stdout, "配列サイズ:%d\n", arr->nelts);
 
 	apr_file_printf(apr_stdout, "\n");
 
 	apr_pool_destroy(p);
 	apr_terminate();
 
 	return EXIT_SUCCESS;
 }

コマンドオプション

以下の関数を使って、コマンドオプションを取得する

 APR_DECLARE(apr_status_t) apr_getopt_init(apr_getopt_t **os, apr_pool_t *cont, int argc, const char *const *argv)
 APR_DECLARE(apr_status_t) apr_getopt(apr_getopt_t *os, const char *opts, char *optch, const char **optarg)

apr_getopt_initを使ってメモリプールからapr_getopt_tを作成する。apr_getopt_tには引数が格納されている。apr_getoptを順次使うと、指定したオプションの値をoptch, optargに格納する。例えば、command -a aaaと指定するとoptchは、'a'でoptargは、'aaa'になる。

【サンプルプログラム】
 #include <stdlib.h>
 
 #include <apr_file_io.h>
 #include <apr_strings.h>
 #include <apr_getopt.h>
 
 static apr_file_t *apr_stdout, *apr_stdin, *apr_stderr;
 
 int main(int argc, const char * const *argv) {
apr_pool_t *p;
apr_getopt_t *os;
char ch;
const char *arg;
 
apr_app_initialize(&argc, &argv, NULL);
apr_pool_create(&p, NULL);
 
apr_file_open_stdout(&apr_stdout, p);
apr_file_open_stdin(&apr_stdin, p);
apr_file_open_stderr(&apr_stderr, p);
 
// getopt初期化
apr_getopt_init(&os, p, argc, argv);
 
while(apr_getopt(os,"a:b:cd",&ch, &arg) == APR_SUCCESS) {
	switch (ch) {
		case 'a':
		case 'b':
			apr_file_printf(apr_stdout, "option char: %c, option arg: %s\n", ch, arg);
			break;
		default:
			apr_file_printf(apr_stdout, "option char: %c\n", ch);
			break;
	}
}
 
apr_pool_destroy(p);
apr_terminate();
 
return EXIT_SUCCESS;
 }
添付ファイル
人気記事ランキング
ウィキ募集バナー