Linux内核中的中断栈与内核栈的补充说明

论坛 期权论坛     
选择匿名的用户   2021-5-23 02:01   12   0
<div class="tit6">
<a href="">Linux内核中的中断栈与内核栈的补充说明</a> (2012-02-20 20:17)
</div>
<div class="tit7">
<a href="http://blog.chinaunix.net/space.php?uid&#61;23769728&amp;do&#61;tag">标签</a>:  
<a href="http://blog.chinaunix.net/space.php?uid&#61;23769728&amp;do&#61;tag&amp;id&#61;271989">Linux内核栈</a>  
<a href="http://blog.chinaunix.net/space.php?uid&#61;23769728&amp;do&#61;tag&amp;id&#61;271990">中断栈</a>  
<a href="http://blog.chinaunix.net/space.php?uid&#61;23769728&amp;do&#61;tag&amp;id&#61;271991">Linux中断处理</a>  
<a href="http://blog.chinaunix.net/space.php?uid&#61;23769728&amp;do&#61;tag&amp;id&#61;22079">设备驱动</a>  分类:
<a href="http://blog.chinaunix.net/space.php?uid&#61;23769728&amp;do&#61;blog&amp;frmd&#61;0&amp;classid&#61;152217&amp;view&#61;me"> Linux系统内核</a>
</div>
<div class="detail" id="detail" style="line-height:1.3">
<p><span style="font-size:16px"><span style="font-family:黑体">中断栈与内核栈的话题更多地属于内核的范畴,所以在《深入Linux设备驱动程序内核机制》第5章“中断处理”当中,基本上没怎么涉及到上述内容,只是在5.4节有些许的文字讨论中断栈在中断嵌套情形下可能的溢出问题。<br> <br> 本贴在这个基础上对内核栈与中断栈的话题做些补充,讨论基于x86 32位系统,因为64位系统下Linux内核关于栈的支持原理上是相同的,不过也有些特性属于64位特有的,比如IST(Interrupt Stack Table),如果可能将来会在processor版块发个帖子专门讨论。</span><br> <br> <span style="font-family:黑体">1. <strong>x86下内核栈与中断栈是否共享的问题<br> </strong><br> 我们知道Linux系统下每个用户进程都有个task_struct对象来表示,同时在处理器层面还对应一个TSS(Task State Segment),当中断发生时,用户进程或者处于用户态(ring 3)或者处于内核态(ring 0),如果是在用户态,那么会发生栈的切换问题,也就是会切换到内核态的栈,如果是在内核态,那么就没有栈切换的问题。但是x86处理器在ring 0上只有一个ESP,这意味着中断发生后,只能使用一个栈,这个栈就是内核栈(kernel stack)。处理器的硬件逻辑会将被中断进程的下条指令(CS,EIP)以及EFLAG压入栈,当然如果发生用户态栈向内核态栈的切换,处理器还会把用户态的(SS, ESP)也压入栈,此时使用的就是内核栈。这个行为属于处理器的硬件逻辑范畴,不是系统软件的行为。<br> <br> 至于x86下内核栈与中断栈是否共享的问题,其实是个内核设计的问题,换言之,中断栈可与内核栈共享,也可重新分配一个独立的中断栈。2.4的内核版本似乎采用中断栈与内核栈共享的设计,因为这种设计的好处是代码相对简单,如前所述,直接使用ESP0就可以了,但是负面因素是中断栈如果发生嵌套,可能破坏内核栈的一些数据,因为毕竟共享,所以栈空间有时候难免会捉襟见肘。所以在2.5内核版本开发中,来自IBM的一位大侠曾提交过一个补丁(详见http://lwn.net/Articles/21846/),试图在中断发生时,从内核栈switch到一个独立的中断栈中,后来也不知道被内核社区采纳了没有,总之我现在在3.2的内核源码中没有看到那位仁兄的补丁代码了,当然也可能是那个补丁已经长成现在的代码样子了。<br> <br> 现在的Linux内核中采用的是内核栈与中断栈分离的设计,下面我们从源码层面来看一看这种分离是如何完成的。<br> <br> </span></span><span style="font-size:16px"><span style="font-family:黑体">内核栈与中断栈分离的核心代码发生在do_IRQ() --&gt; handle_irq() --&gt; execute_on_irq_stack()<br> 最后一个函数字面上的意思大约是在中断栈中执行中断处理例程,也就是说中断的处理函数会在独立于被中断进程的上下文中执行。execute_on_irq_stack的函数实现为:<br> <br> <span style="font-family:Courier">&lt;arch/x86/kernel/irq_32.c&gt;</span></span><span style="font-family:Courier"><br> <br> </span></span></p>
<div class="codeText" id="codeText">
  <ol class="dp-css" style="margin:0px 1px 0px 0px; padding:5px 0px"><li><span style="font-family:Courier"><span style="color:#000000">static inline <span style="color:#ff00"> int</span><br> </span></span></li><li><span style="font-family:Courier"><br> </span></li><li><span style="font-family:Courier">execute_on_irq_stack<span style="color:#00cc">(</span><span style="color:#ff00">int</span> overflow<span style="color:#00cc">,</span> struct irq_desc <span style="color:#00cc">*</span>desc<span style="color:#00cc">,</span> <span style="color:#ff00"> int</span> irq<span style="color:#00cc">)</span><br> </span></li><li><span style="font-family:Courier"><br> </span></li><li><span style="font-family:Courier"><span style="color:#00cc">{<!-- --></span><br> </span></li><li><span style="font-family:Courier">        union irq_ctx <span style="color:#00cc"> *</span>curctx<span style="c
分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:3875789
帖子:775174
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP