Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/28.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在DECLARE_KFIFO中使用工会的理由是什么_C_Linux_Linux Kernel_Unions - Fatal编程技术网

在DECLARE_KFIFO中使用工会的理由是什么

在DECLARE_KFIFO中使用工会的理由是什么,c,linux,linux-kernel,unions,C,Linux,Linux Kernel,Unions,我正在查看,特别是宏,我不明白为什么要使用联合体 #define DECLARE_KFIFO(name, size) \ union { \ struct kfifo name; \ unsigned char name##kfifo_buffer[size + sizeof(struct kfifo)]; \ } 我的问题如下: 在这里使用联合有什么意义这解决了什么设计目标?是出于性能原因吗 你怎么能进入这个匿名联盟?例如,这不起作用: #include <stdio.

我正在查看
,特别是宏,我不明白为什么要使用
联合体

#define DECLARE_KFIFO(name, size) \
union { \
    struct kfifo name; \
    unsigned char name##kfifo_buffer[size + sizeof(struct kfifo)]; \
}
我的问题如下:

  • 在这里使用
    联合
    有什么意义这解决了什么设计目标?是出于性能原因吗
  • 你怎么能进入这个匿名联盟?例如,这不起作用:

    #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;
    ^
    
    #包括
    int main()
    {
    联合{
    INTA;
    浮球b;
    };
    a=10;
    }
    main.c:18:5:错误:“a”未声明(此函数首次使用)
    a=10;
    ^
    
  • 为什么要声明不能使用的内容?

  • 这是如何与宏一起工作的?如何访问union以及它与上一个宏有什么关系
  • 如果我的记忆正确,那么在C中,一个并集只能使用一个元素。这是怎么回事它将只使用声明联盟中的一个成员?

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

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

    /**
     * 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];
    };
    
    声明两个对象时,更自然的做法是使用两个字段的匿名结构,而不是联合:

    它应该完全匿名,以允许直接访问其
    名称
    字段

    与结构的实现相比,通过匿名联合实际实现的
    declarekfifo
    给出了相同的“字段”
    名称
    ,并为其缓冲区分配了相同数量的字节(数字
    大小
    ):

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


    最近的内核5.6.12仍然在kfifo中使用联合,只是它要复杂得多

    不完全正确。较新的内核版本使用
    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()
    运算符声明所有其他字段仅用于提取其类型

    因此,
    \uuuuu STRUCT\ukfifo\ucommon
    只是一个“聪明的”
    STRUCT KFIFO
    声明,它知道它包含的数据类型

    宏的定义

    #define DECLARE_KFIFO(fifo, type, size) STRUCT_KFIFO(type, size) fifo
    
    展开中间宏后,将给出:

    #define DECLARE_KFIFO(fifo, type, size) struct { \
        __STRUCT_KFIFO_COMMON(type, recsize, ptrtype); \
        type        buf[((size < 2) || (size & (size - 1))) ? -1 : size]; \
    } fifo
    
    #define DECLARE_KFIFO(先进先出,类型,大小)结构{\
    __STRUCT_KFIFO_COMMON(type、recsize、ptrtype)\
    buf型[(尺寸<2)| |(尺寸和尺寸-1))?-1:尺寸]\
    }先进先出
    
    所以,此时它是一个具有给定名称的结构类型的字段。与旧定义类似,此结构包含两个字段:

    • struct kfifo
      object(它的“聪明”版本)和
    • kfifo的缓冲区

    请注意,kfifo API的这种实现在实践中从未实际使用过。如果查看内核代码的其余部分,在更改为当前版本之前,没有使用任何
    声明_KFIFO
    ,该版本没有使用
    联合,而是使用
    结构(如下@Tsyvarev解释)。至于为什么它首先被声明为
    联盟
    ,您必须直接询问原始作者()。这看起来更像是一个错误,而不是一个有意义的设计选择。我不明白你所说的
    \uuuu STRUCT\ukfifo\ucommon
    是一个“聪明的”
    STRUCT KFIFO
    声明。当我说在一个工会中一次只能访问一个成员时,我说的对吗?如果是这样,如果我访问
    struct\uuu kfifo
    ,那么数据类型信息会去哪里?因为如果我那样做的话,它会变得难以接近。反之亦然,如果我访问数据类型,数据就会丢失。“在一个联合中,一次只能访问一个成员?”-不,C语言没有这样的限制。参见此处示例:。请注意,在联盟中,成员仅共享数据。因此,工会的一种成员永远不会消失。
    #define DECLARE_KFIFO(fifo, type, size) struct { \
        __STRUCT_KFIFO_COMMON(type, recsize, ptrtype); \
        type        buf[((size < 2) || (size & (size - 1))) ? -1 : size]; \
    } fifo