【问题标题】:Conflicting function declaration and macro?冲突的函数声明和宏?
【发布时间】:2019-05-16 19:11:52
【问题描述】:

我正在查看 linux 内核中的这个头文件: https://elixir.bootlin.com/linux/v4.14/source/arch/x86/boot/string.h

#ifndef BOOT_STRING_H
#define BOOT_STRING_H

/* Undef any of these macros coming from string_32.h. */
#undef memcpy
#undef memset
#undef memcmp

void *memcpy(void *dst, const void *src, size_t len);
void *memset(void *dst, int c, size_t len);
int memcmp(const void *s1, const void *s2, size_t len);

#define memcpy(d,s,l) __builtin_memcpy(d,s,l)
#define memset(d,c,l) __builtin_memset(d,c,l)
#define memcmp  __builtin_memcmp

...

#endif /* BOOT_STRING_H */

我无法弄清楚 memcpy、memset 和 memcmp 上的 #undef + 函数声明 + 宏定义是做什么的。例如,它首先声明了一个函数 memcpy,然后定义了一个宏 memcpy。我不确定这样做的目的是什么。我发现这里定义了这个函数:https://elixir.bootlin.com/linux/v4.14/source/arch/x86/boot/copy.S#L20。如果代码中的某处使用 memcpy(例如这里:https://elixir.bootlin.com/linux/v4.14/source/arch/x86/boot/main.c#L40)使用 memcpy,它使用什么? copy.S 或 __builtin_memcpy 中定义的函数?

【问题讨论】:

  • 可能声明的目的是,如果人们绕过以下宏(例如取消定义它们),它仍然可以工作

标签: c linux-kernel


【解决方案1】:

函数声明和宏不冲突。 memcpy() 在内核中有几个定义,#undef 块上方的注释暗示了这一点——string_32.h 中定义了另一个 memcpy()

#undef memcpy 正在取消 string_32.h 中的 #define,因此它不会存在于任何包含 /boot/string.h 的文件中。然后声明memcpy(),并为其构建一个新宏。

#define 语句正在为memcpy() 创建一个新宏,因为 string_32.h 中的宏在此上下文中不再存在。内核开发人员出于多种原因使用宏;更多信息请参见this thread 中的答案。

/boot/copy.Sassembly file。你可以阅读一些关于它的作用here/boot/main.c 中使用的memcpy() 来自 /boot/string.h -- 检查包含语句。

【讨论】:

  • 当你说它来自 /boot/string.h 你的意思是 __builtin_memcpy 吗?我的假设是它最终会使用副本中的那个。S 否则为什么在同一个模块中会有这样的定义。
  • __builtin_memcpy(d,s,l)memcpy(d,s,l) 的宏,这意味着它们的计算结果相同:void *memcpy(void *dst, const void *src, size_t len); 的定义。由于您实际上没有看到在您链接到的 /boot/main.c 中的行上调用了__builtin_memcpy(),因此您可以放心地假设您是直接调用memcpy()copy.S 中的memcpy 版本正在被汇编程序使用,而不是在 /boot/main.c 中,这在我链接的一篇文章中进行了讨论到。