- 论坛徽章:
- 0
|
原帖由 塑料袋 于 2006-12-21 09:16 发表
不是我变的内敛,是这两天暂时没心思说废话。
我跟你论究Kernel里的程序,是一件费尽吐沫的事。我宁可让所有CUer瞧不起我,也不想把时间浪费在对一个不摸kernel门的人,讲解kernel里边的程序上。
如果你不贴你的注释,我可能会认为你真的很牛,但很遗憾,看了注释后可以明确的告诉你,你现在的功力是读核食物链的最底层,连小虾米都不是,顶多是个单细胞的浮游生物吧。我把你在285楼的问题引用过来吧,省的菜鸟和老牛都浪费时间去翻你以前的贴子。我知道你这两天心情不好,因为从我发贴到现在正好是48小时,你却依旧不能参透其中奥秘。失眠了吧?绝望了吧?
我知道这段代码已经远远超过了你的智力极限,你是一个只见语句不见语意的蠢材。你的什么《半年来我的读核体会》简直叫人笑掉大牙,你刚知道用面向对象的方式来读核?七年前这就是共识了,你却以为你找到了什么香饽饽。
等你看懂了才在CU发狂吧,从现在计时,大家都来看看塑料袋到底需要多长时间才能参透其中内核中very常见的保护机制。
- 我看的是2.4.32的内容,iput()函数相关的部分我不理解,谁如果能解答我的疑惑,感激不尽,谢谢.主要是第二个问题想不明白
- 问题一
- i_count==0时,如果inode->i_nlink>0,且inode存在于hash表中时, 有这样三行代码
- spin_lock(&inode_lock);
- inodes_stat.nr_unused--;
- list_del_init(&inode->i_hash);
- 它为什么能这么肯定的把inode从hash中删除?并且inodes_stat.nr_unused--;
- 从判断出i_count==0,到这三行代码,以前有一段时间,并没有持有自旋锁,执行到这三行时,也许已经inode->i_count>0
- 问题二
- static inline void sync_one(struct inode *inode, int sync)
- {
- while (inode->i_state & I_LOCK) {
- __iget(inode);
- spin_unlock(&inode_lock);
- __wait_on_inode(inode);
- iput(inode);
- spin_lock(&inode_lock);
- }
- __sync_one(inode, sync);
- }
- iput在i_count==0时会通过write_inode_now调用这个函数,但是在调用这个函数时,并不一定i_count>0,也许i_count=0. 因为调用write_inode_now之前,已经释放了自旋锁,使其他CPU通过hash得到本inode成为可能
- i_count=0时,SMP上另一进程在kupdate的话,会设置这个i_state为I_LOCK,所以本函数再次iget,然后又iput,
- 在这之间__wait_on_inode的时候,也许另一进程iget到这个inode,对其操作,然后把它标记为I_DIRTY
- ,在i_count==2时调用iput,结束对这个inode的使用,这时i_count==1
- 终于轮到__wait_on_inode(inode)被唤醒再次运行,这个函数在i_count==1时马上又iput,在write_inode_now时,并不持有自旋锁,并不排除SMP上运行kupdate进程的可能,因此这个inode又是I_LOCK,而i_count==0,所以又需要再次iget,iput,这样下去,进程不挂掉??????
- 关联到的代码附加如下
- iput()
- ...释放预分配块
- /* i_count--,得到inode_lock自旋锁
- * 如i_count>0,释放自旋锁,返回0,iput结束
- * 如i_count=0,继续持有自旋锁,返回1
- */
- if (!atomic_dec_and_lock(&inode->i_count, &inode_lock))
- return;
- if (!inode->i_nlink) {
- inode彻底失效,咱不说这种情况
- }else{ /* 我想了很久这种情况,这里只是暂时持有自旋锁,保证了在这个点上暂时i_count==0*/
- if (!list_empty(&inode->i_hash)) {
- if (!(inode->i_state & (I_DIRTY|I_LOCK)))
- __refile_inode(inode);
- inodes_stat.nr_unused++;
- spin_unlock(&inode_lock);
- if (!sb || (sb->s_flags & MS_ACTIVE))
- return;
- /* 执行到这里时,由于前几行代码已经释放了自旋锁,所以也许SMP已经使这个
- *inode->i_count>0
- */
- write_inode_now(inode, 1); /*执行这个函数时会不会使进程挂掉????????*/
- /* inodes_stat.nr_unused--????为什么这么肯定就能nr_unused--
- * 也许inode还有引用
- */
-
- spin_lock(&inode_lock);
- inodes_stat.nr_unused--;
- list_del_init(&inode->i_hash);
- }
- list_del_init(&inode->i_list);
- inode->i_state|=I_FREEING;
- inodes_stat.nr_inodes--;
- spin_unlock(&inode_lock);
- if (inode->i_data.nrpages)
- truncate_inode_pages(&inode->i_data, 0);
- clear_inode(inode);
- }
- void write_inode_now(struct inode *inode, int sync)
- {
- struct super_block * sb = inode->i_sb;
- if (sb) {
- spin_lock(&inode_lock);
- while (inode->i_state & I_DIRTY)
- sync_one(inode, sync);
- spin_unlock(&inode_lock);
- /* 一旦释放了自旋锁,可能inode马上再次被I_DIRTY,前边自旋锁内的循环前功尽弃。
- *
- */
- if (sync)
- wait_on_inode(inode);
- }
- else
- printk(KERN_ERR "write_inode_now: no super block\n");
- }
- /* 这时inode->i_count>0,也可能inode->i_count==0,因为在调用write_inode_now前,已经释放了自旋锁
- *
- * 假如这个进程正在被同步中, 设置了I_LOCK, 而i_count==0时,本函数再次iget,iput,又一次执行了 iput,而这次iput时,完全可能会与上一个iput执行相同的路线, 比如说在iput中write_inode_now前的瞬间,SMP上的另一个进程又把这个inode标记为脏,然后又切换进kupdate进程,进程开始同步这个inode,又设置了I_LOCK,而这时i_count==0
- 因此这个进程不会完蛋??
- */
- static inline void sync_one(struct inode *inode, int sync)
- {
- while (inode->i_state & I_LOCK) {
- __iget(inode);
- spin_unlock(&inode_lock);
- __wait_on_inode(inode);
- iput(inode);
- spin_lock(&inode_lock);
- }
- __sync_one(inode, sync);
- }
- /* 参数( inode ,是否同步)
- *
- * inode 入locked 链,释放自旋锁,执行:
- * dirty_page 链换至locked_page,回写
- * inode 回写至磁盘块,等待
- * locked_page链换至clean_page 链,等待
- * inode 得到自旋锁,清I_LOCK,按优先级顺序选择链
- */
- static inline void __sync_one(struct inode *inode, int sync)
- {
- unsigned dirty;
- /* 对inode 上锁,换链至s_locked_inodes*/
- list_del(&inode->i_list);
- list_add(&inode->i_list, &inode->i_sb->s_locked_inodes);
- if (inode->i_state & (I_LOCK|I_FREEING))
- BUG();
- /* Set I_LOCK, reset I_DIRTY */
- dirty = inode->i_state & I_DIRTY;
- inode->i_state |= I_LOCK;
- inode->i_state &= ~I_DIRTY;
- spin_unlock(&inode_lock);
- /* 不判断是否uptodata ,就将address space->dirty_pages 中的页
- * 转移至locked_pages 链,根据dirty 判断是否不等待的回写
- */
- filemap_fdatasync(inode->i_mapping);
- /* 如果inode 设置了I_DIRTY_SYNC | I_DIRTY_DATASYNC,
- * 则回写磁盘inode 和超级块
- *
- * 顺便等待页回写完成
- */
- if (dirty & (I_DIRTY_SYNC | I_DIRTY_DATASYNC))
- write_inode(inode, sync);
- /* 不判断是否uptodata ,就将address space->locked_pages 中的页
- * 转移至clean_pages 链,根据锁定 判断是否等待
- */
- filemap_fdatawait(inode->i_mapping);
- spin_lock(&inode_lock);
- /* 对inode 解锁,换链判断顺序为s_dirty_inode,inode->i_count,
- * inode->i_data.nr_pages,最后万不得已到inode_unused 链
- */
- inode->i_state &= ~I_LOCK;
- __refile_inode(inode);
- wake_up(&inode->i_wait);
- }
复制代码
我不是高手,你说的对,我就是一个不摸kernel门的人,但却比你强,你看不懂的我懂,你不会的我会。想做Linux内核大陆第一高手,先看看可不可以干掉所有cuer,我就是第一个cuer。 |
|