> For the complete documentation index, see [llms.txt](https://book.bsdcn.org/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://book.bsdcn.org/man/man9/hashalloc.9.md).

# hashalloc.9

`hashalloc` — 分配和释放内核哈希表

## 名称

`hashalloc`, `hashfree`

## 概要

```c
#include <sys/malloc.h>
```

```c
#include <sys/hash.h>
```

```c
void *
hashalloc(struct hashalloc_args *args)
void
hashfree(void *table, struct hashalloc_args *args)
```

## 描述

`hashalloc` 和 `hashfree` 函数提供了灵活的内核编程接口 (KPI)，用于分配和释放具有可配置桶头的哈希表。

`hashalloc` 根据 `args` 结构中指定的参数为哈希表分配内存。它计算适当的桶数（根据请求的 `type` 调整 `args->size`），使用 [malloc(9)](/man/man9/malloc.9.md) 分配内存，初始化每个桶的队列头（例如 `LIST_HEAD`、`TAILQ_HEAD` 等），如果请求则初始化每桶锁。返回的内存分配可用作头结构数组，这些头结构以请求类型的已初始化列表头开始，后跟请求类型的已初始化锁。

`hashfree` 释放先前由 `hashalloc` 分配的哈希表。

这两个函数都要求调用者传递相同（或等效）的 `struct hashalloc_args`，该结构指定哈希表的所需配置，具有以下成员：

```c
struct hashalloc_args {
    /* 必需参数 */
    size_t  size;          /* 输入：所需桶数，输出：已分配 */
    int     mflags;            /* malloc(9) 标志 */
    struct malloc_type *mtype; /* malloc(9) 类型 */
    /* 可选参数 */
    size_t  hdrsize;            /* 桶头大小；0 = 自动 */
    enum {
        HASH_TYPE_POWER2,
        HASH_TYPE_PRIME,
    }       type;               /* 默认 HASH_TYPE_POWER2 */
    enum {
        HASH_HEAD_LIST,
        HASH_HEAD_CK_LIST,
        HASH_HEAD_SLIST,
        HASH_HEAD_CK_SLIST,
        HASH_HEAD_STAILQ,
        HASH_HEAD_CK_STAILQ,
        HASH_HEAD_TAILQ,
    }       head;               /* 默认 HASH_HEAD_LIST */
    enum {
        HASH_LOCK_NONE,
        HASH_LOCK_MTX,
        HASH_LOCK_RWLOCK,
        HASH_LOCK_SX,
        HASH_LOCK_RMLOCK,
        HASH_LOCK_RMSLOCK,
    }       lock;               /* 默认 HASH_LOCK_NONE */
    int     lopts;              /* 锁初始化选项 */
    const char *lname;          /* 锁名称 */
    int  (*ctor)(void *);	/* 桶构造函数 */
    void (*dtor)(void *);	/* 桶析构函数 */
    /* 返回参数 */
    int error;                  /* 失败时的错误代码 */
};
```

`hashalloc` 需要参数成员 `size`、`mflags` 和 `mtype`。`hashfree` 需要参数 `size`（由先前调用 `hashalloc` 填充）和 `mtype`。其余参数是可选的并具有合理的默认值。以非默认分配参数分配的哈希表应向 `hashfree` 传递相同的参数。该结构应使用稀疏 C99 初始化器初始化，因为它可能包含不透明的扩展成员。该结构可在调用者的栈上分配。

**`HASH_TYPE_POWER2`** 向上取整到小于或等于参数 `size` 的最大 2 的幂。

**`HASH_TYPE_PRIME`** 调整到小于或等于参数 `size` 的最大质数。

**`HASH_HEAD_LIST`** [queue(3)](/man/misc/queue.3.md) `LIST_HEAD`

**`HASH_HEAD_CK_LIST`** Concurrency-kit `CK_LIST_HEAD`

**`HASH_HEAD_SLIST`** [queue(3)](/man/misc/queue.3.md) `SLIST_HEAD`

**`HASH_HEAD_CK_SLIST`** Concurrency-kit `CK_SLIST_HEAD`

**`HASH_HEAD_STAILQ`** [queue(3)](/man/misc/queue.3.md) `STAILQ_HEAD`

**`HASH_HEAD_CK_STAILQ`** Concurrency-kit `CK_STAILQ_HEAD`

**`HASH_HEAD_TAILQ`** [queue(3)](/man/misc/queue.3.md) `TAILQ_HEAD`

**`HASH_LOCK_NONE`** 无每桶锁。

**`HASH_LOCK_MTX`** 每桶 [mutex(9)](/man/man9/mutex.9.md)。

**`HASH_LOCK_RWLOCK`** 每桶 [rwlock(9)](/man/man9/rwlock.9.md)。

**`HASH_LOCK_SX`** 每桶 [sx(9)](/man/man9/sx.9.md)。

**`HASH_LOCK_RMLOCK`** 每桶 [rmlock(9)](/man/man9/rmlock.9.md)。

**`HASH_LOCK_RMSLOCK`** 每桶可休眠 (rms) [rmlock(9)](/man/man9/rmlock.9.md)。

**`size`** `hashalloc` 所需的桶数。成功返回时，`hashalloc` 将此成员设置为实际分配的数量（可能向上取整到 2 的幂或最近的质数）。`hashalloc` 返回的值应随后提供给 `hashfree`。

**`mflags`**, `mtype` 直接传递给 [malloc(9)](/man/man9/malloc.9.md)。

**`hdrsize`** 允许调用者设置不同（增大）桶头大小的可选成员。

**`type`** 桶计数策略：默认为 `HASH_TYPE_POWER2`。

**`head`** 每个桶的队列头类型，[queue(3)](/man/misc/queue.3.md) 或 Concurrency-kit (CK) 类型。默认为 `HASH_HEAD_LIST`。

**`lock`** 同步：默认为 `HASH_LOCK_NONE`。

**`lopts`** 传递给 mtx\_init(9)、rw\_init(9)、sx\_init(9)、rm\_init(9) 或 rms\_init(9) 的选项（如果启用了锁定）。

**`lname`** 锁名称。除非 `lock` 为 `HASH_LOCK_NONE`，否则此成员是必需的。

**`ctor`** 可选构造函数，由 `hashalloc` 在列表头和锁初始化后为每个桶调用。可能因错误代码失败，导致 `hashalloc` 失败。

**`dtor`** 可选析构函数，由 `hashfree` 在锁析构函数和列表空检查之前为每个桶调用。

## 返回值

`hashalloc` 成功时返回指向已分配并初始化的哈希表的指针，内存分配失败或构造函数失败时返回 `NULL`。`args` 的 `error` 成员设置为适当的错误代码。当 `args` 中的 `mflags` 包含 `M_WAITOK` 标志且 `ctor` 为 NULL 或从不失败时，`hashalloc` 从不失败。

## 实例

使用 TAILQ 桶的简单互斥锁保护哈希表：

```c
struct bucket {
    TAILQ_HEAD(, foo)   head;
    struct mtx          lock;
} *table;
struct hashalloc_args args = {
    .size    = 9000,
    .mflags  = M_WAITOK,
    .mtype   = M_FOO,
    .head    = HASH_HEAD_TAILQ,
    .lock    = HASH_LOCK_MTX,
    .lopts   = MTX_DEF,
    .lname   = "bucket of foo",
};
table = hashalloc(&args);
/* 将 table 用作 struct bucket 数组 ... */
mtx_lock(&table[hash].lock);
TAILQ_INSERT_HEAD(&table[hash].head, foo, next);
/* 稍后 */
hashfree(table, &args);
```

## 参见

[malloc(9)](/man/man9/malloc.9.md), [mutex(9)](/man/man9/mutex.9.md), [rmlock(9)](/man/man9/rmlock.9.md), [rwlock(9)](/man/man9/rwlock.9.md), [sx(9)](/man/man9/sx.9.md), [queue(3)](/man/misc/queue.3.md)

## 历史

`hashfree` KPI 首次出现于 FreeBSD 16.0。它取代了自 4.4BSD 以来可用的旧接口 `hashinit`，通过提供对哈希表结构和锁定策略的更大控制。

## 作者

Gleb Smirnoff <glebius@FreeBSD.org>


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://book.bsdcn.org/man/man9/hashalloc.9.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
