romfs 文件系统和devtmpfs 文件系统

romfs 文件系统   

网上有很多关于romfs文件系统的介绍,文件接口简单  ,只读文件系统

   之前对linux文件系统不了解,只知道是管理文件的系统,之前只停留在数据管理概念阶段 ,现在看看代码研究了下  大致思想,未完。。

  我找了下 linux/fs/里面比较简单的一个文件系统 romfs。因为是只读 那么省掉好多事情,数据文件和文件信息 是按照链表方式分布的。

 链表头(super block)-》文件头1(包含下一个文件的地址,文件类型,本长度,校验信息,文件名字)+文件数据

                                                          文件2 地址被上一个文件1头里面保存--》文件头2(包含下一个文件的地址,文件类型,本长度,校验信息,文件名字)+文件数据

  .。。。。。。。。。。。。。。。。。。文件n+1 地址被上一个文件n头里面保存--》文件n+1包含下一个文件的地址,文件类型,本长度,校验信息,文件名字)+文件数据

我们把上面个的文件头x就是信息 称作 物理 inode,linux  fs的inode 包含好多属性,因为不是所有的文件系统 只需要这些新就够了,其中涉及 读写权限 文件所属 修改时间。。。很多信息。

我们来看下 romfs 在linux 下面的代码理解,我们侧重分析下

 

register_filesystem(&romfs_fs_type);

static struct file_system_type romfs_fs_type = {
	.owner		= THIS_MODULE,
	.name		= "romfs",
	.mount		= romfs_mount,
	.kill_sb	= romfs_kill_sb,
	.fs_flags	= FS_REQUIRES_DEV,
};



/*
 * get a superblock for mounting
 */
static struct dentry *romfs_mount(struct file_system_type *fs_type,
			int flags, const char *dev_name,
			void *data)
{
	struct dentry *ret = ERR_PTR(-EINVAL);

#ifdef CONFIG_ROMFS_ON_MTD              ///先以一种存储类型为例
	ret = mount_mtd(fs_type, flags, dev_name, data, romfs_fill_super);
#endif
#ifdef CONFIG_ROMFS_ON_BLOCK
	if (ret == ERR_PTR(-EINVAL))
		ret = mount_bdev(fs_type, flags, dev_name, data,
				  romfs_fill_super);
#endif
	return ret;
}



/*
 * fill in the superblock    romf的超级块信息比较少,提取关键信息 给linux 文件系统
 */
static int romfs_fill_super(struct super_block *sb, void *data, int silent)
{
	struct romfs_super_block *rsb;
	struct inode *root;
	unsigned long pos, img_size;
	const char *storage;
	size_t len;
	int ret;


	sb->s_maxbytes = 0xFFFFFFFF;
	sb->s_magic = ROMFS_MAGIC;
	sb->s_flags |= SB_RDONLY | SB_NOATIME;  //SB_RDONLY 只读属性
	sb->s_op = &romfs_super_ops;           

#ifdef CONFIG_ROMFS_ON_MTD
	/* Use same dev ID from the underlying mtdblock device */
	if (sb->s_mtd)
		sb->s_dev = MKDEV(MTD_BLOCK_MAJOR, sb->s_mtd->index);  
#endif
	/* read the image superblock and check it */
	rsb = kmalloc(512, GFP_KERNEL);
	if (!rsb)
		return -ENOMEM;

	sb->s_fs_info = (void *) 512;
	ret = romfs_dev_read(sb, 0, rsb, 512);
	if (ret < 0)
		goto error_rsb;

	img_size = be32_to_cpu(rsb->size);

	if (sb->s_mtd && img_size > sb->s_mtd->size)
		goto error_rsb_inval;

	sb->s_fs_info = (void *) img_size;

	if (rsb->word0 != ROMSB_WORD0 || rsb->word1 != ROMSB_WORD1 ||
	    img_size < ROMFH_SIZE) {
		if (!silent)
			pr_warn("VFS: Can't find a romfs filesystem on dev %s.\n",
			       sb->s_id);
		goto error_rsb_inval;
	}

	if (romfs_checksum(rsb, min_t(size_t, img_size, 512))) {
		pr_err("bad initial checksum on dev %s.\n", sb->s_id);
		goto error_rsb_inval;
	}

	storage = sb->s_mtd ? "MTD" : "the block layer";

	len = strnlen(rsb->name, ROMFS_MAXFN);
	if (!silent)
		pr_notice("Mounting image '%*.*s' through %s\n",
			  (unsigned) len, (unsigned) len, rsb->name, storage);

	kfree(rsb);
	rsb = NULL;

	/* find the root directory */
	pos = (ROMFH_SIZE + len + 1 + ROMFH_PAD) & ROMFH_MASK;

	root = romfs_iget(sb, pos);
	if (IS_ERR(root))
		return PTR_ERR(root);

	sb->s_root = d_make_root(root);
	if (!sb->s_root)
		return -ENOMEM;

	return 0;

。。。。。
}


 第1行     register_filesystem 注册为文件系统 

 第5行     文件系统名字

 第6行     挂在这个文件系统时候的行为

 第38行   mount 的关键行为获取文件信息 超级快

 第51行   romfs 超级快的 ops 接口

 第56行   填充 s_dev (设备号信息)和上面 romfs_super_ops 一块打开操作文件用

 第64行    读取512字节超级块信息(实际上没这么大,多读取点,后面在提取关键信息)

 第75行    检查 romfs 超级快 标记字符信息 看下对不对

 第83行    检查 romfs 超级快 校验信息 看下对不对(只是简单就和计算sun)

 第90行    检查 romfs 超级快查找 文件名信息(超级块里面的文件名是卷宗名)

 第99行   接下来找到第一个文件的文件信息了->根目录文件。

 第101行 找到根文件的 物理inode 并填充关键信息到新linux 文件inode

 第105行 inode转换到 根路径

 

