首页 > 解决方案 > Linux 中的 kmemdup_nul() 和 kstrndup() 有什么区别?

问题描述

它们是相似的功能,但它们之间的确切区别是什么?Linux 文档指出:

注意:如果确切知道大小,请改用 kmemdup_nul()。

标签: clinux-kernel

解决方案


这两个函数都通过分配所需的内存kmalloc(),然后NUL在分配的缓冲区的末尾放置一个终止符。两者之间的唯一区别是kstrndup()首先调用strnlen()计算字符串的长度以及所需的大小,从而扫描字符串。

您可以将kmemdup_nul()其视为kstrndup(). 如果您已经知道字符串的长度,则可以避免初始扫描,只需kmemdup_nul()将长度作为参数传入即可。这可以节省时间,因为不需要扫描字符串,这就是您看到该注释的原因。

此外,kstrndup()如果字符串比 短,则可以节省空间max,因此,如果您不知道字符串的长度,即使kmemdup_nul()可以正常工作,您也可能需要调用kstrndup()以潜在地节省空间。

您可以从代码中清楚地看到,这两个函数之间的唯一区别是对strnlen(). 这是源代码,来自mm/util.c

/**
 * kstrndup - allocate space for and copy an existing string
 * @s: the string to duplicate
 * @max: read at most @max chars from @s
 * @gfp: the GFP mask used in the kmalloc() call when allocating memory
 *
 * Note: Use kmemdup_nul() instead if the size is known exactly.
 *
 * Return: newly allocated copy of @s or %NULL in case of error
 */
char *kstrndup(const char *s, size_t max, gfp_t gfp)
{
    size_t len;
    char *buf;

    if (!s)
        return NULL;

    len = strnlen(s, max);
    buf = kmalloc_track_caller(len+1, gfp);
    if (buf) {
        memcpy(buf, s, len);
        buf[len] = '\0';
    }
    return buf;
}
EXPORT_SYMBOL(kstrndup);

/**
 * kmemdup_nul - Create a NUL-terminated string from unterminated data
 * @s: The data to stringify
 * @len: The size of the data
 * @gfp: the GFP mask used in the kmalloc() call when allocating memory
 *
 * Return: newly allocated copy of @s with NUL-termination or %NULL in
 * case of error
 */
char *kmemdup_nul(const char *s, size_t len, gfp_t gfp)
{
    char *buf;

    if (!s)
        return NULL;

    buf = kmalloc_track_caller(len + 1, gfp);
    if (buf) {
        memcpy(buf, s, len);
        buf[len] = '\0';
    }
    return buf;
}
EXPORT_SYMBOL(kmemdup_nul);

推荐阅读