【问题标题】:Why does such a struct contain two array fields containing only one element?为什么这样的结构包含两个仅包含一个元素的数组字段?
【发布时间】:2014-07-24 14:21:05
【问题描述】:

请注意:此问题与One element array in struct)不重复

以下代码摘自Linux内核源码(版本:3.14)

struct files_struct
{
    atomic_t count;
    struct fdtable __rcu *fdt;
    struct fdtable fdtab;

    spinlock_t file_lock ____cacheline_aligned_in_smp;
    int next_fd;
    unsigned long close_on_exec_init[1];
    unsigned long open_fds_init[1];
    struct file __rcu * fd_array[NR_OPEN_DEFAULT];
};

我只是想知道为什么close_on_exec_initopen_fds_init 被定义为包含一个元素的数组,而不仅仅是定义为unsigned long close_on_exec_init;unsigned long open_fds_init;

【问题讨论】:

  • 也很好解释here
  • 看起来它不可能是灵活数组的破解,因为数组成员不在末尾。
  • 上面给出的帖子与这个问题不同。而且答案不适用于这个问题。
  • @xmllmx 你能解释一下你的问题有什么不同吗?
  • @Code-Guru,数组字段数多于一个,而不是最后一个字段。

标签: c arrays linux struct idioms


【解决方案1】:

这些字段是一种优化,因此 Linux 不必为不超过 BITS_PER_LONG 打开文件描述符的典型进程执行尽可能多的分配。

close_on_exec_init 字段在分配files_struct 时为fdt->close_on_exec 提供初始存储。 (参见fs/file.c 中的dup_fd。)

如果相应的文件描述符设置了“close-on-exec”标志,则设置fdt->close_on_exec 的每一位。因此,如果进程的打开文件描述符多于unsigned long 中的位数,Linux 只需要为fdt->close_on_exec 分配额外的空间。

open_fds_init 字段为fdt->open_fds 字段提供相同的功能。 fd_array 字段为fdt->fd 字段提供相同的功能。 (注意fd_array 的大小为BITS_PER_LONG。)

close_on_exec_initopen_fds_init 字段以前的类型为 struct embedded_fd_set,但在 this commit 中更改为裸数组。提交消息没有解释为什么作者选择使用单元素数组而不是裸标量。也许作者(David Howells)只是想避免使用& 运算符。

【讨论】:

    【解决方案2】:

    我的最佳猜测:这些字段的地址比它们的实际值更频繁地使用。在这种情况下,将它们设置为大小为 1 的数组可以节省每次需要它们的地址时键入 &,因为在 C 中,在表达式中使用数组的名称几乎在所有情况下都完全等同于获取其第一个元素的地址:

    int x;
    int y[1];
    
    function_that_needs_address_of_int(&x);
    function_that_needs_address_of_int(y);
    function_that_needs_address_of_int(&y[0]);    // Identical to previous line
    

    (正如其他人在 cmets 中指出的那样,这些字段不可能被用作可变长度数组的黑客,因为有多个并且它们不会出现在struct.)

    [编辑: 正如 user3477950 所指出的,数组名称并不总是与其第一个元素的地址相同——在某些情况下,例如 sizeof 的参数,它们的含义不同事物。 (这是我能想到的 C 的唯一上下文;在 C++ 中,将数组名称作为参数传递也可以将模板参数的类型推断为引用类型。)]

    【讨论】:

    • "在表达式中使用数组的名称完全等同于获取其第一个元素的地址" - 不,它们不完全等同(想想sizeof 等人),它会最好解释一下,在某些情况下,数组名称可能会衰减为指向其第一个元素的指针。
    猜你喜欢
    • 2014-05-02
    • 1970-01-01
    • 2021-06-29
    • 2023-03-23
    • 2013-12-07
    • 2019-06-20
    • 2014-12-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多