【第8章】追踪ASSERT宏

   终于开始下篇的旅途了,没想到作者在下篇严重高估了读者,全然不像上篇那样把80%的代码拿出来讲解。刚看到第8章的开头偶就云里雾里了,这种感觉很像是第一次看上篇时的感觉,不过还好还好,偶这不是挺过上篇了么,关键还是方法问题。作者在下篇大概只拿出来了5,60%的代码出来讲,这样偶就必须在他的源代码里翻来翻去,全给扒拉出来,他的代码还好有注释,偶还得根据偶的思路来重写并加上注释。。真是辛苦。。下篇只占用了整本书的1/3,还以为很快就能搞定,看来偶真是太天真了。

 

   万事开头难,为了方便调试,首先祭出了ASSERT宏和PANIC宏,这两个宏就是拿来调试的。这次先把ASSERT宏搞定吧。这个宏在C++中相信很多人也用过吧。

 

   首先把此宏的定义找出来,

   在include/const.h中:

 

   首先是一个预处理,避免重复定义此宏。如果define了ASSERT,则先是一个函数声明:

 

   此宏有一个参数,如果这个参数为真,则不做处理,如果不为真,则调用先前声明的函数。 

 

   接着就调用它,把1个表达式转化为字符串,传进此函数,其它3个参数是被展开的文件名,传递给编译器的那个文件名,和展开成当前的行号,这样就可以方便的知道异常出现的地点。

 

   接着跟进到assertion_failure函数,

   lib/misc.c:

 

   首先调用了printl函数,这个函数其实就是printf函数的宏,等于调用了printf函数,printf函数是改进过了的,这个等会再说。函数返回以后,出现一个陀注释,意思是说,如果在系统进程中ASSERT失败,在系统会在printl函数返回halt掉,如果发生在用户进程中,则printl会正常的返回,但是随后又调用了一个spin函数,来看看这个函数:

   lib/misc.c:

 

   这个函数调用了printl把参数的串打印出来后就进入了1个死循环。后面的嵌入汇编永远不会执行。

   现在就很明了了,就是printl函数也就是printf函数做了什么改进呢,把代码贴出来。

   kernel/printf.c

 

   调用的vsprintf函数是关键,贴出来先,注释是我加的。。。乱是乱了点。。

   kernel/vsprintf.c

 

 

   逻辑很清晰,总之是把格式字符串给解析好喽返回去,其中用了一个i2a函数,可以随意设置要转化的进制数,其中用到了递归。。很好。。贴出来先。

   kernel/vsprintf.c

 

   printf函数最后调用了printx函数,printx函数就是系统调用咯,跟进去看。

   kernel/syscall.asm

 

   把栈中的解析好的串的地址放到edx中给内核使用,接着跟进到内核。

   kernel/kernel.asm

 

   先把当前指针压了进去,再把edx压了进去,我们知道这是解析好的串的地址,再把ecx,ebx压了进去,这两个参数在printx函数中是用不着的,这是为了与其它系统调用兼容,日后再说,接着就是中断调用实质性的工作了,跟入。

   kernel/proc.c

 

   这里用了一个技巧,如果k_reenter的值为0,则表示ASSERT是在用户进程中调用的,如果k_reenter的值大于0,则表示是在系统进程发生的。在用户进程发生就要把解析好的串的虚拟地址转换为线性地址,由于每个进程的LDT中的段描述符是从GDT中拷来的,只是DPL不一样,所以这里的操作暂时没什么意义,不过也要跟进一下。

 

   这个宏是根据进程的PCB指针得到相对PCB表的偏移

   include/proc.h

 

   kernel/proc.c

   ldt_seg_linear函数是根据PCB指针和此PCB的LDT的选择子偏移得到此选择子的基地址。

   va2la函数是根据进程号即相对PCB表的偏移得到参数void指针的线性地址。

 

   回到sys_printx接着判断解析好的串的第一个字符是否是约定好的字符,如果是PANIC或者ASSERT且在系统进程发生的,则往显存中一直写入解析好的串直到超过显存范围为止。写完后就嵌入汇编halt。

   如果是普通的输出或者是在用户进程发生的ASSERT则逐个字符把解析好的串叫给OutChar打印,正常退出。而用户进程的ASSERT结束输出后回到assertion_failure后调用spin函数进入死循环。

    

     这只是非常简单的把作者的代码过了一遍,还得自己写呢。。不过总算有了大概的思路。。明天继续。。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值