zoukankan      html  css  js  c++  java
  • sysfs 文件系统的建立

    1.sysf文件系统的全局变量

    static struct vfsmount *sysfs_mount;
    struct super_block * sysfs_sb = NULL;
    struct kmem_cache *sysfs_dir_cachep;
    

    2. 文件系统类型:file_system_type

    fs/sysfs/symlink.c
    static struct file_system_type sysfs_fs_type = 
    {
        .name        = "sysfs",
        .get_sb        = sysfs_get_sb,
        .kill_sb    = kill_anon_super,
    };

     2.sysfs文件系统初始化:sysfs_init

    fs/sysfs/symlink.c

    
    
    struct kmem_cache *sysfs_dir_cachep;
    int
    __init sysfs_init(void) { int err = -ENOMEM;
        /*创建一个分配sysfs_dirent的cash, name :sysfs_dir_cache 此cashe在/proc/slabinfo中显示的名字*/ sysfs_dir_cachep
    = kmem_cache_create("sysfs_dir_cache", sizeof(struct sysfs_dirent), 0, 0, NULL); if (!sysfs_dir_cachep) goto out; err = sysfs_inode_init(); if (err) goto out_err; err = register_filesystem(&sysfs_fs_type); if (!err) { sysfs_mount = kern_mount(&sysfs_fs_type); if (IS_ERR(sysfs_mount)) { printk(KERN_ERR "sysfs: could not mount!\n"); err = PTR_ERR(sysfs_mount); sysfs_mount = NULL; unregister_filesystem(&sysfs_fs_type); goto out_err; } } else goto out_err; out: return err; out_err: kmem_cache_destroy(sysfs_dir_cachep); sysfs_dir_cachep = NULL; goto out; }

      sysfs_inode_init():主要是初始化BDI(backing device infor )信息

    static struct backing_dev_info sysfs_backing_dev_info = {
        .ra_pages    = 0,    /* No readahead */
        .capabilities    = BDI_CAP_NO_ACCT_AND_WRITEBACK,
    };
    int __init sysfs_inode_init(void)
    {
        return bdi_init(&sysfs_backing_dev_info);
    }
    int bdi_init(struct backing_dev_info *bdi)
    {
        int i;
        int err;
        bdi->dev = NULL;
        bdi->min_ratio = 0;
        bdi->max_ratio = 100;
        bdi->max_prop_frac = PROP_FRAC_BASE;
        for (i = 0; i < NR_BDI_STAT_ITEMS; i++) {
            err = percpu_counter_init(&bdi->bdi_stat[i], 0);
            if (err)
                goto err;
        }
        bdi->dirty_exceeded = 0;
        err = prop_local_init_percpu(&bdi->completions);
        if (err) {
    err:
            while (i--)
                percpu_counter_destroy(&bdi->bdi_stat[i]);
        }
        return err;
    }

      register_filesystem(&sysfs_fs_type);

    static struct file_system_type sysfs_fs_type = {
        .name        = "sysfs",
        .get_sb        = sysfs_get_sb,
        .kill_sb    = kill_anon_super,
    };
    static int sysfs_get_sb(struct file_system_type *fs_type,int flags, const char *dev_name, void *data, struct vfsmount *mnt)
    {
        return get_sb_single(fs_type, flags, data, sysfs_fill_super, mnt);
    }

    说明:
    1.register_filesystem只是把文件系统描述结构,插入系统全局链表中;在该文件系统被挂载(mount)到系统时,调用文件系统结构体的getsb函数,完成对文件系统的超级块分配和初始化;
    2.get_sb_single函数创建一个新的super_block,并用sysfs_fill_super填充这个super_block结构,然后使mnt->mnt_sb指向该super_block,mnt->mnt_root指向该超级块的文件系统的根目录的
    目录项对象;

     sysfs_mount = kern_mount(&sysfs_fs_type);

    #define kern_mount(type) kern_mount_data(type, NULL)
    struct vfsmount *kern_mount_data(struct file_system_type *type, void *data)
    {
        return vfs_kern_mount(type, MS_KERNMOUNT, type->name, data);
    }
    struct vfsmount *
    vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void *data)
    {
        struct vfsmount *mnt;
        char *secdata = NULL;
        int error;
    
        if (!type)return ERR_PTR(-ENODEV);
    
        error = -ENOMEM;
        mnt = alloc_vfsmnt(name);
        if (!mnt)goto out;
        if (data && !(type->fs_flags & FS_BINARY_MOUNTDATA)) {
            secdata = alloc_secdata();
            if (!secdata)
                goto out_mnt;
            error = security_sb_copy_data(data, secdata);
            if (error)
                goto out_free_secdata;
        }
        /*调用文件系统的超级块分配函数*/
        error = type->get_sb(type, flags, name, data, mnt);
        if (error < 0)
            goto out_free_secdata;
        BUG_ON(!mnt->mnt_sb);
        error = security_sb_kern_mount(mnt->mnt_sb, flags, secdata);
        if (error)
             goto out_sb;
    
        mnt->mnt_mountpoint = mnt->mnt_root; //指向文件系统安装点目录的dentry
        mnt->mnt_parent = mnt;
        up_write(&mnt->mnt_sb->s_umount);//安装文件系统卸载所用的信号量
        free_secdata(secdata);
        return mnt;
    out_sb:
        dput(mnt->mnt_root);
        deactivate_locked_super(mnt->mnt_sb);
    out_free_secdata:
        free_secdata(secdata);
    out_mnt:
        free_vfsmnt(mnt);
    out:
        return ERR_PTR(error);
    }

    sysfs_get_sb

    static int sysfs_get_sb(struct file_system_type *fs_type,
        int flags, const char *dev_name, void *data, struct vfsmount *mnt)
    {
        return get_sb_single(fs_type, flags, data, sysfs_fill_super, mnt);
    }
    int get_sb_single(struct file_system_type *fs_type, int flags, void *data,int (*fill_super)(struct super_block *, void *, int), struct vfsmount *mnt)
    {
        struct super_block *s;
        int error;
        s = sget(fs_type, compare_single, set_anon_super, NULL);
        if (IS_ERR(s))
            return PTR_ERR(s);
        if (!s->s_root) {
            s->s_flags = flags;
            error = fill_super(s, data, flags & MS_SILENT ? 1 : 0);
            if (error) {
                deactivate_locked_super(s);
                return error;
            }
            s->s_flags |= MS_ACTIVE;
        }
        do_remount_sb(s, flags, data, 0);
        simple_set_mnt(mnt, s);//系统挂载点指向超级块的根目录的dentry和超级块本身
        return 0;
    }
    void simple_set_mnt(struct vfsmount *mnt, struct super_block *sb)
    {
        mnt->mnt_sb = sb;
        mnt->mnt_root = dget(sb->s_root);//指向文件系统根目录的dentry
    }

    超级块的填充

    fs/sysfs/symlink.c line29
    static const struct super_operations sysfs_ops = {

        .statfs        = simple_statfs,
        .drop_inode    = generic_delete_inode,
        .delete_inode    = sysfs_delete_inode,
    };
    static
    int sysfs_fill_super(struct super_block *sb, void *data, int silent) { struct inode *inode; struct dentry *root; sb->s_blocksize = PAGE_CACHE_SIZE; //块的大小,以字节为单位 sb->s_blocksize_bits = PAGE_CACHE_SHIFT;//基本块设备驱动程序中块的大小,以字节为单位 sb->s_magic = SYSFS_MAGIC; //文件系统的魔数 sb->s_op = &sysfs_ops; sb->s_time_gran = 1; sysfs_sb = sb; /* get root inode, initialize and unlock it */ mutex_lock(&sysfs_mutex); inode = sysfs_get_inode(&sysfs_root); mutex_unlock(&sysfs_mutex); if (!inode) { pr_debug("sysfs: could not get root inode\n"); return -ENOMEM; } /* instantiate and link root dentry */ root = d_alloc_root(inode); if (!root) { pr_debug("%s: could not get root dentry!\n",__func__); iput(inode); return -ENOMEM; } root->d_fsdata = &sysfs_root; sb->s_root = root; return 0; }
  • 相关阅读:
    数据类型
    蓝牙Controller框架梳理
    蓝牙协议框架梳理
    低功耗蓝牙漏洞分析
    C语言进阶1-#define和const
    KMP算法详细分解
    C语言---指针变量详解3
    C语言---指针变量详解2
    C语言---指针变量详解1
    C语言---指针变量作为函数参数
  • 原文地址:https://www.cnblogs.com/linengier/p/2992813.html
Copyright © 2011-2022 走看看