经常浏览内核代码,看到这种声明:
static struct kmem_cache cache_cache =
{
.batchcount = 1,
.limit = BOOT_CPUCACHE_ENTRIES,
.shared = 1,
.buffer_size = sizeof(struct kmem_cache),
.name = "kmem_cache",
};
潜意识里认为跟平常看到结构体初始化没什么2样,以为只有声明的成员被初始化了,而为声明的成员在必要时进行初始化。
前几天看slab的cache_cache的建立后,通用缓存随即建立过程中,追踪代码到此处:
slabp = alloc_slabmgmt(cachep, objp, offset,local_flags & ~GFP_CONSTRAINT_MASK, nodeid);
展开-------------------->>>>>>
static struct slab *alloc_slabmgmt()
{
.........
.........
.........
if (OFF_SLAB(cachep))
{
/* Slab management obj is off-slab. */
slabp = kmem_cache_alloc_node(cachep->slabp_cache,local_flags & ~GFP_THISNODE, nodeid);
if (!slabp)
return NULL;
}
else
{
slabp = objp + colour_off;
colour_off += cachep->slab_size;
}
........
........
}
此处的cachep是缓存cache_cache的值,OFF_SLAB(cachep)处的定义为
#define OFF_SLAB(x) ((x)->flags & CFLGS_OFF_SLAB)
off_slab要调用cache_cache的flags成员值,可明明从开始到现在也没看到哪条语句给flags赋值啊,重复地搜素代码,就
是没发现,百思不得其解,后来发现linux2.6.10的代码里有对flags赋值一项,以后的版本删掉此处的赋值有什么意义呢,能
不能从linux版本更新信息那获得一点线索?一直追查,查到linux 2.6.2---->linux 2.6.20.1之间改了,但版本更新消息里没
有对此的说明,于是确定是哪里理解错了。。搞了好久没想通,作罢,放了大半天,突然间想到是不是初始化赋值的那里理解
错了,编译测试代码,查看网上资料才发现这种指定结构初始化以前还真没编过,只是自己一厢情愿的认为跟平常的初始化一
样,这种初始化表明未被申明的成员默认为0或者是NULL;
附上网上查阅资料
当结构体中字段比较多,并且只对部分字段指定初值时,可以采用以下简洁方式,而不需要对每个字段都指定初值:
static struct 结构体类型名 变量名 = {
.字段名1 = 字段值1,
.字段名2 = 字段值2,
......
};
static关键字可以保证将未指定初值的字段设为0或者NULL。例如:
struct file_operations {
struct module *owner;
loff_t (*llseek) (struct file *, loff_t, int);
ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
ssize_t (*aio_read) (struct kiocb *, const struct iovec *, unsigned long, loff_t);
ssize_t (*aio_write) (struct kiocb *, const struct iovec *, unsigned long, loff_t);
int (*readdir) (struct file *, void *, filldir_t);
unsigned int (*poll) (struct file *, struct poll_table_struct *);
int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long);
long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);
long (*compat_ioctl) (struct file *, unsigned int, unsigned long);
int (*mmap) (struct file *, struct vm_area_struct *);
int (*open) (struct inode *, struct file *);
int (*flush) (struct file *, fl_owner_t id);
int (*release) (struct inode *, struct file *);
int (*fsync) (struct file *, struct dentry *, int datasync);
int (*aio_fsync) (struct kiocb *, int datasync);
int (*fasync) (int, struct file *, int);
int (*lock) (struct file *, int, struct file_lock *);
ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int);
unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);
int (*check_flags)(int);
int (*dir_notify)(struct file *filp, unsigned long arg);
int (*flock) (struct file *, int, struct file_lock *);
ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *, size_t, unsigned int);
ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *, size_t, unsigned int);
int (*setlease)(struct file *, long, struct file_lock **);
};
static const struct file_operations zero_fops = {
.llseek = zero_lseek,
.read = read_zero,
.write = write_zero,
.mmap = mmap_zero,
};