同城约会| 杂志期刊| 小说| 两性论坛| 军事电影| 两性知识| 电脑知识| 汽车| 旅游| 收藏

FreeBSD 5 内核源代码分析之中断处理

来源: 作者: 出处:综艺读书 2006-10-10 
关 键 词:数据结构  

  FreeBSD 5 内核中断处理的最大特点是将中断处理程序在线程的上下文中运行。
为此,内核为每个注册的中断源(即vector)准备一个内核线程,即中断线程,
其任务就是等待中断的发生,一旦发生,便运行相应的中断处理程序。

FreeBSD 5这样做,有好处也有坏处。好处是可以简化线程和中断的互斥关系,
并使得中断处理可以阻塞。
坏处是每次响应中断都要进行线程调度,可能有两次线程上下文的切换
(从用户线程切到中断线程再切回来)。未来的想法是进行lazy scheduling,
即尽可能借用当前线程的上下文,只有在中断要阻塞时才进行真正的调度。

与中断有关的源代码主要在

sys/kern/kern_intr.c (与体系结构无关的中断代码)
sys/i386/i386/intr_machdep.c (与i386体系结构相关的中断代码)
sys/i386/isa/atpic.c (与8259A相关的.c代码)
sys/i386/isa/atpic_vector.s (与8259A相关的.s代码)

Contents

1,登记IRQ中断源
1.1 数据结构与函数
1.2 8259A的登记过程
2,IRQ中断的处理过程
3, 软件中断swi
3.1 软件中断的登记
3.2 软件中断的调度

-------------------------------
1,登记IRQ中断源

1.1 数据结构与函数

中断向量表有多个vector,0-31为CPU用,32~32+15对应IRQ0~IRQ15
一个vector对应一个source,数据类型是struct intsrc
代码:
/*
* An interrupt source. The upper-layer code uses the PIC methods to
* control a given source. The lower-layer PIC drivers can store additional
* private data in a given interrupt source such as an interrupt pin number
* or an I/O APIC pointer.
*/
struct intsrc {
struct pic *is_pic;
struct ithd *is_ithread;
u_long *is_count;
u_long *is_straycount;
u_int is_index;
};


其实在vector后面的是中断控制器,如8259A,I/O APIC等,
事实上,对中断源的控制实际上就是对中断控制器的操作,
因此,在struct intsrc中有成员struct pic *is_pic,
即中断控制器的操作函数表,通过这个表,可以为不同的中断控制器
定义不同的操作,达到demultiplex的作用。这里pic是
programmable interrupt controller的意思。
代码:
/*
* Methods that a PIC provides to mask/unmask a given interrupt source,
* "turn on" the interrupt on the CPU side by setting up an IDT entry, and
* return the vector associated with this source.
*/
struct pic {
void (*pic_enable_source)(struct intsrc *);
void (*pic_disable_source)(struct intsrc *);
void (*pic_eoi_source)(struct intsrc *);
void (*pic_enable_intr)(struct intsrc *);
int (*pic_vector)(struct intsrc *);
int (*pic_source_pending)(struct intsrc *);
void (*pic_suspend)(struct intsrc *);
void (*pic_resume)(struct intsrc *);
};

系统中所有的中断源组成一个数组,由于当采用I/O APIC作为中断控制器时,
可以有191个中断号(IRQ),因此该数组大小定义为191。
代码:
static struct intsrc *interrupt_sources[NUM_IO_INTS];

/* With I/O APIC's we can have up to 191 interrupts. */
#define NUM_IO_INTS 191

所谓登记中断源,就是将实际的中断控制器的对应struct intsrc数据结构
添加到该数组中去。同时,系统为每个登记的中断源创建一个中断线程,
中断处理程序就在该线程的上下文中运行,该线程的入口函数为ithread_loop(),

struct intsrc结构成员is_ithread指向描述中断线程的数据结构struct ithd,
而struct ithd结构成员it_td指向真正的线程结构struct thread,从而将中断
与系统的调度单元线程联系起来。

