关于linux0.12临界资源的一点理解和猜测

       今天看代码时突然发现,好像看到linus在写代码时的一些准则了,再根据赵博士的一句话"内核开发者不可能总是关注这些细节问题的!“,然后参照自己的理解总结出来一些准则,本人初学,如果有问题还请留言指正。

       1.在关于锁的操作上,希望是原子操作,所以不管什么先关中断再说

       2.在互斥资源上,如果下面可能睡眠,那么先上锁再说,这点可以从inode.c中的read_inode函数中可以看出!

       3.如果进程修改了某些indoe等一些公共内容,如果下面有bread之类可能睡眠的函数那么先把i_dirty置1,以免丢失数据。

      4.貌似只要是进程打开的,不是用作公共有途的,如打开一个i_node用来添加目录,打开一块缓冲区用作他用,这些都算是私有的,不算是临界,共同使用同个i_node或同一个缓冲区的可能性很小?我只能这么解释他为什么在bread后在进程中不上锁了!

关于linux0.12文件系统目录大小的一个发现

今天看到empty_dir函数发现他并不是比较i_size==32来判断是否为空,而是去读所有的块来判断是否为空,然后就觉得很奇怪,不过总觉得事出必有因,翻来覆去的找了一下,终于有了点发现,去看了一下add_entry和sys_rmdir这两个函数终于发现了一个事实!那就是目录文件的大小只会增大不会减小。下面是实验的截图:

在这个实验里我们可以看到当我建立了test2 test3 test4四个文件后

test1目录变成了80,但是我删除这3个目录项后,test1目录并没有减少,这就说明了,在empty_dir中为什么linus遍历来确定目录是不是为空了!不知道这算不算是一个小bug,还是minix1.0的文件系统中本就是如此!

关于linux0.12中的add_entry中bread中的些猜测

今天看到文件系统namei.c中的add_entry部分了,发现一个问题

                        block = create_block(dir,i/DIR_ENTRIES_PER_BLOCK);
			if (!block)
				return NULL;
			if (!(bh = bread(dir->i_dev,block))) {
				i += DIR_ENTRIES_PER_BLOCK;
				continue;
			}
			de = (struct dir_entry *) bh->b_data;

可以看到,create_block也是就是当目录的i结点不存在时便会创建一个,而在create_block调用的_bamp(inode.c)函数,而bitmap函数中又调用了new_block(bitmap.c)早对磁盘块做了些测试如下:

	for (i=0 ; i<8 ; i++)
		if (bh=sb->s_zmap[i])
			if ((j=find_first_zero(bh->b_data))<8192)
				break;
	if (i>=8 || !bh || j>=8192)
		return 0;
	if (set_bit(j,bh->b_data))
		panic("new_block: bit already set");
	bh->b_dirt = 1;
	j += i*8192 + sb->s_firstdatazone-1;
	if (j >= sb->s_nzones)
		return 0;

这也就是说,不可能会出现非法block号,那么bread失败也就无从谈起了!

退一步说:如果真的失败了那

if ((char *)de >= BLOCK_SIZE+bh->b_data)

这代码又会产生什么后果呢?

所以,我认为赵博士上面的注释有点小失误,下面的注释才是最合理的解释。

这应该是从find_entry函数中拷过来的,但是由于修改时没有注意到,所以留下的一点冗余代码,

注意!!!是冗余代码不是Bug!这也告诉我们,写代码一般不要copy,否则极易出错!

linux0.12中文件系统的一些理解

在看文件系统始终觉得有点理解不了,今天偶有所悟还是赶紧记下来为好!看文件系统时要搞清以下几点:

1.文件系统是用专门的工具来格式化的,也就是说内核中文件系统的代码是不含文件系统的初始化的。其实所谓的操作系统安装就是通过一个工具来制作文件系统然后将系统文件拷入最后再加个引导,但是这个过程比单纯的格式化要麻烦许多,因为安装时要制作根文件系统而不是仅仅格式化,但原理相似!

2.要搞明白在设备中,各种设备也是就i_node的,而这个i_node也就在安装操作系统时就被制作好的。也就是说不管我们mount也好umount也好仅仅是从硬盘目录中读i_node号就行了,并不需要来自己给设备分配结点号。

3.这也就是说各种设备文件i_mode字段中的高四位是早就在安装操作系统(制作根文件系统)时就安装好的.

4.在linux0.12根文件系统中的/dev目录下的各种设备文件是在制作根文件系统时就已经制作好的,不像高版本的可以自动更新块设备等各种设备文件的个数(不确定,不过应该是可以动态更新的^_^)!

