基于linux分怎么实现虚拟文件系统初始化
发表于:2025-02-04 作者:千家信息网编辑
千家信息网最后更新 2025年02月04日,本篇内容主要讲解"基于linux分怎么实现虚拟文件系统初始化",感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习"基于linux分怎么实现虚拟文件系统初始化"吧!
千家信息网最后更新 2025年02月04日基于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安全错误
数据库的锁怎样保障安全
数据库和文体
网络安全对国家战略的重要性
win10总跳出代理服务器认证
电脑连不上网如何ping服务器
世界互联网领先科技发布
凝思系统数据库限制访问设置
衢州万联网络技术有限公司
宿城区网络技术是什么
db2停止管理服务器
笔记本怎么做服务器的显示器
惠州汽车软件开发报价
sony电脑进入网络安全模式
软件开发工程师对身体
新疆化学品管理服务器
世界互联网科技峰会
宿迁网络安全企业
不同数据库数据存储结构
华为网络技术相关的证书
郑州轩盈网络技术有限公司
浙江网络安全特训营收费标准
网络技术韩国
数据库程序员开发笔记本推荐
和网络技术有关的参考文献
最终幻想伊修加德服务器
北京软件开发哪个公司招工
攀枝花软件开发
软件开发转让交税
信阳办公软件开发
河南工业软件开发市价
数据库访问不了如何备份