温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

基于linux分怎么实现虚拟文件系统初始化

发布时间:2021-12-17 09:26:04 阅读:139 作者:iii 栏目:大数据
Linux服务器限时活动,0元免费领,库存有限,领完即止! 点击查看>>

本篇内容主要讲解“基于linux分怎么实现虚拟文件系统初始化”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“基于linux分怎么实现虚拟文件系统初始化”吧!

从main函数开始,直到虚拟文件系统的初始化,路径是init()->setup()->syssetup();sys_setup主要是注册了虚拟文件系统下面所有的文件系统。然后挂载根文件系统。下面是初始化代码。

    asmlinkage int sys_setup(void){	static int callable = 1;	if (!callable)		return -1;	callable = 0;	device_setup();#ifdef CONFIG_MINIX_FS	register_filesystem(&(struct file_system_type)		{minix_read_super, "minix", 1, NULL});#endif#ifdef CONFIG_EXT_FS	register_filesystem(&(struct file_system_type)		{ext_read_super, "ext", 1, NULL});#endif......mount_root();}
   
     
 
    
    AI代码助手复制代码

下面先看一下基本的数据结构。

   
     
 
    
    struct file_system_type {	struct super_block *(*read_super) (struct super_block *, void *, int);	char *name;	int requires_dev;	struct file_system_type * next;};
   
     
 
    
    AI代码助手复制代码

这是一个具体文件系统在虚拟文件系统注册时的表示结构。然后看一下注册文件系统的函数。

   
     
 
    
    int register_filesystem(struct file_system_type * fs){	struct file_system_type ** tmp;	if (!fs)		return -EINVAL;	if (fs->next)		return -EBUSY;	// tmp是二级指针,指向文件系统链表的头指针的地址	tmp = &file_systems;	// 遍历链表,直到尾部,插入新的节点	while (*tmp) {		// 判断是否已经注册了该文件系统		if (strcmp((*tmp)->name, fs->name) == 0)			return -EBUSY;		// 指向当前节点的next域的地址,*tmp得到下一个被比较的节点		tmp = &(*tmp)->next;	}	// 利用二级指针指针修改next域的内容,不需要使用->next = fs的形式	*tmp = fs;	return 0;}
   
     
 
    
    AI代码助手复制代码

就是把一个file_system_type结构体插入一个链表中。注册文件系统其实只是构建一个单链表。接着看挂载根文件系统。这里大致分析一下流程。有时间再详细说。

   
     
 
    
    void mount_root(void){	struct file_system_type * fs_type;	struct super_block * sb;	struct inode * inode, d_inode;	struct file filp;	int retval;	// 清空超级块数组	memset(super_blocks, 0, sizeof(super_blocks));#ifdef CONFIG_BLK_DEV_FD	if (MAJOR(ROOT_DEV) == FLOPPY_MAJOR) {		printk(KERN_NOTICE "VFS: Insert root floppy and press ENTER\n");		wait_for_keypress();	}#endif	memset(&filp, 0, sizeof(filp));	memset(&d_inode, 0, sizeof(d_inode));	// 根设备号	d_inode.i_rdev = ROOT_DEV;	filp.f_inode = &d_inode;	// 只读方式挂载	if ( root_mountflags & MS_RDONLY)		filp.f_mode = 1; /* read only */	else		filp.f_mode = 3; /* read write */	// 暂时忽略	retval = blkdev_open(&d_inode, &filp);	if(retval == -EROFS){		root_mountflags |= MS_RDONLY;		filp.f_mode = 1;		retval = blkdev_open(&d_inode, &filp);	}	for (fs_type = file_systems ; fs_type ; fs_type = fs_type->next) {		if(retval)			break;		// 没有关联到设备则不需要往下执行,有些文件系统是没有对应的底层设备的		if (!fs_type->requires_dev)			continue;		// 读根设备的超级块,设备的第一扇区是分区表,接着是超级块		sb = read_super(ROOT_DEV,fs_type->name,root_mountflags,NULL,1);		// 读取成功		if (sb) {			// 根节点			inode = sb->s_mounted;			inode->i_count += 3 ;	/* NOTE! it is logically used 4 times, not 1 */			sb->s_covered = inode;			sb->s_flags = root_mountflags;			// 当前进程(init进程)的根目录和工作目录设置为根节点			current->fs->pwd = inode;			current->fs->root = inode;			printk ("VFS: Mounted root (%s filesystem)%s.\n",				fs_type->name,				(sb->s_flags & MS_RDONLY) ? " readonly" : "");			// 直接返回,即第一个读取成功的文件系统成为根文件系统			return;		}	}	panic("VFS: Unable to mount root fs on %02x:%02x",		MAJOR(ROOT_DEV), MINOR(ROOT_DEV));}
   
     
 
    
    AI代码助手复制代码

读取根设备的超级块内容,如果成功,则成为根文件系统。并设置当前init进程的工作目录和根目录是根文件系统的根节点对应的inode。我们看看怎么读取超级块的。

   
     
 
    
    // 读设备对应的超级块static struct super_block * read_super(dev_t dev,char *name,int flags,   void *data, int silent){	struct super_block * s;	struct file_system_type *type;	if (!dev)		return NULL;	check_disk_change(dev);	// 有则直接返回,初始化的时候还没有	s = get_super(dev);	if (s)		return s;	// 否则根据name在文件系统链表中(在系统初始化时建立的)找到对应的文件系统节点,里面有一个read_super函数	if (!(type = get_fs_type(name))) {		printk("VFS: on device %d/%d: get_fs_type(%s) failed\n",						MAJOR(dev), MINOR(dev), name);		return NULL;	}	// 在超级块数组中找到一个slot	for (s = 0+super_blocks ;; s++) {		if (s >= NR_SUPER+super_blocks)			return NULL;		if (!s->s_dev)			break;	}	// 赋值给超级块节点的字段	s->s_dev = dev;	s->s_flags = flags;	// 调底层的文件系统到硬盘去读取超级块内容,比如ext文件系统,ext2文件系统等等都定义了该函数。	if (!type->read_super(s,data, silent)) {		s->s_dev = 0;		return NULL;	}	s->s_dev = dev;	s->s_covered = NULL;	s->s_rd_only = 0;	s->s_dirt = 0;	s->s_type = type;	return s;}
   
     
 
    
    AI代码助手复制代码

主要是获取一个超级块结构体,然后调底层文件系统的read_super。然后设置超级块的属性。这里分析一下ext文件系统的read_super。

   
     
 
    
    struct super_block *ext_read_super(struct super_block *s,void *data,				   int silent){	struct buffer_head *bh;	struct ext_super_block *es;	int dev = s->s_dev,block;	lock_super(s);	set_blocksize(dev, BLOCK_SIZE);	// 读取设备的内容,即超级块的内容	if (!(bh = bread(dev, 1, BLOCK_SIZE))) {		s->s_dev=0;		unlock_super(s);		printk("EXT-fs: unable to read superblock\n");		return NULL;	}	// 文件系统的一些属性	es = (struct ext_super_block *) bh->b_data;	s->s_blocksize = 1024;	s->s_blocksize_bits = 10;	s->u.ext_sb.s_ninodes = es->s_ninodes;	s->u.ext_sb.s_nzones = es->s_nzones;	s->u.ext_sb.s_firstdatazone = es->s_firstdatazone;	s->u.ext_sb.s_log_zone_size = es->s_log_zone_size;	s->u.ext_sb.s_max_size = es->s_max_size;	s->s_magic = es->s_magic;	s->u.ext_sb.s_firstfreeblocknumber = es->s_firstfreeblock;	s->u.ext_sb.s_freeblockscount = es->s_freeblockscount;	s->u.ext_sb.s_firstfreeinodenumber = es->s_firstfreeinode;	s->u.ext_sb.s_freeinodescount = es->s_freeinodescount;	brelse(bh);	if (s->s_magic != EXT_SUPER_MAGIC) {		s->s_dev = 0;		unlock_super(s);		if (!silent)			printk("VFS: Can't find an extfs filesystem on dev 0x%04x.\n",				   dev);		return NULL;	}	if (!s->u.ext_sb.s_firstfreeblocknumber)		s->u.ext_sb.s_firstfreeblock = NULL;	else		if (!(s->u.ext_sb.s_firstfreeblock = bread(dev,			s->u.ext_sb.s_firstfreeblocknumber, BLOCK_SIZE))) {			printk("ext_read_super: unable to read first free block\n");			s->s_dev = 0;			unlock_super(s);			return NULL;		}	if (!s->u.ext_sb.s_firstfreeinodenumber)		s->u.ext_sb.s_firstfreeinodeblock = NULL;	else {		block = 2 + (s->u.ext_sb.s_firstfreeinodenumber - 1) / EXT_INODES_PER_BLOCK;		if (!(s->u.ext_sb.s_firstfreeinodeblock = bread(dev, block, BLOCK_SIZE))) {			printk("ext_read_super: unable to read first free inode block\n");			brelse(s->u.ext_sb.s_firstfreeblock);			s->s_dev = 0;			unlock_super (s);			return NULL;		}	}	unlock_super(s);	/* set up enough so that it can read an inode */	s->s_dev = dev;	// 操作函数集	s->s_op = &ext_sops;	// 读取根节点	if (!(s->s_mounted = iget(s,EXT_ROOT_INO))) {		s->s_dev=0;		printk("EXT-fs: get root inode failed\n");		return NULL;	}	return s;}
   
     
 
    
    AI代码助手复制代码

主要工作是读取硬盘的超级块信息到内存,最后读取根节点对应的inode。

到此,相信大家对“基于linux分怎么实现虚拟文件系统初始化”有了更深的了解,不妨来实际操作一番吧!这里是亿速云网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

亿速云「云服务器」,即开即用、新一代英特尔至强铂金CPU、三副本存储NVMe SSD云盘,价格低至29元/月。点击查看>>

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

原文链接:https://my.oschina.net/u/4217331/blog/4379401

AI

开发者交流群×