devtmpfs  文件系统

突然想到  dev下面的那些设备哪里来的,看了看发现 

device_register---》device_add(dev)--》devtmpfs_create_node(dev)

这个devtmpfs 也是个文件系统 没有放在kerne/fs 目录下面,在driver/base/devtmpfs.c  

    wake_up_process(thread);
    wait_for_completion(&req.done);

thread这个进程 在devtmpfs_init  ——》thread = kthread_run(devtmpfsd, &err, "kdevtmpfs")

 


static int devtmpfsd(void *p)
{
	char options[] = "mode=0755";
	int *err = p;
	*err = ksys_unshare(CLONE_NEWNS);
	if (*err)
		goto out;
	*err = ksys_mount("devtmpfs", "/", "devtmpfs", MS_SILENT, options);
	if (*err)
		goto out;
	ksys_chdir("/.."); /* will traverse into overmounted root */
	ksys_chroot(".");
	complete(&setup_done);
	while (1) {
		spin_lock(&req_lock);
		while (requests) {
			struct req *req = requests;
			requests = NULL;
			spin_unlock(&req_lock);
			while (req) {
				struct req *next = req->next;
				req->err = handle(req->name, req->mode,
						  req->uid, req->gid, req->dev);
				complete(&req->done);
				req = next;
			}
			spin_lock(&req_lock);
		}
		__set_current_state(TASK_INTERRUPTIBLE);
		spin_unlock(&req_lock);
		schedule();
	}
	return 0;
out:
	complete(&setup_done);
	return *err;
}

req->name = 

主要看这里吧  

  while (req) {
                struct req *next = req->next;
                req->err = handle(req->name, req->mode,       //req->mode 前面设置过
                          req->uid, req->gid, req->dev);
                complete(&req->done);
                req = next;
            }

  handle_create(name, mode, uid, gid, dev);

           vfs_mknod(d_inode(path.dentry), dentry, mode, dev->devt)

           vfs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t dev)

               vfs_mknod2(NULL, dir, dentry, mode, dev)

                    dir->i_op->mknod(dir, dentry, mode, dev)

                           ramfs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t dev)

                                 d_instantiate(dentry, inode);    

                                      __d_instantiate(entry, inode);    // 目录项高速缓存种 建立 entry 和inode 联系

目录项:目录项是描述文件的逻辑属性,只存在于内存中,并没有实际对应的磁盘上的描述,更确切的说是存在于内存的目录项缓存,为了提高查找性能而设计。注意不管是文件夹还是最终的文件,都是属于目录项,所有的目录项在一起构成一颗庞大的目录树   

所以说 devtmpfs_create_node 会自动 创建 dentry  inode

kthread_run(devtmpfsd, &err, "kdevtmpfs")  --》 devtmpfs_create_node -》wake_up_process(thread) --》devtmpfsd-》handle-》--》handle_create 

  其中handle_create 会调用 (dentry = kern_path_create(AT_FDCWD, nodename, &path, 0))得到dentry

handle_create -》vfs_mknod-》 ramfs_mknod-》ramfs_get_inode-》inode = new_inode(sb) 得到inode  init_special_inode(inode, mode, dev)  inode 和dev_t dev建立联系。

所有 device_add  ,既创建了 文件节点 inode ,也增加了 文件路径信息 dentry,所有如果一个设备添加成功会在 /dev  目录下面 出现对应文件。

如果说我们用mknod 命令 执行    mknod dev/zero c 1 5       估计从 vfs_mknod 开始。

前面    init_special_inode 把inode 和设备号 关联起来,    如果此时open设备会发生如下图所示流程,所有就完成了 ,驱动注册编写了设备驱动,用户通过文件名,使用设备,调用了驱动里面的驱动文件相关动作。

 

                                          

PS:上图是网上搜到的 不是本人制作的,再次声明

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值