5

我正在在线阅读Linux Device Drivers 3rd Edition书籍,但无法理解原子变量的初始化宏:

static atomic_t foobar = ATOMIC_INIT(1);

我查看了Linux 内核 v3.2的源代码,但我只提出了两个定义:

#define ATOMIC_INIT(i) { (i) }

#define ATOMIC_INIT(i) ((atomic_t) { (i) })

宏定义的第二个版本在功能上似乎与第一个版本相同——事实上,当值无论如何都会被隐式强制转换为atomic_t. 为什么有两个版本的定义?

如果在 Linux 内核的未来版本中结构发生变化,宏的目的是否ATOMIC_INIT只是为了防止代码中断?atomic_t

4

2 回答 2

3

许多原子操作必须为每个架构单独实现。各种宏和函数的目的atomic.h是隐藏架构之间的差异。

在实践中,所有架构都使用单个 32 位变量来实现,因此各种宏atomic_t没有实际区别;ATOMIC_INIT所有有趣的事情都发生在操作中。但是内部结构可能会改变(并且对于 32 位 SPARC确实改变过一次),因此您始终应该使用官方 API。

于 2013-04-25T09:37:40.007 回答
2

两种不同形式的区别在于ATOMIC_INIT,第一种只能用在初始化中,第二种可以用在初始化和赋值中。乍一看,这听起来好像第二种更可取,但它有一个无法应用的重要用例:使用static存储规范声明的块范围变量。在块范围内

static atomic_t foobar = ((atomic_t) { (1) });

对标准 C 无效,因为初始化器不是编译时常量表达式。(在文件范围内,复合文字将被静态分配,因此它可以在那里工作。)

我隐约记得内核列表上的一个讨论,其中提到 gcc 有一个允许此类代码的扩展,这是他们不转向 C99 而是坚持将 gnu89 作为 C 方言的原因之一。

于 2013-04-25T15:18:42.933 回答