我注意到,struct pid
在
pid.h,该成员numbers
被定义为大小为 1 的数组。
struct pid
{
refcount_t count;
unsigned int level;
spinlock_t lock;
/* lists of tasks that use this pid */
struct hlist_head tasks[PIDTYPE_MAX];
struct hlist_head inodes;
/* wait queue for pidfd notifications */
wait_queue_head_t wait_pidfd;
struct rcu_head rcu;
struct upid numbers[1];
};
然而,在pid.c,使用 0 以外的索引访问该成员。
pid->numbers[i].nr = nr;
这是如何在不越界的情况下工作的?
答案1
这是灵活数组的一个变体,尽管没有使用现在的标准语法(应该是struct upid numbers[];
)。一般的想法是,为此类结构体分配足够的空间用于所有字段,并为结构体末尾的数组的实际大小分配足够的空间。
这些结构被分配在缓存中;你可以看到尺寸计算create_pid_cachep
:
len = sizeof(struct pid) + level * sizeof(struct upid);
struct pid
这会在给定级别为 a 分配足够的空间(从 0 开始,因此为 one 分配空间struct upid
)。
struct pid
其本身有空间容纳其numbers
数组中的一个元素,因为0级缓存的分配使用KMEM_CACHE
,并且期望代表完整缓存条目的单个结构。
过去几年一直致力于将所有此类阵列用途转换为标准化的灵活阵列;有关更多信息,请参阅Gustavo AR Silva 最近关于内核自我保护项目的演讲2022 年内核食谱。