如何分析基于linux0.11文件系统中的根文件系统挂载原理
发表于:2024-11-18 作者:千家信息网编辑
千家信息网最后更新 2024年11月18日,如何分析基于linux0.11文件系统中的根文件系统挂载原理,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。看完文件系统的
千家信息网最后更新 2024年11月18日如何分析基于linux0.11文件系统中的根文件系统挂载原理
如何分析基于linux0.11文件系统中的根文件系统挂载原理,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。
看完文件系统的基础数据结构。我们接着解析的根文件系统的挂载,因为这是文件系统被使用的起点。根文件系统的挂载是在操作系统初始化的时候进行的。对应的函数是mount_root。
// 系统初始化时挂载根文件系统
void mount_root(void)
{
int i,free;
struct super_block * p;
struct m_inode * mi;
if (32 != sizeof (struct d_inode))
panic("bad i-node size");
// 初始化file结构体列表,struct file file_table[NR_FILE];
for(i=0;i
file_table[i].f_count=0;
// 如果根文件系统是软盘提示插入软盘
if (MAJOR(ROOT_DEV) == 2) {
printk("Insert root floppy and press ENTER");
wait_for_keypress();
}
// 初始化超级块列表
for(p = &super_block[0] ; p < &super_block[NR_SUPER] ; p++) {
p->s_dev = 0;
p->s_lock = 0;
p->s_wait = NULL;
}
// 读取某个设备(硬盘分区)中的超级块,即根文件系统的超级块
if (!(p=read_super(ROOT_DEV)))
panic("Unable to mount root");
// 获取根文件系统的第一个inode节点,里面存的是根目录的数据
if (!(mi=iget(ROOT_DEV,ROOT_INO)))
panic("Unable to read root i-node");
// mi在下面四个地方有赋值,iget里面的get_empty_inode函数已经设置i_count=1,所以这里加三就行
mi->i_count += 3 ; /* NOTE! it is logically used 4 times, not 1 */
// 超级块挂载到了mi对应的inode节点,p->s_isup设置根文件系统的根节点
p->s_isup = p->s_imount = mi;
// 设置当前进程的根文件目录和当前工作目录
current->pwd = mi;
current->root = mi;
free=0;
// 文件系统的逻辑数据块和inode数量
i=p->s_nzones;
while (-- i >= 0)
if (!set_bit(i&8191,p->s_zmap[i>>13]->b_data))
free++;
printk("%d/%d free blocks\n\r",free,p->s_nzones);
free=0;
i=p->s_ninodes+1;
while (-- i >= 0)
if (!set_bit(i&8191,p->s_imap[i>>13]->b_data))
free++;
printk("%d/%d free inodes\n\r",free,p->s_ninodes);
}
从代码中我们可以知道,该函数的主要工作是读取硬盘的超级块内容,然后申请一个inode节点作为根文件系统的根节点。最后把inode设置成当前进程的根节点。这时候的当前进程是操作系统的初始化进程。后续进程是从该进程fork出来的。所以根节点都是一样的。
下面看一下读取超级块的实现。主要逻辑是申请一个表示超级块的结构体,然后把超级块从硬盘读取进来,进行字段的初始化和处理。
// 读取dev对应的超级块
static struct super_block * read_super(int dev)
{
struct super_block * s;
struct buffer_head * bh;
int i,block;
if (!dev)
return NULL;
check_disk_change(dev);
// 在超级块表中则直接返回
if (s = get_super(dev))
return s;
// 找一个可用于存储超级块的空项
for (s = 0+super_block ;; s++) {
if (s >= NR_SUPER+super_block)
return NULL;
if (!s->s_dev)
break;
}
s->s_dev = dev;
s->s_isup = NULL;
s->s_imount = NULL;
s->s_time = 0;
s->s_rd_only = 0;
s->s_dirt = 0;
// 加锁,避免其他进程使用超级块里的数据,这时候还没读进来
lock_super(s);
// 把设备的第一块读进来,即超级块的内容
if (!(bh = bread(dev,1))) {
// 释放
s->s_dev=0;
free_super(s);
return NULL;
}
*((struct d_super_block *) s) =
*((struct d_super_block *) bh->b_data);
brelse(bh);
// 不是超级块则rollback
if (s->s_magic != SUPER_MAGIC) {
s->s_dev = 0;
free_super(s);
return NULL;
}
for (i=0;i
s->s_imap[i] = NULL;
for (i=0;i
s->s_zmap[i] = NULL;
block=2;
// 读inode和块位图信息,s_imap_blocks块表示inode位图,读进来
for (i=0 ; i < s->s_imap_blocks ; i++)
if (s->s_imap[i]=bread(dev,block)) // s_imap_blocks > 8时会溢出
block++;
else
break;
for (i=0 ; i < s->s_zmap_blocks ; i++)
if (s->s_zmap[i]=bread(dev,block))
block++;
else
break;
// 没全读成功全部释放
if (block != 2+s->s_imap_blocks+s->s_zmap_blocks) {
for(i=0;i
brelse(s->s_imap[i]);
for(i=0;i
brelse(s->s_zmap[i]);
s->s_dev=0;
free_super(s);
return NULL;
}
// 第一个不能使用,置第一个为已使用,因为找空闲块的时候,返回0表示失败。所以第0块可用的话会有二义性
s->s_imap[0]->b_data[0] |= 1;
s->s_zmap[0]->b_data[0] |= 1;
free_super(s);
return s;
}
至此,根文件系统就加载完成了。后续的对文件系统的使用都是基于这个根文件系统的根节点的。
看完上述内容是否对您有帮助呢?如果还想对相关知识有进一步的了解或阅读更多相关文章,请关注行业资讯频道,感谢您对的支持。
系统
文件
节点
进程
数据
内容
函数
硬盘
结构
操作系统
位图
时候
目录
设备
软盘
逻辑
工作
帮助
原理
分析
数据库的安全要保护哪些东西
数据库安全各自的含义是什么
生产安全数据库录入
数据库的安全性及管理
数据库安全策略包含哪些
海淀数据库安全审计系统
建立农村房屋安全信息数据库
易用的数据库客户端支持安全管理
连接数据库失败ssl安全错误
数据库的锁怎样保障安全
量化数据库技术架构
四季青国家网络安全园二期
证券公司数据库开发
湖北app软件开发的报价
深圳app软件开发定制费用
服务器机柜好做吗
网络安全个人信息保护日手抄报
软件开发管理平台开源
软件开发二年可以干嘛
怎么在手机上修改数据库的日期
阿坝网络安全应急计划
安全教育知识网络安全
qt连接数据库有网时速度比较快
贺州 网络安全
戴尔服务器管理口地址6
天津进口农业信息系统数据库
公司信息数据库怎么手绘
中新软件开发有限公司招聘
计算机网络技术的考试形式
键入网络安全密钥怎么写
腾达网络技术有限公司
neo4j与数据库连接
安系统的身份证查询数据库
湖南哪些大专学软件开发
数据库创建成功后怎么上传文件
靠谱的网络安全培训
iis服务器怎么设置安全
网络安全做开发
育碧服务器怎么登陆网吧
数据库减少了数据的冗余