航天科技2016校园招聘:笔记:中断,下半部 - unbutun的专栏 - CSDN博客

来源:百度文库 编辑:九乡新闻网 时间:2024/04/29 03:34:20
先弄清两个概念,进程上下文和中断上下文处理器总处于以下状态中的一种:
1、内核态,运行于进程上下文,内核代表进程运行于内核空间;
2、内核态,运行于中断上下文,内核代表硬件运行于内核空间;
3、用户态,运行于用户空间。用户空间的应用程序,通过系统调用,进入内核空间。这个时候用户空间的进程要传递很多变量、参数的值给内核,内核态运行的时候也要保存用户进程的一些寄存器值、变量等。所谓的“进程上下文”,可以看作是用户进程传递给内核的这些参数以及内核要保存的那一整套的变量和寄存器值和当时的环境等。硬件通过触发信号,导致内核调用中断处理程序,进入内核空间。这个过程中,硬件的一些变量和参数也要传递给内核,内核通过这些参数进行中断处理。所谓的“中断上下文”,其实也可以看作就是硬件传递过来的这些参数和内核需要保存的一些其他环境(主要是当前被打断执行的进程环境)。
响应特定中断时会执行对应的中断处理程序,硬件通过中断线通知内核发生了中断,一条中断线可以被共享.(大多数设备都是共享中断线,这意味着如果从一条中断线接收到中断,可能是这条中断线上任何设备发来的.)内核会在do_IRQ()中调用handle_IRQ_enevt()来运行对应中断线所安装的所有中断处理程序.当中断处理程序在执行时,相应的中断线会被屏蔽.所以中断处理程序不会被嵌套,即不用考虑可重入.简化了编写.怎么区分一条中断线上的不同设备?..
每一个中断处理程序里还得检测到底是不是对应的中断产生.
在中断处理程序中不能睡眠..
关于下半部:
下半部的存在是因为中断处理程序中,是关本条中断线中断,或者关所有中断的.为了要让中断处理程序尽快返回,所以把一些相对次要的工作交给下半部做.当然得注册好下半部对映的处理程序,并触发才行.下半部到底什么时候会执行呢?,即什么时候执行do_softirq();
这个问题等下再谈论,这里只要知道会在中断处理程序返回后的一段时间内执行.当然也是越快越好了.
先看下半部的实现机制.主要有五种
1.BH                 2.5中除去
2.任务队列           2.5中除去
3.软中断             2.3开始引入
4.tasklet            2.3开始引入
5.工作队列           2.5开始引入前两种是过时的,新内核基本除去.
这里主要讨论下,软中断和tasklet.软中断:
其数据结构表示为:
struct softirq{
    void (*action)(struct softirq_action *);
    void *data;
}
static struct softirq softirq_vec[32];每个注册的软件中断占该数组的一项.因此最多只能有32个软中断.软中断怎么执行的呢?
首先软中断要被设置,有一个对映这个数级的32位的位图,通过softirq_pending()宏的返回值,可以知道哪一位被设置.也就表示该软中断等待处理在do_softirq()中..也就会根据这个位图调用软中断的处理函数action;
软中断的处理函数也是不能睡眠的.tasklet:
一个tasklet基数据结构表示为:
struct task_struct{
    struct tasklet_struct *next;
    unsigned long state;
    atomic_t count;
    void (*func)(unsigned long);
    unsigned long data;
}
tasklet基于软中断实现,与软件中断的区别是
1:个数不会受限.软件中断只能是32个.而且不能像tasklet样动态的注册或去除.2.相同的tasklet不能同时执行.不同的tasklet能同时在不同的处理器上执行
  相同的软中断可以同时在所有处理器上执行.不同的也可以为什么说tasklet基于软中断实现?
因为tasklet的执行,是按这样的流程来的.
通过tasklet_schedule()或tasklet_hi_schedule(优先不同)唤起软中断中的TASKLET_SOFTIRQ或HI_SOFTIRQ.这样在do_softirq()执行时就会执行这两个软中断对应的处理函数tasklet_action()和tasklet_hi_action();这两个处理函数会扫描tasklet的链表,然后调用具体的tasklet的执行函数(task_struct结构中的func,也是不能睡眠的).当然得进行一些检查,关于count,state等字段.有两个宏in_interrupt(),和in_irq().前一个判断内核是否正在执行中断处理程序或下半部处理程序,后一个只判断内核是否正在执行中断处理程序.最后,来看软中断的执行时间,即do_softirq()的运行时间.
有两种选择:
1.中断返回时马上调用执行.这样能对软中断即时处理.但是这样
一直频繁执行软中断了(因为有的软中断本身可能还会重复触发).用户进程很可能会处于饥饿状态.
2.如果不马上执行.比如延后到下一次执行时机再执行(一般是下一次中断返回).但是这样当系统空闲时,也必须得等一段时间.这样利用率又不高.同时也可能有大量软中断得不到执行.现在内核采用第二种方法,但通过一个ksoftirqd线程来解决这一问题.这个线程就是循环调用do_softirq(),每个处理器有一个这样的线程.当有大量软中断,时该线程被唤醒.(do_softirq()中通过判断是否有重复触发,来决定唤醒ksoftirqd线程).
ksoftirqd的优先级最低,所以不会抢占用户进程,但当系统空闲时就会调用,从而解决了空闲时也得等一段时间才能处理软中断的问题.
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/unbutun/archive/2009/11/08/4783210.aspx