5.在修改超级块等内存数据比硬盘上对硬盘上对应的数据多一部分时,只有在修改硬盘上存储的东西时才会置*_dirty!

6.事实证明,在linux0.12中是不支持用一个软链接指向另一个软链接的!

7.软链接中不能嵌套!

关于重新编译内核后VirtualBox不能使用的问题

      编译完内核后进入linux3.0内核后,习惯性的打开virtualbox,然后突然发现virtualbox提示错误,然后又出现一个对话框,上面写着:

Nevertheless, there is no shortage of changes, such as the auto grouping of processes within a session, which has caused a lot of commotion in the Linux online world as it is expected to considerably increase the reaction speed of the desktop environment under certain ambient conditions

The VirtualBox Linux kernel driver (vboxdrv) is either not loaded or there is a permission problem with /dev/vboxdrv. Please reinstall the kernel module by executing

'/etc/init.d/vboxdrv setup'

as root. Users of Ubuntu, Fedora or Mandriva should install the DKMS package first. This package keeps track of Linux kernel changes and recompiles the vboxdrv kernel module if necessary.

      然后就开始了我的一下午的google,发现网上大都是说使用

/etc/init.d/vboxdrv setup进行重新编译,我试了之后发现仍提示
Failed, trying without DKMS ... failed!
Recompiling VirtualBox kernel modules:
Look at /var/log/vbox-install.log to find out what went wrong ... failed!

好吧,再google,又有了新的答案了,说是让使用

sudo apt-get install dkms

来安装dkms再编译,汗我还不太懂啥叫dkms,但人家说装就装呗,装着装着我就感觉不对劲,怎么净是些linux2.6.32的kernel-headers啊,我的内核可是才编译的linux-3.0的,果然,我装上dkms后再使用

/etc/init.d/vboxdrv setup

依然得到的是那个错误。

       再次google时意外的发现另一种方法:

sudo apt-get install linux-headers-$(uname -r)

去安装头文件,然后进入/usr/src/vboxhost-4.1.8/中去编译,但是不知道是我的源有问题还是内核太新了,sudo apt-get 安装失败了根本找不到linux-headers-3.0.0。

        没办法只有自己硺磨了,不管怎么说先进入/usr/src/vboxhost-4.1.8再说吧

cd /usr/src/vboxhost-4.1.8

然后编译一下试试

make

得到如下信息:

*** Building 'vboxdrv' module ***
make[1]: Entering directory `/usr/share/virtualbox/src/vboxhost/vboxdrv'
Makefile:172: *** Error: unable to find the sources of your current Linux kernel. Specify KERN_DIR=<directory> and run Make again。 停止。
make[1]: Leaving directory `/usr/share/virtualbox/src/vboxhost/vboxdrv'
make: *** [all] 错误 2


苦思冥想之后斗胆试了一下

sudo make KERN_DIR=/usr/src/linux-3.0

结果惊奇的发现似乎可以了,然后理所当然

sudo make install

理所当然的得到了如下信息

make[1]: Entering directory `/usr/share/virtualbox/src/vboxhost/vboxdrv'
Makefile:172: *** Error: unable to find the sources of your current Linux kernel. Specify KERN_DIR=<directory> and run Make again。 停止。
make[1]: Leaving directory `/usr/share/virtualbox/src/vboxhost/vboxdrv'
make: *** [install] 错误 2


于是再加个Shell变量试试

sudo make install KERN_DIR=/usr/src/linux-3.0

成功了。

       然后再执行

sudo /etc/init.d/vboxdrv setup(KERN_DIR=/usr/src/linux-3.0)

得到如下信息

Error! Your kernel headers for kernel 3.0.0 cannot be found at
/lib/modules/3.0.0/build or /lib/modules/3.0.0/source.

Failed, trying without DKMS ... failed!
Recompiling VirtualBox kernel modules:
Look at /var/log/vbox-install.log to find out what went wrong ... failed!


于是进入/lib/modules/3.0.0/然后发现source这个软链接被链接到我编译的目下去了,而我又把那个目录给移到别处了,难怪会出错了,把原目录移回来再执行,OK,一切正常了。

      再次打开virtualbox,发现又有新的错误

Failed to load unit 'HGCM' (VERR_INVALID_PARAMETER)

google后发现好像跟saved state有关,于是右键virtualbox中的windowsxp系统,选择discard saved state.

       再次重新virtualbox,OK终于进入了xp!大功告成!

ps:貌似比以前更快了哈,不知道是不是错觉!