请注意:此问题与(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_init
和open_fds_init
被定义为包含一个元素的数组,而不仅仅定义为unsigned long close_on_exec_init;
和unsigned long open_fds_init;
。
答案 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_init
和open_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 ++中,将数组名称作为参数传递也可以使模板参数的类型被推断为引用类型。)]