Linux内核API get_super

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,会出现如图所示的结果。

Linux内核API get_super

结果分析:

在get_super函数中,首先打印出当前目录的super_block的编号,然后将这个结构体中的block_device当作参数传入了get_super函数中,应该得到的是当前目录的super_block结构体,而第二次打印出来的结构体编号与第一次相同,说明函数这两个super_block结构体表示的是同一个super_block。

赞(0)
未经允许不得转载:极客笔记 » Linux内核API get_super
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址