基于linux分怎么实现虚拟文件系统初始化
发表于:2025-12-02 作者:千家信息网编辑
千家信息网最后更新 2025年12月02日,本篇内容主要讲解"基于linux分怎么实现虚拟文件系统初始化",感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习"基于linux分怎么实现虚拟文件系统初始化"吧!
千家信息网最后更新 2025年12月02日基于linux分怎么实现虚拟文件系统初始化
本篇内容主要讲解"基于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();
}
下面先看一下基本的数据结构。
struct file_system_type {
struct super_block *(*read_super) (struct super_block *, void *, int);
char *name;
int requires_dev;
struct file_system_type * next;
};
这是一个具体文件系统在虚拟文件系统注册时的表示结构。然后看一下注册文件系统的函数。
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;
}
就是把一个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 x:x",
MAJOR(ROOT_DEV), MINOR(ROOT_DEV));
}
读取根设备的超级块内容,如果成功,则成为根文件系统。并设置当前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;
}
主要是获取一个超级块结构体,然后调底层文件系统的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 0xx.\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;
}
主要工作是读取硬盘的超级块信息到内存,最后读取根节点对应的inode。
到此,相信大家对"基于linux分怎么实现虚拟文件系统初始化"有了更深的了解,不妨来实际操作一番吧!这里是网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!
系统
文件
节点
设备
内容
函数
指针
结构
成功
底层
进程
工作
地址
属性
指向
数组
根目录
目录
硬盘
分析
数据库的安全要保护哪些东西
数据库安全各自的含义是什么
生产安全数据库录入
数据库的安全性及管理
数据库安全策略包含哪些
海淀数据库安全审计系统
建立农村房屋安全信息数据库
易用的数据库客户端支持安全管理
连接数据库失败ssl安全错误
数据库的锁怎样保障安全
电工 网络技术人员
做网络安全方面的ppt
杭州湾新区财务软件开发定制
vc 操作数据库
炉石传说有涉外服务器吗
南充博学软件开发公司
网络安全科学技术中心
网络安全人员怎么竞技
小程序网络安全学习
网络安全就是保存有价值的数
网络安全监控装置配置二次
烟草 大数据库
上海必知富网络技术有限公司
桌面云端有服务器吗
如何导入数据库备份
工行软件开发杭州加班
单机逃离塔科夫服务器
数据库的jdbc驱动
县级以上网络安全
服务器怪兽
电驴服务器在国内吗
安阳县委网络安全和信息化
个税申报软件开发单位
特价App招聘软件开发
优豆互联网科技广州有限公司
IMS的新数据库DDD分级
浙大图书馆数据库
图书馆能购买哪些数据库
梦创网络技术有限公司官网
县级以上网络安全