C - 函数 Usleep 的隐式声明

  • 本文关键字:声明 Usleep 函数 c usleep
  • 更新时间 :
  • 英文 :

gcc (GCC) 4.6.3
c89

我正在尝试使用usleep.但是,我不断收到以下警告:

功能usleep的隐式声明

我已经包含了unistd.h头文件。

手册页提到了一些关于这一点的内容。但我不确定我是否理解它:

usleep():
   Since glibc 2.12:
       _BSD_SOURCE ||
           (_XOPEN_SOURCE >= 500 ||
               _XOPEN_SOURCE && _XOPEN_SOURCE_EXTENDED) &&
           !(_POSIX_C_SOURCE >= 200809L || _XOPEN_SOURCE >= 700)
   Before glibc 2.12:
       _BSD_SOURCE || _XOPEN_SOURCE >= 500 || _XOPEN_SOURCE && _XOPEN_SOURCE_EXTENDED

但不确定我如何处理上述内容?

该列表是定义usleep的先决条件。它基本上是一个类似 C 的表达式,涉及#define变量,在包含头文件之前必须为 true。

头文件本身只会在通常是大量#ifdef语句巢中定义usleep,开发人员已经花时间告诉您需要做什么,这样您就不必花费数小时试图自己弄清楚:-(

假设您使用的是 2.12 或更高版本的glibc,这意味着您必须:

  • 声明_BSD_SOURCE;或
  • 声明其他三件事的复杂组合,我不会费心去解码。

可能最简单的解决方法是简单地使用 gcc -D _BSD_SOURCE 或 put 进行编译:

#define _BSD_SOURCE

在包含头文件之前的代码中,该文件为您提供usleep .

您可能希望在任何包含之前定义这些内容,以防各种头文件之间存在依赖关系。

这可能有效:在 Linux 上使用 gcc 编译时添加-std=gnu99

例:

arm-linux-gcc -lpthread -std=gnu99  -o test ArmLinuxDataPipe1.2.1.c

Tl;dr

如果需要获取使用 usleep() 进行编译的旧代码,请将以下行添加到包含在任何其他库之前的头文件中:

#define _XOPEN_SOURCE   600
#define _POSIX_C_SOURCE 200112L

或者将编译器标志-std=c11 -D_XOPEN_SOURCE=600 -D_POSIX_C_SOURCE=200112L添加到生成文件。

这告诉环境您的程序使用此旧版本的 UNIX API,其中usleep()未被弃用。

或者(如果这肯定是新代码(将usleep()替换为nanosleep(),为您的库版本设置适当的功能测试宏,并检查您的代码库是否有其他位腐烂。

在 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宏特别尝试在四十多年的时间里启用来自各种不同操作系统的扩展。 有时,它甚至被用作非标准扩展的包罗万象。 这两个宏都已弃用,与当前接受的答案相反,您永远不应该在新代码中使用任何一个宏。

在本世纪,有两个UNIX标准,POSIX,它成为IEEE标准,以及来自Open Group(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,则会弃用它。 如果您选择"随心所欲"选项,它们也会启用,但这是一个坏主意。

有关现在在 C 语言中更好的睡眠演示,请参阅我的eRCaGuy_hello_world存储库,例如:

  1. sleep_nanosleep.c
  2. sleep_nanosleep_minimum_time_interval.c
  3. timinglib_sleep_and_sleep_until.c
  4. timinglib.h
  5. timeinglib.c
<小时 />

nanosleep()演示:如何从nanosleep()编写自己的sleep_us()函数

将以下内容添加到代码的顶部,#define _POSIX_C_SOURCE 199309L部分位于#include <time.h>之前,以便它将引入<time.h>nanosleep()函数!

// This line **must** come **before** including <time.h> in order to bring in
// the POSIX functions such as `clock_gettime()`, `nanosleep()`, etc., from
// `<time.h>`!
#define _POSIX_C_SOURCE 199309L
// For `nanosleep()`:
#include <time.h>

然后改用nanosleep()来创建自己的sleep_us()函数,以休眠设定的微秒数:

void sleep_us(unsigned long microseconds)
{
    struct timespec ts;
    ts.tv_sec = microseconds / 1000000ul;            // whole seconds
    ts.tv_nsec = (microseconds % 1000000ul) * 1000;  // remainder, in nanoseconds
    nanosleep(&ts, NULL);
}

为了在 Linux Ubuntu 上编译和运行,我创建了一个 sleep_test.c 文件并使用:

gcc -Wall -g3 -std=c11 -o sleep_test sleep_test.c && ./sleep_test

引用:

  1. (这是故意循环参考:请参阅我在此答案下的评论(:是否有 C 到毫秒的替代睡眠函数?
  2. http://man7.org/linux/man-pages/man2/nanosleep.2.html
    1. 提到:

    _POSIX_C_SOURCE >= 199309L

相关:

  1. 我的另一个答案是使用 POSIX 定时函数(例如:clock_gettime():以微秒为单位获取 C 格式的时间戳?

更进一步:

  1. 尝试使用单调时钟和标志TIMER_ABSTIME clock_nanosleep(),以实现类似于 FreeRTOS vTaskDelayUntil()功能的功能,以实现精确和可重复的周期性操作。
    1. 通过在#include <time.h>之前使用#define _POSIX_C_SOURCE 200112L来增加 POSIX 版本,以便访问clock_nanosleep()

问题的答案:用 #define _BSD_SOURCE#define _GNU_SOURCE

对于那些有错误的人

warning: #warning "_BSD_SOURCE and _SVID_SOURCE are deprecated, use _DEFAULT_SOURCE" [-Wcpp]
 # warning "_BSD_SOURCE and _SVID_SOURCE are deprecated, use _DEFAULT_SOURCE"
   ^~~~~~~

使用后#define _BSD_SOURCE请尝试使用

#define _GNU_SOURCE

注意:在包含为您提供usleep()的标题之前使用,即在包含unistd.h之前

使用 nanosleep(( 反而对我有用。

在相关说明中:usleep(( 自 POSIX-2008 以来已被删除,并且 建议改用 nanosleep((。

相关内容

  • 没有找到相关文章

最新更新