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

📄 super.c

📁 LINUX 0.11版内核代码。 并有代码分析说明。
💻 C
📖 第 1 页 / 共 2 页
字号:
/* passed* linux/fs/super.c** (C) 1991 Linus Torvalds*/#include <set_seg.h>
/** super.c contains code to handle the super-block tables.*/#include <linux/config.h>	// 内核配置头文件。定义键盘语言和硬盘类型(HD_TYPE)可选项。#include <linux/sched.h>	// 调度程序头文件,定义了任务结构task_struct、初始任务0 的数据,// 还有一些有关描述符参数设置和获取的嵌入式汇编函数宏语句。#include <linux/kernel.h>	// 内核头文件。含有一些内核常用函数的原形定义。#include <asm/system.h>		// 系统头文件。定义了设置或修改描述符/中断门等的嵌入式汇编宏。#include <errno.h>		// 错误号头文件。包含系统中各种出错号。(Linus 从minix 中引进的)。#include <sys/stat.h>		// 文件状态头文件。含有文件或文件系统状态结构stat{}和常量。int sync_dev (int dev);		// 对指定设备执行高速缓冲与设备上数据的同步操作。(fs/buffer.c,59)void wait_for_keypress (void);	// 等待击键。(kernel/chr_drv/tty_io.c, 140)/* set_bit()使用了setb 指令,因为汇编编译器gas 不能识别指令setc *///// 测试指定位偏移处比特位的值(0 或1),并返回该比特位值。(应该取名为test_bit()更妥帖)// 嵌入式汇编宏。参数bitnr 是比特位偏移值,addr 是测试比特位操作的起始地址。// %0 - ax(__res),%1 - 0,%2 - bitnr,%3 - addr
/*#define set_bit(bitnr,addr) ({ \register int __res __asm__( "ax"); \__asm__( "bt %2,%3;setb %%al": "=a" (__res): "a" (0), "r" (bitnr), "m" (*(addr))); \__res; })*/
extern _inline int set_bit(int bitnr,char* addr)
{
//	register int __res;
	_asm{
		xor eax,eax
		mov ebx,bitnr
		mov edx,addr
		bt [edx],ebx
		setb al
//		mov __res,eax
	}
//	return __res;
}
struct super_block super_block[NR_SUPER] = {0};	// 超级块结构数组(共8 项)。/* this is initialized in init/main.c *//* ROOT_DEV 已在init/main.c 中被初始化 */int ROOT_DEV;//// 锁定指定的超级块。static voidlock_super (struct super_block *sb){	cli ();			// 关中断。	while (sb->s_lock)		// 如果该超级块已经上锁,则睡眠等待。		sleep_on (&(sb->s_wait));	sb->s_lock = 1;		// 给该超级块加锁(置锁定标志)。	sti ();			// 开中断。}//// 对指定超级块解锁。(如果使用ulock_super 这个名称则更妥帖)。static voidfree_super (struct super_block *sb){	cli ();			// 关中断。	sb->s_lock = 0;		// 复位锁定标志。	wake_up (&(sb->s_wait));	// 唤醒等待该超级块的进程。	sti ();			// 开中断。}//// 睡眠等待超级块解锁。static voidwait_on_super (struct super_block *sb){	cli ();			// 关中断。	while (sb->s_lock)		// 如果超级块已经上锁,则睡眠等待。		sleep_on (&(sb->s_wait));	sti ();			// 开中断。}//// 取指定设备的超级块。返回该超级块结构指针。struct super_block *get_super (int dev){	struct super_block *s;// 如果没有指定设备,则返回空指针。	if (!dev)		return NULL;// s 指向超级块数组开始处。搜索整个超级块数组,寻找指定设备的超级块。	s = 0 + super_block;	while (s < NR_SUPER + super_block)// 如果当前搜索项是指定设备的超级块,则首先等待该超级块解锁(若已经被其它进程上锁的话)。// 在等待期间,该超级块有可能被其它设备使用,因此此时需再判断一次是否是指定设备的超级块,// 如果是则返回该超级块的指针。否则就重新对超级块数组再搜索一遍,因此s 重又指向超级块数组// 开始处。	if (s->s_dev == dev)	{		wait_on_super (s);		if (s->s_dev == dev)			return s;		s = 0 + super_block;// 如果当前搜索项不是,则检查下一项。如果没有找到指定的超级块,则返回空指针。	}	else		s++;	return NULL;}//// 释放指定设备的超级块。// 释放设备所使用的超级块数组项(置s_dev=0),并释放该设备i 节点位图和逻辑块位图所占用// 的高速缓冲块。如果超级块对应的文件系统是根文件系统,或者其i 节点上已经安装有其它的文件// 系统,则不能释放该超级块。voidput_super (int dev){	struct super_block *sb;//  struct m_inode *inode;	int i;// 如果指定设备是根文件系统设备,则显示警告信息“根系统盘改变了,准备生死决战吧”,并返回。	if (dev == ROOT_DEV)	{		printk ("root diskette changed: prepare for armageddon\n\r");		return;	}// 如果找不到指定设备的超级块,则返回。	if (!(sb = get_super (dev)))		return;// 如果该超级块指明本文件系统i 节点上安装有其它的文件系统,则显示警告信息,返回。	if (sb->s_imount)	{		printk ("Mounted disk changed - tssk, tssk\n\r");		return;	}// 找到指定设备的超级块后,首先锁定该超级块,然后置该超级块对应的设备号字段为0,也即即将// 放弃该超级块。	lock_super (sb);	sb->s_dev = 0;// 然后释放该设备i 节点位图和逻辑块位图在缓冲区中所占用的缓冲块。	for (i = 0; i < I_MAP_SLOTS; i++)		brelse (sb->s_imap[i]);	for (i = 0; i < Z_MAP_SLOTS; i++)		brelse (sb->s_zmap[i]);// 最后对该超级块解锁,并返回。	free_super (sb);	return;}//// 从设备上读取超级块到缓冲区中。// 如果该设备的超级块已经在高速缓冲中并且有效,则直接返回该超级块的指针。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;// 否则,首先在超级块数组中找出一个空项(也即其s_dev=0 的项)。如果数组已经占满则返回空指针。	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;// 然后锁定该超级块,并从设备上读取超级块信息到bh 指向的缓冲区中。如果读超级块操作失败,// 则释放上面选定的超级块数组中的项,并解锁该项,返回空指针退出。	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);// 如果读取的超级块的文件系统魔数字段内容不对,说明设备上不是正确的文件系统,因此同上面// 一样,释放上面选定的超级块数组中的项,并解锁该项,返回空指针退出。// 对于该版linux 内核,只支持minix 文件系统版本1.0,其魔数是0x137f。	if (s->s_magic != SUPER_MAGIC)	{		s->s_dev = 0;		free_super (s);		return NULL;	}// 下面开始读取设备上i 节点位图和逻辑块位图数据。首先初始化内存超级块结构中位图空间。	for (i = 0; i < I_MAP_SLOTS; i++)		s->s_imap[i] = NULL;	for (i = 0; i < Z_MAP_SLOTS; i++)		s->s_zmap[i] = NULL;// 然后从设备上读取i 节点位图和逻辑块位图信息,并存放在超级块对应字段中。	block = 2;	for (i = 0; i < s->s_imap_blocks; i++)		if (s->s_imap[i] = bread (dev, block))

⌨️ 快捷键说明

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