Tl;博士
如果您需要获取使用 usleep() 进行编译的旧代码,请将这些行添加到您在任何其他库之前包含的头文件中:
#define _XOPEN_SOURCE 600
#define _POSIX_C_SOURCE 200112L
或者将编译器标志 -std=c11 -D_XOPEN_SOURCE=600 -D_POSIX_C_SOURCE=200112L 添加到您的 makefile。
这告诉环境您的程序使用this older version of the UNIX API,其中usleep() 未被弃用。
或者——如果这是新代码,肯定会——用nanosleep()替换usleep(),为您的库版本适当地设置功能测试宏,并检查您的代码库是否有其他位损坏。
在 Linux 上,您可以在 man feature_test_macros 中检查您的库支持的 _XOPEN_SOURCE 和 _POSIX_C_SOURCE 的值。
完整的图片
更长的答案:这就是发生的事情。
历史上有几种不同的 UNIX 标准,最终每个人都想到的最佳实践是让代码指定它是为哪个版本的 UNIX API 编写的。程序员通过定义一个功能测试宏来做到这一点。
UNIX 中最早的分裂之一是 AT&T 的 System V 和加州大学的伯克利标准发行版 (BSD)。由于 System V 是正式版本并且其行为成为默认设置,而 BSD Unix 是一些最早的免费软件并在许多大学中使用,因此看到遗留代码声明 _BSD_SOURCE 比 _SVID_SOURCE 更常见。 _BSD_SOURCE 宏特别尝试在 40 多年的时间里启用来自各种不同操作系统的扩展。有时,它甚至被用作非标准扩展的包罗万象。这两个宏都已弃用,并且与当前接受的答案相反,您不应该在新代码中使用任何一个。
在本世纪,有两个 UNIX 标准,POSIX 成为 IEEE 标准,以及来自开放组 (X/Open) 的单一 Unix 规范 (SUS)。 X/Open SUS 是 POSIX 的超集,也是您通常编写的内容。曾经有许多不同的功能测试宏,您可以声明它们以启用这些标准的当前版本,并且仍然支持这些宏以实现向后兼容性。您可以在粘贴的条件中看到其中一些,但在编写新代码时无需担心它们。代码检查的一个宏 _XOPEN_SOURCE_EXTENDED 现在已过时,但历史上选择了 1995 年的 SUS 版本。
理论上,在任何现代版本的 UNIX 或 Linux 上设置的正确功能测试宏是 _XOPEN_SOURCE。您应该查找您的库支持的最新版本号。在实践中,我认为同时定义_POSIX_C_SOURCE 是一种谨慎的防御性编码,以保证没有其他人可以不一致地设置它并破坏你的代码。您的问题就是一个很好的例子:如果您将 _XOPEN_SOURCE 设置为向后兼容,但将 _POSIX_C_SOURCE 设置为工具链中其他位置的更新版本,则较高版本的 _POSIX_C_SOURCE 将优先,usleep() 不会工作。
所以,这些条件的意思是 usleep() 不是一个 POSIX 函数,但曾经出现在一些类似 BSD 的操作系统上,因此它在 1995 年进入了 SUS。它在 2008 年被弃用,并且从那时起,选择任何版本的 POSIX 或 SUS 都会主动禁用它。因此,如果您选择 SUS 的 500 或 600 版本(并且另一个过时的同义词也将其打开),则启用它,但如果您选择任何最新版本的 POSIX 或 SUS,则不推荐使用。如果您选择随心所欲选项,它们也会启用,但这是个坏主意。