⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 super.c

📁 LINUX 0.11版内核代码。 并有代码分析说明。
💻 C
📖 第 1 页 / 共 2 页
字号:
			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)	{// 释放i 节点位图和逻辑块位图占用的高速缓冲区。		for (i = 0; i < I_MAP_SLOTS; i++)			brelse (s->s_imap[i]);		for (i = 0; i < Z_MAP_SLOTS; i++)			brelse (s->s_zmap[i]);//释放上面选定的超级块数组中的项,并解锁该超级块项,返回空指针退出。		s->s_dev = 0;		free_super (s);		return NULL;	}// 否则一切成功。对于申请空闲i 节点的函数来讲,如果设备上所有的i 节点已经全被使用,则查找// 函数会返回0 值。因此0 号i 节点是不能用的,所以这里将位图中的最低位设置为1,以防止文件// 系统分配0 号i 节点。同样的道理,也将逻辑块位图的最低位设置为1。	s->s_imap[0]->b_data[0] |= 1;	s->s_zmap[0]->b_data[0] |= 1;// 解锁该超级块,并返回超级块指针。	free_super (s);	return s;}//// 卸载文件系统的系统调用函数。// 参数dev_name 是设备文件名。intsys_umount (char *dev_name){	struct m_inode *inode;	struct super_block *sb;	int dev;// 首先根据设备文件名找到对应的i 节点,并取其中的设备号。	if (!(inode = namei (dev_name)))		return -ENOENT;	dev = inode->i_zone[0];// 如果不是块设备文件,则释放刚申请的i 节点dev_i,返回出错码。	if (!S_ISBLK (inode->i_mode))	{		iput (inode);		return -ENOTBLK;	}// 释放设备文件名的i 节点。	iput (inode);// 如果设备是根文件系统,则不能被卸载,返回出错号。	if (dev == ROOT_DEV)		return -EBUSY;// 如果取设备的超级块失败,或者该设备文件系统没有安装过,则返回出错码。	if (!(sb = get_super (dev)) || !(sb->s_imount))		return -ENOENT;// 如果超级块所指明的被安装到的i 节点没有置位其安装标志,则显示警告信息。	if (!sb->s_imount->i_mount)		printk ("Mounted inode has i_mount=0\n");// 查找i 节点表,看是否有进程在使用该设备上的文件,如果有则返回忙出错码。	for (inode = inode_table + 0; inode < inode_table + NR_INODE; inode++)		if (inode->i_dev == dev && inode->i_count)			return -EBUSY;// 复位被安装到的i 节点的安装标志,释放该i 节点。	sb->s_imount->i_mount = 0;	iput (sb->s_imount);// 置超级块中被安装i 节点字段为空,并释放设备文件系统的根i 节点,置超级块中被安装系统// 根i 节点指针为空。	sb->s_imount = NULL;	iput (sb->s_isup);	sb->s_isup = NULL;// 释放该设备的超级块以及位图占用的缓冲块,并对该设备执行高速缓冲与设备上数据的同步操作。	put_super (dev);	sync_dev (dev);	return 0;}//// 安装文件系统调用函数。// 参数dev_name 是设备文件名,dir_name 是安装到的目录名,rw_flag 被安装文件的读写标志。// 将被加载的地方必须是一个目录名,并且对应的i 节点没有被其它程序占用。intsys_mount (char *dev_name, char *dir_name, int rw_flag){	struct m_inode *dev_i, *dir_i;	struct super_block *sb;	int dev;// 首先根据设备文件名找到对应的i 节点,并取其中的设备号。// 对于块特殊设备文件,设备号在i 节点的i_zone[0]中。	if (!(dev_i = namei (dev_name)))		return -ENOENT;	dev = dev_i->i_zone[0];// 如果不是块设备文件,则释放刚取得的i 节点dev_i,返回出错码。	if (!S_ISBLK (dev_i->i_mode))	{		iput (dev_i);		return -EPERM;	}// 释放该设备文件的i 节点dev_i。	iput (dev_i);// 根据给定的目录文件名找到对应的i 节点dir_i。	if (!(dir_i = namei (dir_name)))		return -ENOENT;// 如果该i 节点的引用计数不为1(仅在这里引用),或者该i 节点的节点号是根文件系统的节点// 号1,则释放该i 节点,返回出错码。	if (dir_i->i_count != 1 || dir_i->i_num == ROOT_INO)	{		iput (dir_i);		return -EBUSY;	}// 如果该节点不是一个目录文件节点,则也释放该i 节点,返回出错码。	if (!S_ISDIR (dir_i->i_mode))	{		iput (dir_i);		return -EPERM;	}// 读取将安装文件系统的超级块,如果失败则也释放该i 节点,返回出错码。	if (!(sb = read_super (dev)))	{		iput (dir_i);		return -EBUSY;	}// 如果将要被安装的文件系统已经安装在其它地方,则释放该i 节点,返回出错码。	if (sb->s_imount)	{		iput (dir_i);		return -EBUSY;	}// 如果将要安装到的i 节点已经安装了文件系统(安装标志已经置位),则释放该i 节点,返回出错码。	if (dir_i->i_mount)	{		iput (dir_i);		return -EPERM;	}// 被安装文件系统超级块的“被安装到i 节点”字段指向安装到的目录名的i 节点。	sb->s_imount = dir_i;// 设置安装位置i 节点的安装标志和节点已修改标志。/* 注意!这里没有iput(dir_i) */	dir_i->i_mount = 1;		/* 这将在umount 内操作 */	dir_i->i_dirt = 1;		/* NOTE! we don't iput(dir_i) */	return 0;			/* we do that in umount */}//// 安装根文件系统。// 该函数是在系统开机初始化设置时(sys_setup())调用的。( kernel/blk_drv/hd.c, 157 )voidmount_root (void){	int i, free;	struct super_block *p;	struct m_inode *mi;// 如果磁盘i 节点结构不是32 个字节,则出错,死机。该判断是用于防止修改源代码时的不一致性。	if (32 != sizeof (struct d_inode))		panic ("bad i-node size");// 初始化文件表数组(共64 项,也即系统同时只能打开64 个文件),将所有文件结构中的引用计数// 设置为0。[??为什么放在这里初始化?]	for (i = 0; i < NR_FILE; i++)		file_table[i].f_count = 0;// 如果根文件系统所在设备是软盘的话,就提示“插入根文件系统盘,并按回车键”,并等待按键。	if (MAJOR (ROOT_DEV) == 2)	{		printk ("Insert root floppy and press ENTER");		wait_for_keypress ();	}// 初始化超级块数组(共8 项)。	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");//从设备上读取文件系统的根i 节点(1),如果失败则显示出错信息,死机。	if (!(mi = iget (ROOT_DEV, ROOT_INO)))		panic ("Unable to read root i-node");// 该i 节点引用次数递增3 次。因为下面266-268 行上也引用了该i 节点。	mi->i_count += 3;		/* NOTE! it is logically used 4 times, not 1 *//* 注意!从逻辑上讲,它已被引用了4 次,而不是1 次 */// 置该超级块的被安装文件系统i 节点和被安装到的i 节点为该i 节点。	p->s_isup = p->s_imount = mi;// 设置当前进程的当前工作目录和根目录i 节点。此时当前进程是1 号进程。	current->pwd = mi;	current->root = mi;// 统计该设备上空闲块数。首先令i 等于超级块中表明的设备逻辑块总数。	free = 0;	i = p->s_nzones;// 然后根据逻辑块位图中相应比特位的占用情况统计出空闲块数。这里宏函数set_bit()只是在测试// 比特位,而非设置比特位。"i&8191"用于取得i 节点号在当前块中的偏移值。"i>>13"是将i 除以// 8192,也即除一个磁盘块包含的比特位数。	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);// 统计设备上空闲i 节点数。首先令i 等于超级块中表明的设备上i 节点总数+1。加1 是将0 节点// 也统计进去。	free = 0;	i = p->s_ninodes + 1;// 然后根据i 节点位图中相应比特位的占用情况计算出空闲i 节点数。	while (--i >= 0)		if (!set_bit (i & 8191, p->s_imap[i >> 13]->b_data))			free++;// 显示设备上可用的空闲i 节点数/i 节点总数。	printk ("%d/%d free inodes\n\r", free, p->s_ninodes);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -