为什么这样的结构包含两个只包含一个元素的数组字段?

时间:2014-06-04 04:12:46

标签: c arrays linux struct idioms

请注意:此问题与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;

2 个答案:

答案 0 :(得分:5)

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

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

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

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)只是想避免使用&运算符。

答案 1 :(得分:2)

我最好的猜测:这些字段的地址使用频率远高于实际值。在这种情况下,将它们设置为size-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

(正如其他人在评论中所指出的那样,不能将这些字段用作可变长度数组的hack,因为它有多个并且它们不会出现在结尾处。 struct。)

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