请注意:这个问题不是 (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;
。
这些字段是一种优化,因此Linux不必为一个不超过BITS_PER_LONG
个打开的文件描述符的典型进程执行那么多的分配。
当分配files_struct
时,close_on_exec_init
字段为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_init
和open_fds_init
字段以前的类型是struct embedded_fd_set
,但在这次提交中被更改为裸数组。提交消息没有解释为什么作者选择使用单元素数组而不是纯标量。也许作者(David Howells)只是想避免使用&
运算符。
我最好的猜测是:这些字段的地址比它们的实际值使用得更频繁。在这种情况下,将它们设置为大小为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
的末尾。)
[EDIT:]正如user3477950所指出的,数组名并不总是与其第一个元素的地址相同——在某些上下文中,比如sizeof
的参数,它们意味着不同的东西。(这是我能想到的C的唯一上下文;>