在 Linux 中生成随机 UUID

发布于 2024-08-20 07:06:48 字数 217 浏览 5 评论 0原文

我陷入了一个奇怪的困境。我需要在我的 Linux 程序(我使用 RPM 分发)中生成 UUID。我不想通过要求用户安装 libuuid 来向我的应用程序添加另一个依赖项(似乎大多数 Linux 发行版中都不包含 libuuid,例如 CentOS)。

是否没有一个标准的 Linux 系统调用可以生成 UUID(例如,在 Windows 中有 CoCreateGuid)? uuidgen 命令有什么用?

I am stuck in a strange predicament. I need to generate UUIDs in my Linux program (which I distribute using RPMs). I do not want to add another dependency to my application by requiring the user to install libuuid (seems like libuuid isn't included in most Linux distros, like CentOS).

Isn't there a standard Linux system call which generates UUIDs (like say, in Windows there CoCreateGuid)? What does the command uuidgen use?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

橘虞初梦 2024-08-27 07:06:48

我错过了什么吗?你不能:

cat /proc/sys/kernel/random/uuid

Am I missing something? Can't you:

cat /proc/sys/kernel/random/uuid
国粹 2024-08-27 07:06:48

感谢您的所有评论!

我仔细检查了每一个,下面是最适合我的要求的:

我需要的只是简单的基于时间的 UUID,这些 UUID 是为每个安装该应用程序的用户从随机数生成的。 RFC 4122 中指定的 UUID 版本 4 正是如此。我仔细研究了建议的算法,并提出了一个非常简单的解决方案,它可以在 Linux 和 Windows 中运行(也许它太简单了,但它确实满足了需求!):

srand(time(NULL));

sprintf(strUuid, "%x%x-%x-%x-%x-%x%x%x", 
    rand(), rand(),                 // Generates a 64-bit Hex number
    rand(),                         // Generates a 32-bit Hex number
    ((rand() & 0x0fff) | 0x4000),   // Generates a 32-bit Hex number of the form 4xxx (4 indicates the UUID version)
    rand() % 0x3fff + 0x8000,       // Generates a 32-bit Hex number in the range [0x8000, 0xbfff]
    rand(), rand(), rand());        // Generates a 96-bit Hex number

Thanks for all your comments!

I went through each one, and here's what suited my requirement the best:

What I needed was just plain time-based UUIDs which were generated from random numbers once for every user who installed the application. UUID version 4 as specified in RFC 4122 was exactly it. I went through a the algorithm suggested, and came up with a pretty simple solution which would work in Linux as well as Windows (Maybe its too simplistic, but it does satisfy the need!):

srand(time(NULL));

sprintf(strUuid, "%x%x-%x-%x-%x-%x%x%x", 
    rand(), rand(),                 // Generates a 64-bit Hex number
    rand(),                         // Generates a 32-bit Hex number
    ((rand() & 0x0fff) | 0x4000),   // Generates a 32-bit Hex number of the form 4xxx (4 indicates the UUID version)
    rand() % 0x3fff + 0x8000,       // Generates a 32-bit Hex number in the range [0x8000, 0xbfff]
    rand(), rand(), rand());        // Generates a 96-bit Hex number
满身野味 2024-08-27 07:06:48

我发现(对于 Linux 开发者)一个好方法是 #include。然后你就有了一些可以调用的函数:

void uuid_generate(uuid_t out);
void uuid_generate_random(uuid_t out);

A good way I found (for linux dev) is to #include <uuid/uuid.h>. Then you have a few functions you can call:

void uuid_generate(uuid_t out);
void uuid_generate_random(uuid_t out);
℉服软 2024-08-27 07:06:48

有什么理由不能静态链接到 libuuid 吗?

Is there any reason why you can't just link statically to libuuid?

荭秂 2024-08-27 07:06:48

我还不能对答案发表评论,但我只想指出,接受的答案使用 rand() 在 Windows 上根本无法正常工作,其中 RAND_MAX 被定义为 0x7fff,仅给出 15 位随机性。在 Linux 上它更高,但看起来像是 0x7fffffff,提供 31 位随机性,但仍然缺少 1 位到完整的 32 位长度。

使用 rand() 最安全的方法是依赖这样一个事实:任何地方的最低保证 RAND_MAX 值都将是 0x7fff - 多次调用它,左移 15 位并与新值进行“或”运算,直到满足要求产生一定量的随机位。

此外,sprintf 中的格式字符串应指定宽度,因此要考虑前导零(宽度基于相应参数注释中提到的位):

sprintf(strUuid, "%08x%08x-%08x-%08x-%08x-%08x%08x%08x", 
    rand(), rand(),                 // Generates a 64-bit Hex number
    rand(),                         // Generates a 32-bit Hex number
    ((rand() & 0x0fff) | 0x4000),   // Generates a 32-bit Hex number of the form 4xxx (4 indicates the UUID version)
    rand() % 0x3fff + 0x8000,       // Generates a 32-bit Hex number in the range [0x8000, 0xbfff]
    rand(), rand(), rand());        // Generates a 96-bit Hex number

此外 - 代码生成 256 位值,而不是 128 位值兼容
RFC 4122 UUID。

最后的评论:

rand() % 0x3fff + 0x8000,       // Generates a 32-bit Hex number in the range [0x8000, 0xbfff]

由于模运算符,产生的实际范围是[0x8000,0xbffe]。 % 应该是 & (或者如果使用 %,0x3fff 应该是 0x4000,但是除法总是比按位 AND 更昂贵的操作)。

这是代码的修订版本:

#include <cstdio>
#include <cstdlib>
#include <ctime>
#include <cstdint>

uint32_t rand32()
{
    return ((rand() & 0x3) << 30) | ((rand() & 0x7fff) << 15) | (rand() & 0x7fff);
}

bool gen_uuid4(char dst[37], size_t len)
{
    int n = snprintf(dst, len, "%08x-%04x-%04x-%04x-%04x%08x", 
        rand32(),                         // Generates a 32-bit Hex number
        rand32() & 0xffff,                // Generates a 16-bit Hex number
        ((rand32() & 0x0fff) | 0x4000),   // Generates a 16-bit Hex number of the form 4xxx (4 indicates the UUID version)
        (rand32() & 0x3fff) + 0x8000,     // Generates a 16-bit Hex number in the range [0x8000, 0xbfff]
        rand32() & 0xffff, rand32());     // Generates a 48-bit Hex number
        
    return n >= 0 && n < len;             // Success only when snprintf result is a positive number and the provided buffer was large enough.
}

int main()
{
    char strUuid[37];
    srand(time(NULL));
    
    bool success = gen_uuid4(strUuid, sizeof(strUuid));
    
    printf("%s\n", success ? strUuid : "UUID generation failed!");
    
    return 0;
}

I can't post comments on answers yet, but I'd just like to point out that the accepted answer's use of rand() won't work well at all on Windows, where RAND_MAX is defined as 0x7fff, giving just 15 bits of randomness. On Linux it's higher, but looks like it's 0x7fffffff, giving 31 bits of randomness, still missing 1 bit to full 32 bit length.

The safest way to use rand() would be to rely on the fact that the lowest guaranteed RAND_MAX value anywhere is going to be 0x7fff - call it multiple times, shifting left by 15 bits and OR'ing with a new value, until the required amount of random bits is produced.

Also, the format string in sprintf should have width specified, so leading zeros are taken into account (the widths are based on the mentioned bits in the respective argument comment):

sprintf(strUuid, "%08x%08x-%08x-%08x-%08x-%08x%08x%08x", 
    rand(), rand(),                 // Generates a 64-bit Hex number
    rand(),                         // Generates a 32-bit Hex number
    ((rand() & 0x0fff) | 0x4000),   // Generates a 32-bit Hex number of the form 4xxx (4 indicates the UUID version)
    rand() % 0x3fff + 0x8000,       // Generates a 32-bit Hex number in the range [0x8000, 0xbfff]
    rand(), rand(), rand());        // Generates a 96-bit Hex number

Furthermore - the code produces 256 bit values, rather than 128 bit values compatible with
RFC 4122 UUIDs.

And final comment:

rand() % 0x3fff + 0x8000,       // Generates a 32-bit Hex number in the range [0x8000, 0xbfff]

due to the modulo operator, the actual range produced is [0x8000, 0xbffe]. The % should have been & (or 0x3fff should have been 0x4000 if using %, but division is always a more expensive operation than bitwise AND).

Here's a revised version of the code:

#include <cstdio>
#include <cstdlib>
#include <ctime>
#include <cstdint>

uint32_t rand32()
{
    return ((rand() & 0x3) << 30) | ((rand() & 0x7fff) << 15) | (rand() & 0x7fff);
}

bool gen_uuid4(char dst[37], size_t len)
{
    int n = snprintf(dst, len, "%08x-%04x-%04x-%04x-%04x%08x", 
        rand32(),                         // Generates a 32-bit Hex number
        rand32() & 0xffff,                // Generates a 16-bit Hex number
        ((rand32() & 0x0fff) | 0x4000),   // Generates a 16-bit Hex number of the form 4xxx (4 indicates the UUID version)
        (rand32() & 0x3fff) + 0x8000,     // Generates a 16-bit Hex number in the range [0x8000, 0xbfff]
        rand32() & 0xffff, rand32());     // Generates a 48-bit Hex number
        
    return n >= 0 && n < len;             // Success only when snprintf result is a positive number and the provided buffer was large enough.
}

int main()
{
    char strUuid[37];
    srand(time(NULL));
    
    bool success = gen_uuid4(strUuid, sizeof(strUuid));
    
    printf("%s\n", success ? strUuid : "UUID generation failed!");
    
    return 0;
}
烟酉 2024-08-27 07:06:48

也许ooid会有所帮助? http://ooid.sourceforge.net/

Perhaps ooid will help? http://ooid.sourceforge.net/

盗心人 2024-08-27 07:06:48

POSIX 中不存在用于生成 UUID 的系统调用,但我想您可以在某个地方找到 BSD/MIT 代码来生成 UUID。 ooid 是根据 Boost 软件许可证发布的,根据维基百科,该许可证是 BSD/MIT 风格的宽松许可证。然后您只需将其粘贴到您的应用程序中,无需添加依赖项。

No system call exists in POSIX to generate UUID, but I guess you can find somewhere a BSD/MIT code to generate the UUID. ooid is released under the Boost software license, which according to wikipedia, is a permissive license in the style of BSD/MIT. Then you can just paste it into your application, without any need to add dependencies.

心凉怎暖 2024-08-27 07:06:48

uuidgen 在我的 ubuntu linux dist 上工作得很好。

uuidgen on my ubuntu linux dist works just fine.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文