代码:
/*
* Describe an interrupt thread. There is one of these per interrupt vector.
* Note that this actually describes an interrupt source. There may or may
* not be an actual kernel thread attached to a given source.
*/
struct ithd {
struct mtx it_lock;
struct thread *it_td; /* Interrupt process. */
LIST_ENTRY(ithd) it_list; /* All interrupt threads. */
TAILQ_HEAD(, intrhand) it_handlers; /* Interrupt handlers. */
struct ithd *it_interrupted; /* Who we interrupted. */
void (*it_disable)(uintptr_t); /* Enable interrupt source. */
void (*it_enable)(uintptr_t); /* Disable interrupt source. */
void *it_md; /* Hook for MD interrupt code. */
int it_flags; /* Interrupt-specific flags. */
int it_need; /* Needs service. */
uintptr_t it_vector;
char it_name[MAXCOMLEN + 1];
};

/*
* Register a new interrupt source with the global interrupt system.
* The global interrupts need to be disabled when this function is
* called.
*/
int
intr_register_source(struct intsrc *isrc)
{
int error, vector;

vector = isrc->is_pic->pic_vector(isrc);
if (interrupt_sources[vector] != NULL)
return (EEXIST);
error = ithread_create(&isrc->is_ithread, (uintptr_t)isrc, 0,
(mask_fn)isrc->is_pic->pic_disable_source,
(mask_fn)isrc->is_pic->pic_enable_source, "irq%d:", vector);
if (error)
return (error);
mtx_lock_spin(&intr_table_lock);
if (interrupt_sources[vector] != NULL) {
mtx_unlock_spin(&intr_table_lock);
ithread_destroy(isrc->is_ithread);
return (EEXIST);
}
intrcnt_register(isrc);
interrupt_sources[vector] = isrc;
mtx_unlock_spin(&intr_table_lock);
return (0);
}

int
ithread_create(struct ithd **ithread, uintptr_t vector, int flags,
void (*disable)(uintptr_t), void (*enable)(uintptr_t), const char *fmt, ...)
{
struct ithd *ithd;
struct thread *td;
struct proc *p;
int error;
va_list ap;

/* The only valid flag during creation is 99v_SOFT. */
if ((flags & ~99v_SOFT) != 0)
return (EINVAL);

ithd = malloc(sizeof(struct ithd), M_99vHREAD, M_WA99vOK | M_ZERO);
ithd->it_vector = vector;
ithd->it_disable = disable;
ithd->it_enable = enable;
ithd->it_flags = flags;
TAILQ_IN99v(&ithd->it_handlers);
mtx_init(&ithd->it_lock, "ithread", NULL, MTX_DEF);

va_start(ap, fmt);
vsnprintf(ithd->it_name, sizeof(ithd->it_name), fmt, ap);
va_end(ap);

error = kthread_create(ithread_loop, ithd, &p, RFSTOPPED | RFHIGHPID,
0, "%s", ithd->it_name);
if (error) {
mtx_destroy(&ithd->it_lock);
free(ithd, M_99vHREAD);
return (error);
}
td = FIRST_THREAD_IN_PROC(p); /* XXXKSE */
mtx_lock_spin(&sched_lock);
td->td_ksegrp->kg_pri_class = PRI_99vHD;
td->td_priority = PRI_MAX_99vHD;
TD_SET_IWA99v(td);
更多内容请看Freebsd开发/调试  Freebsd频道  FreeBSD使用教程专题,或进入讨论组讨论。
收藏此文】【 】【打印】【关闭
较早的文章:FreeBSD 4.10 汉化总结

较新的文章:FreeBSD 5.0-Release Note
相关图文阅读
频道图文推荐
综艺读书宗旨
相关专题
·数据库处理专题 (7274篇文章)
·FreeBSD系统安全管理 (7310篇文章)
·全面解析 Linux2.6内核 (525篇文章)
·FreeBSD使用教程 (5218篇文章)
·Freebsd频道 (618篇文章)
·FreeBSD系统的使用 (83篇文章)
·Freebsd优化/安全 (77篇文章)
·Freebsd开发/调试 (66篇文章)
热点标签: 数据结构  
阅读排行榜
最新技术文档
站内各频道最新更新文档
站内最新制作专题
热门关键字导读
Photoshop教 程照片处理 照片制作 PS快捷键 抠图
计 算 机 故 障XP系统修复
艺 术 与 设 计设计 流媒体 设计欣赏 边框
计 算 机 安 全ARP
站内频道文章精选
百度推荐,商机无限
搜索您感兴趣的内容
Web 全站
综艺电脑频道编辑信箱  告诉我们您想看的专题或文章

Google

友情互链 | 收藏本站 | 联系我们 | 在线留言 | 京ICP备08008424号|