アプリケーションにエクスポートするカーネルメモリーを割り当てるには、ddi_umem_alloc (9F) を使用します。ddi_umem_alloc() で使用される構文は、次のとおりです。
void *ddi_umem_alloc(size_t size, int flag, ddi_umem_cookie_t *cookiep);
ここでは:
割り当てるバイト数。
スリープ条件やメモリータイプを決定するために使用されます。
カーネルメモリー cookie へのポインタ。
ddi_umem_alloc(9F) は、ページ境界割り当てされたカーネルメモリーを割り当てます。ddi_umem_alloc() は、割り当てられたメモリーへのポインタを返します。最初、メモリーにはゼロが設定されます。割り当てられるバイト数はシステムページサイズの倍数であり、size パラメータから切り上げられます。割り当てられたメモリーは、カーネル内で使用してもかまいません。このメモリーは、アプリケーションにもエクスポートできます。cookiep は、割り当てられるカーネルメモリーを記述するカーネルメモリー cookie へのポインタです。cookiep は、ドライバがカーネルメモリーをユーザーアプリケーションにエクスポートするときに、devmap_umem_setup (9F) で使用されます。
flag 引数は、ddi_umem_alloc(9F) がブロックするかそれともすぐにリターンするのかと、割り当てられるカーネルメモリーがページング可能かどうかを示します。flag 引数の値は次のとおりです。
ドライバは、メモリーが使用可能になるまで待機する必要はありません。メモリーが使用可能でない場合は NULL を返します。
ドライバは、メモリーが使用可能になるまで無期限に待機できます。
ドライバは、メモリーのページアウトを許可します。これを設定しないと、メモリーがロックダウンされます。
ddi_umem_lock() 関数は、デバイスロックメモリーのチェックを実行できます。 この関数は、project.max-locked-memory に指定された制限値に基づいてチェックします。現在のプロジェクトのロックメモリー使用量が制限値を下回っている場合、そのプロジェクトのロックメモリーバイト数が増やされます。制限チェックのあとでメモリーがロックされます。ddi_umem_unlock() 関数を呼び出すとメモリーのロックが解除され、プロジェクトのロックメモリーバイト数が減らされます。
使用されるアカウンティング方式は、精度の低いフルプライスモデルです。たとえば、オーバーラップしたメモリー領域を含む同一プロジェクト内で umem_lockmemory() を呼び出した 2 つの呼び出し元は、2 回課金されます。
ゾーンがインストールされた Oracle Solaris システムの project.max-locked-memory および zone.max-locked_memory リソース制御については、Resource Management and Oracle Solaris Zones Developer’s Guide のほか、resource_controls (5) も参照してください。
次の例は、アプリケーションアクセス用のカーネルメモリーを割り当てる方法を示したものです。ドライバは、複数のアプリケーションによって共有メモリー領域として使用される 1 枚のカーネルメモリーページをエクスポートします。メモリーの割り当ては、アプリケーションが共有ページをはじめてマップしたときに segmap (9E) 内で行われます。ドライバが複数のアプリケーションデータモデルをサポートする必要がある場合には、追加のページが割り当てられます。たとえば、64 ビットドライバが、64 ビットアプリケーションと 32 ビットアプリケーションの両方にメモリーをエクスポートするとします。このとき、64 ビットアプリケーションが 1 枚目のページを共有し、32 ビットアプリケーションが 2 枚目のページを共有します。
使用例 10-4 ddi_umem_alloc() ルーチンの使用static int
xxsegmap(dev_t dev, off_t off, struct as *asp, caddr_t *addrp, off_t len,
unsigned int prot, unsigned int maxprot, unsigned int flags,
cred_t *credp)
{
int error;
minor_t instance = getminor(dev);
struct xxstate *xsp = ddi_get_soft_state(statep, instance);
size_t mem_size;
/* 64-bit driver supports 64-bit and 32-bit applications */
switch (ddi_mmap_get_model()) {
case DDI_MODEL_LP64:
mem_size = ptob(2);
break;
case DDI_MODEL_ILP32:
mem_size = ptob(1);
break;
}
mutex_enter(&xsp->mu);
if (xsp->umem == NULL) {
/* allocate the shared area as kernel pageable memory */
xsp->umem = ddi_umem_alloc(mem_size,
DDI_UMEM_SLEEP | DDI_UMEM_PAGEABLE, &xsp->ucookie);
}
mutex_exit(&xsp->mu);
/* Set up the user mapping */
error = devmap_setup(dev, (offset_t)off, asp, addrp, len,
prot, maxprot, flags, credp);
return (error);
}