在DECLARE_KFIFO中使用联合的背后原理是什么

我正在查看<linux/kfifo.h>,特别是DECLARE_KFIFO宏,但我不知道为什么要使用union

#define DeclARE_KFIFO(name,size) \
union { \
    struct kfifo name; \
    unsigned char name##kfifo_buffer[size + sizeof(struct kfifo)]; \
}

我的问题如下:

  1. 在这里使用union有什么意义? 可以解决什么设计目标?是出于性能原因吗?
  2. 您甚至将如何访问此匿名联合?例如,这不起作用:

    #include <stdio.h>
    
    int main()
    {
    union {
        int a;
        float b;
    };
    
    a = 10;
    }
    main.c:18:5: error: ‘a’ undeclared (first use in this function)
    a = 10;
    ^
    

为什么要声明一些无法使用的内容?

  1. 如何与INIT_KFIFO宏一起使用?如何访问联合以及它与先前的宏有什么关系?
  2. 如果我的记忆正确地为我服务,那么在C语言中,您只能在一个并集中使用一个元素。那么,这是怎么回事? 它将仅使用已声明的工会中的一名成员吗?

注意:此代码适用于2.6.33内核。我知道它的旧代码,但最近的内核5.6.12仍在kfifo中使用并集,只是其复杂得多。

tcl1011 回答:在DECLARE_KFIFO中使用联合的背后原理是什么

对该宏的注释几乎解释了 一切:

/**
 * DECLARE_KFIFO - macro to declare a kfifo and the associated buffer
 * @name: name of the declared kfifo datatype
 * @size: size of the fifo buffer. Must be a power of two.
 *
 * Note1: the macro can be used inside struct or union declaration
 * Note2: the macro creates two objects:
 *  A kfifo object with the given name and a buffer for the kfifo
 *  object named name##kfifo_buffer
 */

此宏仅用作(作为其他结构)或联合的字段。有了这种用法,宏就会创建(在结构或联合中分配):

  • 一个kfifo对象,可以作为名称为name
  • 的字段进行访问
  • kfifo的缓冲区。

所以,结构声明就像

struct my_struct {
   int a;
   char b;
   DECLARE_KFIFO(my_fifo,100);
};

具有与

相似的效果
struct my_struct {
   int a;
   char b;
   // This field may be used for call kfifo functions
   struct kfifo my_fifo;
   // This field is never used directly.
   // Pointer to this buffer is stored in the '.buffer' field of kfifo object.
   unsigned char buffer_internal_to_kfifo_implementation[size];
};

声明两个对象使用两个字段的匿名结构代替 union 会更自然:

#define DECLARE_KFIFO(name,size) \
struct { \
    struct kfifo name; \
    unsigned char name##kfifo_buffer[size]; \
}

它应该是完全匿名的,以允许直接访问其name字段。

与结构的实现相比,DECLARE_KFIFO通过匿名 union 的实际实现给出相同的“字段” name,并分配相同数量的字节(数量为{{1 }})作为其缓冲区:

size

很难说为什么选择union { \ struct kfifo name; \ unsigned char name##kfifo_buffer[size + sizeof(struct kfifo)]; \ } 而不是union


最近的内核5.6.12仍在kfifo中使用并集,只是更加复杂。

不太正确。较新的内核版本出于完全不同的目的而使用struct

union

这里#define __STRUCT_KFIFO_COMMON(datatype,recsize,ptrtype) \ union { \ struct __kfifo kfifo; \ datatype *type; \ const datatype *const_type; \ char (*rectype)[recsize]; \ ptrtype *ptr; \ ptrtype const *ptr_const; \ } 是唯一用于读写数据字节的字段。声明所有其他字段仅用于使用kfifo运算符提取其类型

因此,typeof()只是一个“聪明的” __STRUCT_KFIFO_COMMON声明,它知道其中包含的数据类型。

struct kfifo宏的定义

DECLARE_KFIFO

扩展中间宏后,给出:

#define DECLARE_KFIFO(fifo,type,size) STRUCT_KFIFO(type,size) fifo

因此,该时间是具有给定名称的结构类型的字段。与旧定义类似,此结构包含两个字段:

  • #define DECLARE_KFIFO(fifo,size) struct { \ __STRUCT_KFIFO_COMMON(type,ptrtype); \ type buf[((size < 2) || (size & (size - 1))) ? -1 : size]; \ } fifo 对象(其“聪明”版本)和
  • kfifo的缓冲区。
本文链接:https://www.f2er.com/2361833.html

大家都在问