通过itop工具了解系统中每秒多少中断发生,发生在哪个CPU上。
Linux下中断来源可以从 /proc/interrupts 中了解到:
$ cat /proc/interrupts CPU0 CPU1 0: 247701 250313 IO-APIC-edge timer 1: 501 567 IO-APIC-edge i8042 3: 1 1 IO-APIC-edge 8: 1 0 IO-APIC-edge rtc0 9: 256 240 IO-APIC-fasteoi acpi 12: 1134 1149 IO-APIC-edge i8042 16: 629 554 IO-APIC-fasteoi nvidia 17: 21313 20869 IO-APIC-fasteoi firewire_ohci, eth1 18: 0 0 IO-APIC-fasteoi mmc0 19: 51822 50079 IO-APIC-fasteoi ata_piix, ata_piix 20: 5605 5255 IO-APIC-fasteoi ehci_hcd:usb2, uhci_hcd:usb3, uhci_hcd:usb6 21: 0 0 IO-APIC-fasteoi uhci_hcd:usb4, uhci_hcd:usb7 22: 33 33 IO-APIC-fasteoi ehci_hcd:usb1, uhci_hcd:usb5, uhci_hcd:usb8 45: 337 247 PCI-MSI-edge eth0 46: 441 447 PCI-MSI-edge hda_intel NMI: 0 0 Non-maskable interrupts LOC: 169176 174899 Local timer interrupts SPU: 0 0 Spurious interrupts PMI: 0 0 Performance monitoring interrupts PND: 0 0 Performance pending work RES: 42289 40236 Rescheduling interrupts CAL: 154 1076 Function call interrupts TLB: 5838 5365 TLB shootdowns TRM: 0 0 Thermal event interrupts THR: 0 0 Threshold APIC interrupts MCE: 0 0 Machine check exceptions MCP: 5 5 Machine check polls ERR: 1 MIS: 0
软中断可以从/proc/softirqs 了解到:
$ cat /proc/softirqs CPU0 CPU1 HI: 0 0 TIMER: 160508 1170976 NET_TX: 2 2 NET_RX: 3303 3165 BLOCK: 50964 49198 BLOCK_IOPOLL: 0 0 TASKLET: 24743 24284 SCHED: 39483 41848 HRTIMER: 34 40 RCU: 92193 92592
总的中断次数可以从vmstat或者dstat了解到:
$ vmstat procs -----------memory---------- ---swap-- -----io---- -system-- ----cpu---- r b swpd free buff cache si so bi bo in cs us sy id wa 3 0 0 44160 327144 876600 0 0 894 584 458 2295 11 5 70 15
itop提供了更方便的方式了解,作者Hunz在源码里面写:
It’s quite simple but it does its job.
虽然简单,但是适用:
Ubutun下可以这样安装: apt-get install itop
$ itop INT NAME RATE MAX 0 [PIC-edge time] 628 Ints/s (max: 628) 1 [PIC-edge i804] 4 Ints/s (max: 4) 17 [PIC-fasteoi fire] 8 Ints/s (max: 22) 19 [PIC-fasteoi ata_] 1 Ints/s (max: 14) 20 [PIC-fasteoi ehci] 25 Ints/s (max: 25) 45 [MSI-edge eth0] 1 Ints/s (max: 1)
他会计算每秒每个中断源中断的次数,看起来比较方便.
itop 程序代码 (redhat)
#!/usr/bin/perl # # Interrupt top # # Show the interrupts per second/per IRQ per CPU # Parse /proc/interrupts file for data # # CPU0 CPU1 # 0: 3025267376 3026744388 IO-APIC-edge timer # 1: 833854 843315 IO-APIC-edge i8042 # 6: 15 63 IO-APIC-edge floppy # 7: 0 0 IO-APIC-edge parport0 # 8: 532620 522911 IO-APIC-edge rtc # 9: 1 0 IO-APIC-level acpi # 12: 9812189 9981980 IO-APIC-edge i8042 # 14: 27181914 27208373 IO-APIC-edge ide0 # 58: 249517917 0 IO-APIC-level eth0 # 66: 1090230 1089904 IO-APIC-level ehci_hcd:usb1, uhci_hcd:usb2 # 169: 82497 85243 IO-APIC-level HDA Intel, uhci_hcd:usb5, i915@pci:0000:00:02.0 # 217: 0 0 IO-APIC-level uhci_hcd:usb4 # 233: 2809674 2795397 IO-APIC-level libata, uhci_hcd:usb3 # NMI: 0 0 # LOC: 1754237653 1754237661 # ERR: 0 # MIS: 0 use IO::File; use Term::Cap; $term = Tgetent Term::Cap; print $term->Tputs('cl'); $fh = new IO::File; if (!$fh->open("</proc/interrupts")) { die "Unable to open /proc/interrupts"; } $top = $fh->getpos(); $first_time = 0; while (1) { $fh->setpos($top); # Read and parse interrupts $header = <$fh>; # Header line # Count CPUs $cpus = () = $header =~ /CPU/g; my %irqs; while (<$fh>) { #if (/^\s*(\d+):(\s*(\d+)\s*)*(\S+)\s*(.*)$/) { if (/^\s*(\d+):\s*(\d+)\s+(\S+)\s+(.*)$/) { # Found a IRQ line, Build an assoc array of CPU values #print $1 . ":" . $2 .":". $3 .":". $4 .":". $5 .":". $6 . ":" . $7 .":". $8 .":". $9 . "\n"; $irq = $1; for ($cpu = 0; $cpu < $cpus; $cpu++) { $exp = '$icount = $' . ($cpu + 2); eval $exp; $irqs{$irq}[$cpu] = $icount } eval '$desc = $' . ($cpus + 2); $desc =~ /(\S+)\s+(.*)$/; $irq_type{$irq} = $1; $irq_device{$irq} = $2; #eval '$irq_type{$irq} = $' . ($cpus + 2); #print $irq_type{$irq} . "\n"; #eval '$irq_device{$irq} = $' . ($cpus + 3); } } if ($first_time != 0) { # Prepare sceeen print $term->Tputs('ho'); # Output header printf("%28s%" . ($cpus + 1) * 16 . "s", "", "IRQs/Second\n"); printf('%20s (%3s) ', "Device", "IRQ"); foreach ($cpu = 0; $cpu < $cpus; $cpu++) { printf('%15s ', 'CPU' . $cpu); } printf("%15s\n", "TOTAL"); foreach $irq (keys %irqs) { printf('%20s (%3d): ', substr($irq_device{$irq}, 0, 20), $irq); $total = 0; for ($cpu = 0; $cpu < 2; $cpu ++) { printf("%15s ", $irqs{$irq}[$cpu] - $last{$irq}[$cpu]); $total += $irqs{$irq}[$cpu] - $last{$irq}[$cpu]; } printf("%15s\n", $total); } } $first_time = 1; %last = %irqs; sleep 1; }