- 论坛徽章:
- 0
|
FreeBSD6.2中断
qiuhan
2007.9.10
本文参考了《FreeBSD 5 内核源代码分析之中断处理》,转载请注明,谢谢!
FreeBSD6.2中断处理程序是在线程的上下文中运行的,如果是快速中断,则直接在
当前进程的上下文运行; 否则,设置相应内核中断线程的状态,并等待线程调度来执行
中断线程(由于中断线程优先级很高,不会等的心碎)
与之前的版本有所不同,6.2不是在注册中断源的时候为其创建内核中断线程,而是在
真正为中断添加处理方法的时候根据是否快速中断来选择是否创建中断线程,这样可以
避免资源浪费,例如有些irq中断很可能没有处理程序。为此6.2中增加了一种结构
intr_event来替代结构中断线程ithd在结构中断源intsrc中的位置,并使用
#define ithd intr_event
来保持兼容。而现在的结构中断线程只能改名叫intr_thread(但愿有人会因为你的
改名而喜欢上你)
重要数据结构:
===========
struct intsrc {
struct pic *is_pic; //中断源对应的中断控制器(见下)
struct intr_event *is_event; //中断事件
...
};
中断源就是一个纽带,连接了中断控制器和中断事件。中断处理函数最喜欢的就是它。
所有的中断源都会通过intr_register_source注册到如下数组中:
static struct intsrc *interrupt_sources[NUM_IO_INTS];
#define NUM_IO_INTS 255 //之前的版本中该值为191
struct pic {
void (*pic_enable_source)(struct intsrc *);
void (*pic_disable_source)(struct intsrc *, int);
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 pic *);
void (*pic_resume)(struct pic *);
int (*pic_config_intr)(struct intsrc *, enum intr_trigger,
enum intr_polarity);
void (*pic_assign_cpu)(struct intsrc *, u_int apic_id);
STAILQ_ENTRY(pic) pics;
};
pic(programmable interrupt controller)可以为8259A,I/O APIC。
该结构标识的是中断控制器的方法,如,pic_vector取得中断向量,
pic_eoi_source中断结束。正如你所预料,每个中断控制器的操作方法不一样,
所以需要这种类似MAC的钩子函数。所有的pic都会通过intr_register_pic
注册到全局的链表pics中:
static STAILQ_HEAD(, pic) pics;
struct intr_event {
...
TAILQ_HEAD(, intr_handler) ie_handlers; /* Interrupt handlers. */
...
struct intr_thread *ie_thread; /* Thread we are connected to. */
...
};
中断事件。ie_handlers保存着中断处理方法(Interrupt handlers)的链表,中断处理时
会依次调用该链表中挂载的函数。ie_thread是该中断事件对应的中断线程(只有在ie_handlers
中存在非快速中断时才会存在该中断的内核中断线程。)
struct intr_handler {
driver_intr_t *ih_handler; /* Handler function. */
void *ih_argument; /* Argument to pass to handler. */
...
struct intr_event *ih_event; /* Event we are connected to. */
...
};
中断处理方法。ih_handler是函数指针,ih_argument是调用该函数时传给它的参数。
struct intr_thread {
struct intr_event *it_event;
struct thread *it_thread; /* Kernel thread. */
...
};
中断线程。it_thread是该中断的内核中断线程的指针。
irq中断:
========
1 设置idt
init386 -> atpic_startup -> setidt
为8259A的16个irq设置中断描述项,对应的中断向量为32-47
其中slave 8259A的pin 2(irq2)用于连接master PIC,不为其设置中断向量
2 注册
atpic_init调用intr_register_source,注册15个irq,在数组interrupt_sources
中占用0-15(irq2为空).
intr_register_source以中断源指针为参数,利用其中的pic指针调用pic_vector得到
对应的中断向量,判断interrupt_sources中以该向量为下标的对应项是否为空;如果为空
则通过intr_event_create为其创建一个中断事件(之前的版本直接在这里调用ithread_create
创建一个内核中断线程),并把interrupt_sources中的对应项赋值。
如果使能apic,ioapic_register注册23个irq
3 设备
a 分配irq号:
isa: isa设备的irq(以及drq,port等)是通过/boot/device.hints来进行分配的
设置(以sio0为例):
(gdb) bt
#0 isa_set_resource (dev=0xc1cbe600, child=0xc1d5ad00, type=1, rid=0, start=4, count=1) at ../../../isa/isa_common.c:963
#1 0xc071ed20 in BUS_SET_RESOURCE (_dev=0xc1cbe600, _child=0xc1d5ad00, _type=1, _rid=0, _start=4, _count=1) at ./bus_if.h:445
#2 0xc071ecaf in bus_set_resource (dev=0xc1d5ad00, type=1, rid=0, start=4, count=1) at ../../../kern/subr_bus.c:3448
#3 0xc06c51ca in isahint_add_device (parent=0xc1cbe600, name=0xc0b07e59 "sio", unit=0) at ../../../isa/isahint.c:74
#4 0xc06c5497 in isahint_identify (driver=0xc0a9467c, parent=0xc1cbe600) at ../../../isa/isahint.c:111
#5 0xc071e092 in DEVICE_IDENTIFY (driver=0xc0a9467c, parent=0xc1cbe600) at ./device_if.h:143
#6 0xc071e019 in bus_generic_probe (dev=0xc1cbe600) at ../../../kern/subr_bus.c:2854
#7 0xc06c431a in isa_probe_children (dev=0xc1cbe600) at ../../../isa/isa_common.c:533
#8 0xc096db59 in configure (dummy=0x0) at ../../../i386/i386/autoconf.c:120
#9 0xc06d017d in mi_startup () at ../../../kern/init_main.c:210
#10 0xc044aa35 in begin () at ../../../i386/i386/locore.s:348
bus_generic_probe利用本dev所属的devclass中drivers(名为hint的driver)调用isahint_identify(参见bus)
isahint_identify对所有含有at="isa"的设备调用isahint_add_device
isahint_add_device使用name和unit为参数调用resource_int_value来获取irq(以及drq,port等)的值,如果成功且该值大于0则调用bus_set_resource
设置资源(并不是分配)
isa_set_resource利用child的ivars指针得到设备的资源列表id_resources,并使用resource_list_add把新的irq资源插入尾端
分配:
(gdb) bt
#0 isa_get_resource_list (dev=0xc1cbe600, child=0xc1d5ad00) at ../../../isa/isa_common.c:988
#1 0xc071e8d0 in BUS_GET_RESOURCE_LIST (_dev=0xc1cbe600, _child=0xc1d5ad00) at ./bus_if.h:523
#2 0xc071e807 in bus_generic_rl_get_resource (dev=0xc1cbe600, child=0xc1d5ad00, type=1, rid=0, startp=0x0, countp=0x0) at ../../../kern/subr_bus.c:3213
#3 0xc071edbc in BUS_GET_RESOURCE (_dev=0xc1cbe600, _child=0xc1d5ad00, _type=1, _rid=0, _startp=0x0, _countp=0x0) at ./bus_if.h:474
#4 0xc071ed4b in bus_get_resource (dev=0xc1d5ad00, type=1, rid=0, startp=0x0, countp=0x0) at ../../../kern/subr_bus.c:3462
#5 0xc0957535 in sioprobe (dev=0xc1d5ad00, xrid=0, rclk=1843200, noprobe=0) at ../../../dev/sio/sio.c:543
#6 0xc095affe in sio_isa_probe (dev=0xc1d5ad00) at ../../../dev/sio/sio_isa.c:159
#7 0xc071cc39 in DEVICE_PROBE (dev=0xc1d5ad00) at ./device_if.h:106
#8 0xc071ca6b in device_probe_child (dev=0xc1cbe600, child=0xc1d5ad00) at ../../../kern/subr_bus.c:1715
#9 0xc071d35b in device_probe_and_attach (dev=0xc1d5ad00) at ../../../kern/subr_bus.c:2328
#10 0xc06c4455 in isa_probe_children (dev=0xc1cbe600) at ../../../isa/isa_common.c:575
#11 0xc096db59 in configure (dummy=0x0) at ../../../i386/i386/autoconf.c:120
#12 0xc06d017d in mi_startup () at ../../../kern/init_main.c:210
#13 0xc044aa35 in begin () at ../../../i386/i386/locore.s:348
sioprobe调用bus_get_resource获取irq资源,isa_get_resource_list获取child的资源列表,bus_generic_rl_get_resource在该表中查找对应的irq资源。
最终的资源都是通过nexus_alloc_resource分配。
http://people.freebsd.org/~jhb/papers/bsdcan/2007/article/node4.html
pc/at 主从8259A中断控制器:
主8259A的pin2用于和从8259A相连(对于pc98是pin7),所以irq2不可用。
irq0: isa timer
irq1: keyboard controller
irq3,4: serial ports
irq6: floppy controller
irq7: line printer
irq8: real time clock
irq12: ps/2 mouse
irq13: floating point co-processor(optional)
irq14,15: ide controllers
以上均为isa中断,所以pci中断可以用的irq为:5, 9, 10, and 11
由于isa设备可能更多,需要互斥的占用irq(例如声卡经常占用irq5),所以pci可用的irq集合不是
确定的。为此,增加了PIR(Programmable Interrupt Routers).
pci:
PIR(Programmable Interrupt Routers):
PIR用于把pic中断信号路由到一个中断控制器的输入。例如pci slot 1和slot 2连接成a single input pin
(称为a PCI Link Device)路由到一个irq5.但是,这种路由会把slot 1和slot 2都映射到(共享)irq5,
不能单独设置irq。
(gdb) bt
#0 pci_alloc_resource (dev=0xc1cbee00, child=0xc1cbe800, type=1, rid=0xc1020b6c, start=0, end=4294967295, count=1, flags=6)
at ../../../dev/pci/pci.c:1795
#1 0xc071dd3a in BUS_ALLOC_RESOURCE (_dev=0xc1cbee00, _child=0xc1cbe800, _type=1, _rid=0xc1020b6c, _start=0, _end=4294967295, _count=1, _flags=6)
at ./bus_if.h:263
#2 0xc071ead0 in bus_alloc_resource (dev=0xc1cbe800, type=1, rid=0xc1020b6c, start=0, end=4294967295, count=1, flags=6) at ../../../kern/subr_bus.c:3347
#3 0xc0548eb6 in bus_alloc_resource_any (dev=0xc1cbe800, type=1, rid=0xc1020b6c, flags=6) at ../../../sys/bus.h:328
#4 0xc0548e65 in ed_alloc_irq (dev=0xc1cbe800, rid=0, flags=4) at ../../../dev/ed/if_ed.c:209
#5 0xc054e753 in ed_pci_attach (dev=0xc1cbe800) at ../../../dev/ed/if_ed_pci.c:104
...
pci_alloc_resource使用pci寄存器中的PCIR_INTLINE(cfg->intline)值做为irq号;如果该值无效,则调用pci_assign_interrupt请求总线分配irq。
如果分配的irq号和PCIR_INTLINE寄存器中的内容不相同,则须写回。
特例ata:
if (ata_legacy(dev)) {
int irq = (unit == 0 ? 14 : 15);
b 注册
BUS_SETUP_INTR 经过 isa_setup_intr 和多次 bus_generic_setup_intr寻找parent设备的处理方法,最终调用nexus_setup_intr。
nexus_setup_intr根据传入的irq号调用intr_add_handler。
intr_add_handler根据传入的中断向量vector调用intr_lookup_source查找对应的
中断源,然后调用intr_event_add_handler为中断源的中断事件注册中断处理方法。
intr_event_add_handler根据给定的中断处理函数,参数,名字等创建一个中断处理方法
intr_handler,如果本次添加的处理方法为互斥类型并且当前的中断事件ie的中断处理方法队列
也存在互斥类型,则直接退出。否则,添加到ie的中断处理方法队列中。如果ie的ie_thread
为空,并且本次添加的处理方法不是快速类型,则调用ithread_create创建一个内核中断线程。
c 触发
中断的触发和取消都是通过读写设备的寄存器来实现的,以ata硬盘为例:
#0 ata_generic_command (request=0xc2239660)
at ../../../dev/ata/ata-lowlevel.c:786
#1 0xc04e5f0b in ata_begin_transaction (request=0xc2239660)
at ../../../dev/ata/ata-lowlevel.c:140
#2 0xc04e9dfc in ata_start (dev=0xc2135e80)
at ../../../dev/ata/ata-queue.c:205
#3 0xc04e9aa4 in ata_queue_request (request=0xc2239660)
at ../../../dev/ata/ata-queue.c:95
#4 0xc04e4f31 in ad_strategy (bp=0xc223b108)
at ../../../dev/ata/ata-disk.c:270
#5 0xc0640b2c in g_disk_start (bp=0xc223b420) at ../../../geom/geom_disk.c:289
#6 0xc0642727 in g_io_schedule_down (tp=0xc20cda80)
at ../../../geom/geom_io.c:443
#7 0xc0642a96 in g_down_procbody () at ../../../geom/geom_kern.c:118
#8 0xc0664941 in fork_exit (callout=0xc0642a50 , arg=0x0,
frame=0xc7f62d38) at ../../../kern/kern_fork.c:841
#9 0xc088c1bc in fork_trampoline () at ../../../i386/i386/exception.s:208
IDE: write addr=0x1f6 val=0xe0 /* select device */ ATA_D_IBM|ATA_D_LBA|unit(ata_generic_command)
ide: read status addr=0x3f6 val=50 //查看状态是否为ATA_S_BUSY(ata_wait)
ide: write control addr=0x3f6 val=08 //ATA_A_4BIT /* enable interrupt */ Alt Status/Device control(PIIX:p96-97)
IDE: write addr=0x1f1 val=0x00 //Error/Features
IDE: write addr=0x1f2 val=0x20 //Sector Count
IDE: write addr=0x1f3 val=0x7f //Sector Number
IDE: write addr=0x1f4 val=0x3b //Cylinder Low
IDE: write addr=0x1f5 val=0x19 //Cylinder High
IDE: write addr=0x1f6 val=0xe0 //Drive/Head
IDE: write addr=0x1f7 val=0xc8 //Status/Command
ide: CMD=c8/* read sectors using DMA transfers */WIN_READDMA
表示从扇区号1653631(0x193b7f)开始读取32(0x20)个扇区,并使用DMA传输。
case WIN_READDMA:
case WIN_READDMA_ONCE:
if (!s->bs)
goto abort_cmd;
ide_cmd_lba48_transform(s, lba48);
ide_sector_read_dma(s);
break;
ide_sector_read_dma调用ide_dma_start,进而调用ide_read_dma_cb
ide_read_dma_cb: 如果nsector为0标志传输结束,则调用ide_set_irq启动irq;否则调用bdrv_aio_read读取磁盘。
bmdma: readb 0xc002 : 0x00 //读取状态ATA_BMSTAT_PORT的值(ata_pci_dmastart)
bmdma: writeb 0xc002 : 0x06 //写回ATA_BMSTAT_INTERRUPT|ATA_BMSTAT_ERROR
bmdma_addr_writel: 0x079ba000 //ATA_IDX_OUTL(ch, ATA_BMDTP_PORT, ch->dma->sg_bus);
/* bus address of dmatab */
bmdma: readb 0xc000 : 0x08 //读取命令ATA_BMCMD_PORT的值
bmdma_cmd_writeb: 0x00000009 //写入ATA_BMCMD_START_STOP|ATA_BMCMD_WRITE_READ
aio_read: sector_num=1653631 n=16
aio_read: sector_num=1653647 n=16
4 响应
以irq 14为例,中断产生后,中断入口Xatpic_intr14(i386/isa/atpic_vector.s)
首先准备一个中断堆栈intrframe,其中包括irq号,然后调用atpic_handle_intr。
atpic_handle_intr根据irq号从atintrs获得中断源intsrc指针,然后判断是否是伪
中断,最后把intsrc指针传给intr_execute_handlers来处理。
intr_execute_handlers根据intsrc指针获得pic指针和中断事件intr_event指针,使用pic
的方法pic_vector来获得中断向量,如果该值为0,则clkintr_pending = 1[FIXME]; 然后遍历intr_event的intr_handler链表,如果是快速中断IH_FAST,则直接在当前线程的
上下文执行,并调用pic的方法pic_eoi_source来标志中断结束,可以进行下一个中断;否则
调用pic_disable_source禁止中断(因为中断还需等待调度执行),然后调用
intr_event_schedule_thread 等待线程调度程序调用该中断的中断线程。
intr_event_schedule_thread以intr_event指针为参数,通过它可以得到对应的内核中断线程,
如果该线程的状态为等待中断,那么调用setrunqueue(td, SRQ_INTR)把该线程放到可执行队列上,
参数SRQ_INTR表明本次调度很急(urgent)。
内核中断处理线程ithread_loop负责处理本中断的所有非快速中断。它的参数是一个intr_thread
指针(该参数由ithread_create赋给kthread_create),从它可以得到中断事件intr_event的指针。
函数含有一个for (;;)循环,所以它会一直死皮赖脸的呆在系统内核中, 除非它被判死刑(标志为IT_DEAD)。
每一次for循环都会以intr_event指针为参数调用ithread_execute_handlers,处理完之后调用
mi_switch(SW_VOL, NULL)很有风度的让出cpu。
ithread_execute_handlers负责遍历intr_event的ie_handlers链表,如果不是一个快速中断处理,
就调用ih->ih_handler(ih->ih_argument);完成中断的处理。
bt
#0 ata_pio_read (request=0xc1dde000, length=512) at ../../../dev/ata/ata-lowlevel.c:792
#1 0xc04f4be2 in ata_end_transaction (request=0xc1dde000) at ../../../dev/ata/ata-lowlevel.c:291
#2 0xc04e307c in ata_interrupt (data=0xc1c9c000) at ../../../dev/ata/ata-all.c:341
#3 0xc06ea248 in ithread_execute_handlers (p=0xc1d6f648, ie=0xc1c9f580) at ../../../kern/kern_intr.c:682
#4 0xc06ea3b9 in ithread_loop (arg=0xc1d7e520) at ../../../kern/kern_intr.c:765
#5 0xc06e9008 in fork_exit (callout=0xc06ea328 , arg=0xc1d7e520, frame=0xc8560d38) at ../../../kern/kern_fork.c:821
#6 0xc0973bbc in fork_trampoline () at ../../../i386/i386/exception.s:208
ata_pio_read负责把读取数据。
ide: read status addr=0x3f6 val=50 //判断当前设备是否ATA_S_BUSY(ata_pci_status)
ide: read addr=0x1f7 val=50 /* clear interrupt and get status */ata_end_transaction
(ATA_S_READY|ATA_S_DSC),表示drive ready & drive seek completed
bmdma: readb 0xc000 : 0x09 //读取命令ATA_BMCMD_PORT的值(ata_pci_dmastop)
bmdma_cmd_writeb: 0x00000008 //非掉ATA_BMCMD_START_STOP并写回
bmdma: readb 0xc002 : 0x04 //读取状态ATA_BMSTAT_PORT的值(为ATA_BMSTAT_INTERRUPT)
bmdma: writeb 0xc002 : 0x06 //写回ATA_BMSTAT_INTERRUPT|ATA_BMSTAT_ERROR
ide_ioport_read:
case 7:
if ((!ide_if[0].bs && !ide_if[1].bs) ||
(s != ide_if && !s->bs))
ret = 0;
else
ret = s->status;
s->set_irq(s->irq_opaque, s->irq, 0);
break;
时钟中断:
========
1 设置idt:
SYSINIT(apic_init, SI_SUB_CPU, SI_ORDER_FIRST, apic_init, NULL)
apic_init中探测到的best_enum为:
i386/acpica/madt.c
static struct apic_enumerator madt_enumerator = {
"MADT",
madt_probe,
madt_probe_cpus,
madt_setup_local,
madt_setup_io
};
奇怪的是在调试是查看不到这些函数的符号表(这是在acpi.ko里)
接下来利用钩子函数调用madt_setup_local,进而调用lapic_init来初始化
local APIC。lapic_init调用setidt为时钟中断设置idt
setidt(APIC_TIMER_INT, IDTVEC(timerint), SDT_SYS386IGT, SEL_KPL,
GSEL(GCODE_SEL, SEL_KPL))
(gdb) p APIC_TIMER_INT
$144 = 239
2 初始化:
SYSINIT(clocks, SI_SUB_CLOCKS, SI_ORDER_FIRST, initclocks, NULL)
initclocks -> cpu_initclocks -> lapic_setup_clock
初始化时钟频率并启动clock[FIXME]
3 响应:
timerint准备好堆栈clockframe,然后调用lapic_handle_timer。
lapic_handle_timer会依据hz,stathz和profhz分别触发hardclock, statclock
以及profclock[FIXME]。
软中断(software interrupt):
==========================
1 初始化:
SYSINIT(start_softintr, SI_SUB_SOFTINTR, SI_ORDER_FIRST, start_softintr, NULL)
start_softintr通过swi_add登记两个重要的软件中断,软时钟中断和VM软中断.
swi_add(&clk_intr_event, "clock", softclock, NULL, SWI_CLOCK,
INTR_MPSAFE, &softclock_ih) ||
swi_add(NULL, "vm", swi_vm, NULL, SWI_VM, INTR_MPSAFE, &vm_ih)
swi_add首先调用intr_event_create创建一个中断事件intr_event,然后调用
intr_event_add_handler为该中断事件创建一个中断处理方法(可能会创建中断处理
线程)。
2 注册软时钟中断:
sio_timeout_handle = timeout(comwakeup, (void *)NULL, sio_timeout)
其中,comwakeup为中断处理函数,NULL为传给comwakeup的参数,sio_timeout为中断时间间隔
(单位是ticks)
timeout首先从callout队列callfree中取得第一个空闲的callout结构,然后调用
callout_reset注册,并返回一个callout_handle。
callout_reset利用当前的ticks加上传入的时间间隔作为下标插入callwheel中的相应队列的尾端
3 调度
harkclock如果发现链表指针callwheel中与当前ticks对应的链表不为空:
TAILQ_FIRST(&callwheel[ticks & callwheelmask]) != NULL
则调用swi_sched(softclock_ih, 0);来调度softclock运行。
而VM软中断则是在free_bounce_page中调度:
swi_sched(vm_ih, 0);
softclock有些复杂[FIXME],主要思路就是根据当前的ticks在callwheel中查找队列,
然后依次执行队列中挂载的处理函数(处理之前设置线程不可睡眠)。
4 注销:
untimeout(comwakeup, (void *)NULL, sio_timeout_handle)
comwakeup为要注销的函数,sio_timeout_handle为先前调用timeout注册时的返回值。
untimeout会判断函数和参数是否和sio_timeout_handle中的对应值相同。如果相同,则
调用callout_stop注销。callout_stop是一个宏:
#define callout_stop(c) _callout_stop_safe(c, 0)
_callout_stop_safe利用间隔时间在callwheel链表中寻找对应的队列,并把本callout
从中删除,插入到callfree队首。
6.0 8259:
db> show idt
0 Xdiv
1 Xdbg
2 Xnmi
3 Xbpt
4 Xofl
5 Xbnd
6 Xill
7 Xdna
8 0
9 Xfpusegm
10 Xtss
11 Xmissing
12 Xstk
13 Xprot
14 Xpage
16 Xfpu
17 Xalign
18 Xmchk
19 Xxmm
32 Xatpic_intr0
33 Xatpic_intr1
35 Xatpic_intr3
36 Xatpic_intr4
37 Xatpic_intr5
38 Xatpic_intr6
39 Xatpic_intr7
40 Xatpic_intr8
41 Xatpic_intr9
42 Xatpic_intr10
43 Xatpic_intr11
44 Xatpic_intr12
45 Xatpic_intr13
46 Xatpic_intr14
47 Xatpic_intr15
128 Xint0x80_syscall
db> show irq
irq0: (pid 13)
irq1: atkbd0 (pid 14) {NEED}
irq3: (pid 15)
irq4: (pid 16)
irq5: (pid 17)
irq6: (pid 18)
irq7: ppc0 (pid 19)
irq8: (pid 20)
irq9: (pid 21)
irq10: ed0 (pid 22)
irq11: (pid 23)
irq12: psm0 (pid 24)
irq13: (pid 25)
irq14: ata0 (pid 26) {ENTROPY}
irq15: ata1 (pid 27) {ENTROPY}
6.0 acpi
db> show idt
0 Xdiv
1 Xdbg
2 Xnmi
3 Xbpt
4 Xofl
5 Xbnd
6 Xill
7 Xdna
8 0
9 Xfpusegm
10 Xtss
11 Xmissing
12 Xstk
13 Xprot
14 Xpage
16 Xfpu
17 Xalign
18 Xmchk
19 Xxmm
32 Xatpic_intr0
33 Xatpic_intr1
35 Xatpic_intr3
36 Xatpic_intr4
37 Xatpic_intr5
38 Xatpic_intr6
39 Xatpic_intr7
40 Xatpic_intr8
41 Xatpic_intr9
42 Xatpic_intr10
43 Xatpic_intr11
44 Xatpic_intr12
45 Xatpic_intr13
46 Xatpic_intr14
47 Xatpic_intr15
49 Xapic_isr1
52 Xapic_isr1
55 Xapic_isr1
59 Xapic_isr1
60 Xapic_isr1
61 Xapic_isr1
62 Xapic_isr1
63 Xapic_isr1
128 Xint0x80_syscall
239 Xtimerint
255 Xspuriousint
db> show irq
irq0: (pid 36)
irq1: atkbd0 (pid 13) {NEED}
irq2: (pid 14)
irq3: (pid 15)
irq4: sio0 (pid 16)
irq5: (pid 17)
irq6: (pid 18)
irq7: ppc0 (pid 19)
irq8: (pid 20)
irq9: (pid 21)
irq10: (pid 22)
irq11: ed0 acpi0 (pid 23)
irq12: psm0 (pid 24)
irq13: (pid 25)
irq14: ata0 (pid 26) {ENTROPY}
irq15: ata1 (pid 27) {ENTROPY}
irq16: (pid 28)
irq17: (pid 29)
irq18: (pid 30)
irq19: (pid 31)
irq20: (pid 32)
irq21: (pid 33)
irq22: (pid 34)
irq23: (pid 35)
本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u1/41770/showart_452793.html |
|