get_super()函数可以实现在由参数*bdev
所指定的块设备上获得超级块,并返回超级块数组的指针。在调用此函数时,该相应的文件系统必须已经被加载,或者该超级块已经占用了超级块数组的一项,否则返回NULL。
get_super文件包含
#include <linux/fs.h>
get_super函数定义
在内核源码中的位置:linux-3.19.3/fs/ super.c
函数定义格式:
struct super_block * get_super(struct block_device *bdev)
get_super输入参数说明
bdev
:是block_device型结构体指针,用来指定所获取的是哪个设备上的超级块。
每个块设备用一个块设备结构体struct block_device进行描述,其定义见文件linux-3.19.3/include/linux/fs.h,如下:
struct block_device {
dev_t bd_dev; //这是block_device的搜索编号
int bd_openers; //打开该设备计数值
struct inode * bd_inode;
struct super_block * bd_super; //块设备文件系统超级块结构体,用来操作块文件系统
struct mutex bd_mutex; //打开/关闭互斥信号量
struct list_head bd_inodes; //设备节点链表
void * bd_claiming;
void * bd_holder;
int bd_holders;
bool bd_write_holder;
#ifdef CONFIG_SYSFS
struct list_head bd_holder_list;
#endif
struct block_device *bd_contains; //含有非分区块结构体
unsigned bd_block_size; //用来描述块大小,在申请队列中进行设置
struct hd_struct * bd_part; //硬件分区结构
/*被打开设备的分区次数及统计信息.*/
unsigned bd_part_count;
int bd_invalidated;
struct gendisk * bd_disk; //虚拟块设备下层的通用磁盘结构
stuct request_queue * bd_queue;
struct list_head bd_list;
unsigned long bd_private; //私有数据
int bd_fsfreeze_count;
struct mutex bd_fsfreeze_mutex;
};
get_super返回参数说明
get_super()
函数的返回值是一个超级块super_block结构体,是在内存超级块(即super_block结构体)数组中搜索对应的超级块,并返回超级块数组的指针。如果不存在,则返回NULL。
结构体struct super_block其定义见文件linux-3.19.3/include/linux/fs.h,如下:
struct super_block {
struct list_head s_list; /*指向超级块链表的指针*/
dev_t s_dev; /*设备标识符*/
unsigned char s_blocksize_bits; /*以位为单位的块大小*/
unsigned long s_blocksize; /*以字节为单位的块大小*/
unsigned long long s_maxbytes; /*文件的最长长度*/
struct file_system_type *s_type; /*文件系统类型*/
const struct super_operations*s_op; /*超级块方法*/
struct dquot_operations *dq_op; /*磁盘限额处理的方法*/
struct quotactl_ops *s_qcop; /*磁盘限额管理的方法*/
const struct export_operations *s_export_op; /*网络文件系统使用的输出操作*/
unsigned long s_flags; /*安装标志*/
unsigned long s_magic; /*文件系统的魔数*/
struct dentry *s_root; /*文件系统根目录的目录项对象*/
struct rw_semaphore s_umount; /*卸载所用的信号量*/
int s_count; /*引用计数器*/
atomic_t s_active; /*次级引用计数器*/
#ifdef CONFIG_SECURITY
void *s_security; /*指向超级块安全数据结构的指针*/
#endif
struct xattr_handler **s_xattr; /*指向超级块扩展属性结构的指针*/
struct list_head s_inodes; /*所有索引节点的链表*/
struct hlist_head s_anon; /*用于处理远程网络文件系统的匿名目录项的链表*/
struct list_head s_mounts;
struct block_device *s_bdev;
struct backing_dev_info *s_bdi;
struct mtd_info *s_mtd;
struct hlist_head s_instances; /*用于给定文件系统类型的超级块对象链表的指针*/
unsigned int s_quota_types;
struct quota_info s_dquot; /*磁盘限额的描述符*/
struct sb_writers s_writers;
char s_id[32]; /*包含超级块的块设备名称*/
u8 s_uuid[16]; /*UUID*/
void *s_fs_info; /*指向特定文件系统的超级块信息的指针*/
unsigned int s_max_links;
fmode_t s_mode;
u32 s_time_gran; /*时间戳的最小单位)*/
struct mutex s_vfs_rename_mutex; /* Kludge */
char *s_subtype;
char *s_options;
...
...
...
};
get_super实例解析
编写测试文件:get_super.c
头文件声明如下:
#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/fs_struct.h>
#include <linux/path.h>
#include <linux/sched.h>
MODULE_LICENSE("GPL");
模块初始化函数:
int get_super_init(void)
{
struct super_block *sb;
struct super_block *sb1;
sb =current->fs->pwd.dentry->d_sb; //获取当前文件所在的super_block描述符信息
struct block_device *bdev = sb->s_bdev; //获取当前文件对应的block_device描述符信息
printk("the Superblock's dev number is %d.\n", sb->s_dev);
//显示当前文件对应的dev number
sb1 = get_super(bdev); //获取bdev所对应的超级块
if(sb1 ! = NULL) //显示获取结果的dev number值
printk("After the \"get_super\", the superblock's dev number is %d.\n", sb1->s_dev);
else
printk(“Cannot be found! \n”);
return 0;
}
模块退出函数:
void get_super_exit(void)
{
printk("Goodbye get_super\n");
}
模块初始化及退出函数调用:
module_init(get_super_init);
module_exit(get_super_exit);
实例运行结果及分析:
首先编译模块,执行命令insmod get_super.ko插入模块,然后执行命令dmesg -c,会出现如图所示的结果。
结果分析:
在get_super函数中,首先打印出当前目录的super_block的编号,然后将这个结构体中的block_device当作参数传入了get_super函数中,应该得到的是当前目录的super_block结构体,而第二次打印出来的结构体编号与第一次相同,说明函数这两个super_block结构体表示的是同一个super_block。