在运行时确定操作系统

8

在运行时,ISO C和POSIX都没有提供确定底层操作系统的功能。从理论上讲,这并不重要,因为C语言提供了最常见系统调用的封装。但是,在许多实际场景中,了解主机环境比C语言愿意分享的更多会更有帮助,例如,为了找到存储配置文件的位置或如何调用select()

那么,在C语言编写的应用程序中,有没有惯用的方式来确定运行时的底层操作系统呢?

至少,我能否轻松地区分Linux、Windows、BSD和MacOS?

我的当前猜测是检查某些文件/目录(例如C:\/)的存在性,但这种方法似乎不可靠。也许查询一系列此类来源可以帮助建立“操作系统指纹”的概念,从而增加可靠性。无论如何,期待您的建议。


12
嗯,你知道这些信息是在编译时确定的。 - David Heffernan
4
尝试运行程序一段时间,如果它在崩溃时被终止了,那么你用的是 Windows。如果操作系统更新到 5G 或者猫系统,那么你用的是 Mac。如果在 180 天后被黑客攻击了,那么就是 Linux。否则就是 BSD。 - Kerrek SB
2
@Philip 嗯,#ifdef在这里是必不可少的,即使你不能喜欢它,也必须学会与之共处。 - David Heffernan
3
对于你的应用程序而言,wine+linux就是windows,在Solaris上运行Linux二进制文件也就是Linux,而在BSD上运行这些文件仍然是Linux。 - Carl Norum
2
@rsaxvc 然后就取决于模拟器能否很好地成为被模拟的系统。当您在 Wine 上运行时,从程序的角度来看,操作系统是 Windows。 - David Heffernan
显示剩余14条评论
5个回答

7
实际上,大多数系统都有一个uname命令,它显示当前使用的内核。在Mac OS上,通常是“Darwin”,在Linux上只是简单的“Linux”,在Windows上是“ERROR”,而FreeBSD将返回“FreeBSD”。 更完整的uname输出列表 我相信C语言也有uname的等效命令,因此您不需要system()

看起来我赢了你们所有人 :-) - Tom van der Woerdt
@Tom 你确定在Windows上发生的事情吗?对于所有的C编译器都是这样吗? - David Heffernan
@DavidHeffernan 哈哈,我肯定它不会返回字符串"ERROR"。然而,在Windows上的结果却各不相同。据我所知,只有cygwin返回一个正确的uname,但是一些编译器可能会实际编译它。因此,在Wine或Crossover下运行uname是不可靠的。 - Tom van der Woerdt
@TomvanderWoerdt - 我发了一条消息说“你是对的,不能在所有操作系统上完成”,但后来意识到OP只是在询问BSD/OSX/Windows/Linux。 - rsaxvc

4

如果你在一个POSIX系统上,你可以从<sys/utsname.h>调用uname()。

显然,这并不是百分之百可移植的,但我认为在运行时不会有任何能够保证这一点的方法。

详情请参见手册页面


1

在程序运行时无法确定这一点,因为如果没有史诗般的修补程序,在一个平台上编译的二进制文件将无法在另一个平台上运行,因此您应该仅在与平台相关的代码周围使用#ifdef


4
-1是因为问题是关于如何在运行时确定操作系统,而不是是否应该这样做。 - rurouniwallace
是的,但这并不能帮助 OP。对于 FreeBSD 发出的大多数对象,在 Linux 上都无法使用(这适用于他的大多数情况),因此在运行时进行此操作是他最不幸的事情之一。 - richo

1

接受的答案提到了uname,但没有提供一个最小的工作示例,所以在此提供给有兴趣的人-希望它能为你节省我花费的时间:

#include <stdio.h>
#include <stdlib.h>
#include <sys/utsname.h>

int main(void) {
   struct utsname buffer;
   if (uname(&buffer) != 0) {
      perror("uname");
      exit(0);
   }
   printf("OS: %s\n", buffer.sysname);

   return 0;
}

(可能的)输出:

操作系统:Linux

PS:不幸的是,这个程序使用了一个POSIX头文件:由于缺少sys/utsname.h文件而编译失败,这很可能在Windows上无法工作。


错误 C1083:无法打开包括文件:'sys/utsname.h':没有那个文件或目录。在 Linux 上可以工作,但在 Windows 上不行。 - txs

-2
if (strchr(getenv("PATH"),'\\'))
    puts("You may be on windows...");

尽管我同意“运行时不是确定这个的时间……”


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接