在c编程中生成一致的机器唯一ID

在c编程中生成一致的机器唯一ID

是否可以生成一个唯一的 ID,除非硬件发生变化,否则该 ID 不会随时间而改变。硬件必须用 ac 程序生成。

如果它能够抵御 MAC 地址或硬盘序列号欺骗等欺骗行为,那就太好了。但这并不是绝对的要求。

我需要这样一个ID,以便从许多不同的计算机收集软件数据进行统计。

我已经读过很多类似的帖子,比如这篇: 生成一致的机器唯一ID;但它们不适合我的需要。

我需要这个程序以普通用户身份运行,所以我不能使用像“dmidecode”之类的命令。即使我除了使用 MAC 地址之外没有其他解决方案,我也不希望用户从 Wifi 切换到以太网时 UUID 发生变化,因此仅采用第一个 MAC 地址可能会出现问题。最重要的是,即使安装了 VMware 或 VPN,UUID 也必须保持相同。因此,获取所有 mac 地址都不是一种选择,因为以前的工具会生成更多网络接口和更多 mac 地址,从而更改 UUID。

我还希望它能够在虚拟机上工作,生成的来宾 uuid 应该与主机不同。

我什至不知道这个问题是否有这样的解决方案。但我的想法是仅通过读取 sys/class/net/*/addresses 来获取所有物理现有硬件接口的 MAC 地址。然后附加所有 mac 地址并使用 sha1 对其进行哈希处理以生成 UUID。但是我怎样才能过滤曲目以仅选择正在变化的曲目。我能否确定他们的 orderrer 不会被交换,从而更改附加的字符串以及 UUID。

否则,我可以在没有root权限和第三方工具的情况下检索硬盘序列号吗? (如果我能找到第三方软件的来源就可以了)

任何其他解决方案也将非常受欢迎。

PS:它必须与内核 2.6 或更高版本的任何 Linux 版本兼容

答案1

简短回答

根据我所有的研究和尝试,我想说,不可能制作一个程序来生成遵守以下约束的唯一 ID。

  • 如果在同一台计算机上生成,则每次 ID 必须相同。
  • 如果在不同的计算机上生成,ID 必须不同。
  • 该程序必须以用户身份运行。
  • 该程序必须与任何具有 2.6 内核版本或更高版本的 Linux 发行版兼容
  • 如果计算机被修改(例如:硬件更换),ID 可能会有所不同
  • 该程序不应依赖必须安装在计算机上的第三方工具

长答案

在这里我将展示我对 mac 地址的尝试。

这里的目标是找到一种方法来检索所有物理网络接口的地址。作为普通用户,我发现查找 MAC 地址的最简单方法是读取“/sys”目录中的系统文件。这些文件从 linux 2.6 开始就可用,所以这是完美的。

我的研究让我了解了这些规则: https://www.kernel.org/doc/Documentation/sysfs-rules.txt

不可能按照这些规则中的建议使用 udev 库,因为它必须从外部添加。所以我深入研究了可以在这里找到的源代码:http://cgit.freedesktop.org/systemd/systemd/tree/src/libudev

我从中学到的是,要检索 mac 地址,您应该查找“sys/subsystem”,如果存在,则在其中查找“net”目录,您将找到每个网络接口的目录。如果没有“subsystem”文件夹,则必须在“sys/class”、“sys/bus”和“sys/block”文件夹中查找“net”目录。事实上,我总是在“课堂”中找到它们,但规则说不应该期望这样。

上面我说过,在“net”文件夹中,您会找到网络目录,但这并不完全正确。在linux 2.6(我使用RHEL 4)上,它是目录,在其中您会发现“address”文件,其中包含mac地址和指向“sys/devices”中目录的符号链接。如果在更高的 Linux 版本上,它将直接是指向“/sys/devices”中目录的符号链接,您将在其中找到“address”文件。 (我尝试过 RHEL 6、Debian 7、Debian 8、Ubuntu 15 和内核更新为 linux 4.3 的 Ubuntu 15)

即使在新的 linux 版本(4.3)中我也从未见过“/sys/subsystem”目录。

sysfs 的新布局( >= linux 3) :为了区分物理接口和虚拟接口,我想查看设备的 devpath。我在“/sys/class/net”中的符号链接指向这些目录:

  • “/sys/devices/pci0000:00/0000:00:11.0/0000:02:01.0/net/eth0”
  • “/sys/devices/virtual/net/eth1”

eth1 是我根据本主题创建的一个虚拟虚拟网卡:如何在没有物理适配器的计算机上创建虚拟以太网接口?

因此,您可以看到虚拟文件夹位于“虚拟”文件夹中,这就是区分它们的方法。

sysfs 的旧布局(Linux 2.6):

虚拟网络接口的目录中没有“设备”符号链接。

你会发现“/sys/class/net/eth0/device -> /sys/devices....”但是如果有虚拟eth1,那么“/sys/class/net/eth1”中就不会有这样的符号链接。


总而言之,使用“opendir”、“readdir”、“access('...',F_OK)”、“fopen”.. 您只能检索物理接口的 mac 地址。

然后对它们进行排序,确保它们以相同的顺序出现,然后将所有内容附加到缓冲区中并使用 openssl 中的 SHA1,进行一些解析以使其看起来像 UUID,然后就可以开始了。

但问题是,我不想依赖这样一个事实:网络设备的 devpath 中的任何位置都会有一个“虚拟”文件夹。上面链接的规则中从未说过情况总是如此。所以这个问题不能这样回答。

我希望我所有的研究都能帮助别人。

相关内容