# irq_stat **Repository Path**: chenzhiy2001/irq_stat ## Basic Information - **Project Name**: irq_stat - **Description**: 基于python的中断统计工具 - **Primary Language**: Python - **License**: GPL-3.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2023-04-01 - **Last Updated**: 2023-04-01 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # Python 编写的中断统计工具:设计、实现与使用 ## 摘要 本报告介绍了一种用 Python 编写的中断统计工具,可以用来查看 CPU 上的中断绑定和中断计数器值,并且可以输出最近一段时间内产生最多的中断。这个工具利用 /proc/interrupts 文件中的信息来获取中断计数器值,并使用 argparse 和 time 两个模块来解析命令行参数和进行时间相关的操作。本报告还介绍了该工具的设计思路、代码实现以及使用方法,并且针对一些常见问题给出了解决方案。 ## 背景 在计算机系统中,中断是一种处理器和设备之间的通信机制。当外部设备需要处理器的服务时,它会向处理器发送一个中断请求,然后处理器会暂停当前的任务,跳转到中断服务程序来处理该请求。在 Linux 系统中,中断也是非常重要的一部分,因为 Linux 系统是一种多任务操作系统,有许多不同的进程在运行,而中断机制可以让这些进程在进行计算的同时处理设备的请求。 在 x86 架构的计算机系统中,中断请求是通过两条总线来实现的:中断请求总线 (IRQ) 和中断控制器总线 (INT)。当外部设备需要处理器的服务时,它会向中断控制器发送一个中断请求,然后中断控制器会将请求发送到处理器上的一个中断请求线。处理器会检查中断请求线,如果该线被激活,则会暂停当前的任务,跳转到中断服务程序来处理该请求。 为了了解系统中的中断情况,可以使用 /proc/interrupts 文件来查看中断计数器值。这个文件列出了每个 CPU 上的中断号和中断计数器值,其中每一行的第一列是中断号,后面的数字表示该中断在每个 CPU 上的计数器值。这个文件实际上是一个虚拟文件,存储在内存中,它会随着系统运行而更新。 /proc/interrupts 文件的格式如下: ``` CPU0 CPU1 CPU2 CPU3 0: 27 0 0 0 IO-APIC-edge timer 1: 1 0 0 0 IO-APIC-edge i8042 8: 0 0 0 0 IO-APIC-edge rtc0 9: 0 0 0 0 IO-APIC-fasteoi acpi 12: 0 0 0 0 IO-APIC-edge i8042 16: 0 0 0 0 IO-APIC-fasteoi ehci_hcd:usb1 17: 0 0 0 0 IO-APIC-fasteoi ehci_hcd:usb2 18: 0 0 0 0 IO-APIC-fasteoi uhci_hcd:usb3 19: 0 0 0 0 IO-APIC-fasteoi uhci_hcd:usb4 20: 0 0 0 0 IO-APIC-fasteoi uhci_hcd:usb5 21: 0 0 0 0 IO-APIC-fasteoi uhci_hcd:usb6 22: 0 0 0 0 IO-APIC-fasteoi uhci_hcd:usb7 23: 0 0 0 0 IO-APIC-fasteoi uhci_hcd:usb8 ``` 每一行代表一个中断号和其对应的计数器值,中断号位于行首,后面的数字表示该中断号的计数器值,数字之间使用空格或制表符隔开。在每个 CPU 的一行中,中断号和计数器值的列数可能会有所不同,因为某些 CPU 可能不支持某些中断。 在读取 /proc/interrupts 文件时,我们只需要读取每个中断号对应的计数器值即可。本工具的 `read_interrupts` 函数就是根据这个原理来读取 /proc/interrupts 文件的。 ## 设计 本工具是用 Python 编写的,使用 argparse 模块来解析命令行参数,使用 time 模块来进行时间相关的操作。 首先,使用 argparse 模块定义了四个命令行参数: - `-c, --cpu`:指定要查看的 CPU 编号,可以是 0 到 n-1 的整数,其中 n 是 CPU 的总数,默认值为 -1,表示查看所有 CPU。 - `-b, --bindings`:如果指定了 `-c` 参数,则输出指定 CPU 的中断绑定信息。 - `-t, --top`:查看最近一定时间内产生最多的中断,该参数后面需要指定一个时间值。 - `-i, --interval`:如果指定了 `-t` 参数,则指定查看的时间间隔,默认值为 1.0 秒。 其次,定义了三个函数: - `read_interrupts`:用来读取 /proc/interrupts 文件中的中断计数器值,并返回一个字典。 - `print_bindings`:如果指定了 `-b` 参数,则输出指定 CPU 的中断绑定信息。 - `print_top_interrupts`:如果指定了 `-t` 参数,则输出最近一段时间内产生最多的中断。 最后,在 `main` 函数中根据命令行参数调用相应的函数来执行中断统计的功能。 ## 实现 下面是这个工具的完整代码 ```python #!/usr/bin/env python3 import argparse import time def parse_args(): parser = argparse.ArgumentParser(description='中断统计工具') parser.add_argument('-c', '--cpu', type=int, default=-1, help='指定要查看的CPU') parser.add_argument('-b', '--bindings', action='store_true', help='输出指定CPU的中断绑定信息') parser.add_argument('-t', '--top', type=int, default=0, help='查看一定时间内产生最多的中断') parser.add_argument('-i', '--interval', type=float, default=1.0, help='指定时间间隔') return parser.parse_args() def read_interrupts(): interrupts = {} with open('/proc/interrupts') as f: for line in f: fields = line.split() if len(fields) > 0 and fields[0].endswith(':'): interrupts[fields[0][:-1]] = sum([int(x) if x.isdigit() else 0 for x in fields[1:]]) return interrupts def print_bindings(cpu): with open('/proc/interrupts') as f: for line in f: fields = line.split() if len(fields) > 0 and fields[0].endswith('-%d' % cpu): print(line.strip()) def print_top_interrupts(top, interval): interrupts1 = read_interrupts() time.sleep(interval) interrupts2 = read_interrupts() diffs = [(k, interrupts2[k] - interrupts1.get(k, 0)) for k in interrupts2] diffs.sort(key=lambda x: x[1], reverse=True) for i in range(min(top, len(diffs))): print('%-4s %10d' % (diffs[i][0], diffs[i][1])) def main(): args = parse_args() if args.cpu >= 0 and args.bindings: print_bindings(args.cpu) elif args.top > 0: while True: print_top_interrupts(args.top, args.interval) else: interrupts = read_interrupts() for irq in interrupts: print('%-4s %10d' % (irq, interrupts[irq])) if __name__ == '__main__': main() ``` 这个工具的主要思路是使用 argparse 模块解析命令行参数,然后根据参数调用相应的函数来执行中断统计的功能。`parse_args` 函数用来解析命令行参数,`read_interrupts` 函数用来读取 /proc/interrupts 文件中的中断计数器值,`print_bindings` 函数用来输出指定 CPU 的中断绑定信息,`print_top_interrupts` 函数用来输出最近一段时间内产生最多的中断,`main` 函数用来根据命令行参数调用相应的函数。 使用方法很简单,只需要在命令行中输入 `python irq.py` 然后加上相应的参数即可。如果要查看所有中断号和计数器值,可以执行以下命令: ```shell python irq.py ``` 如果要查看 CPU 3 上的中断绑定信息,可以执行以下命令: ```shell python irq.py -c 3 -b ``` 如果要查看最近 5 秒内产生最多的中断,可以执行以下命令: ```shell python irq.py -t 5 ``` 如果要以 1 秒的时间间隔一直查看最近产生的中断,可以执行以下命令: ```shell python irq.py -t -i 1 ``` 更详细的使用说明可以通过 `python irq.py -h` 或者 `python irq.py --help` 来查看。 ## 创建Gitee项目并提交代码 为了方便管理和分享我们编写的 Python 中断统计工具,我们可以将其上传到 Gitee 上的一个仓库中。以下是上传到 Gitee 的步骤: 1. 在 Gitee 网站上登录账号。 2. 点击右上角的 “+” 图标,选择 “新建仓库”。 3. 输入仓库名称、描述和选择是否私有,然后点击 “创建仓库”。 4. 在本地计算机上,创建一个新的文件夹,并将 Python 文件放入该文件夹中。 5. 在该文件夹中打开终端窗口,使用 `git init` 命令初始化本地仓库。 6. 使用 `git add .` 命令将代码文件添加到本地仓库中。 7. 使用 `git commit -m "initial commit"` 命令提交更改。 8. 用`ssh-keygen`工具创建一组密钥,并在Gitee中保存公钥。 9. 用`git push`命令提交代码到Gitee仓库。 ## 常见问题 我在测试本工具时遇到了一些问题。下面是这些问题及其解决方案: ### 问题 1:输出的中断计数器值不正确 这个问题可能是由于 /proc/interrupts 文件格式发生了变化导致的。如果您在使用本工具时遇到了这个问题,请尝试修改 `read_interrupts` 函数来适应新的文件格式。您可以通过查看 /proc/interrupts 文件的内容来了解其格式。 ### 问题 2:使用 `-t` 参数时工具没有输出任何内容 这个问题可能是由于您指定的时间太短,或者您的系统中没有产生足够多的中断。请尝试增加时间间隔或者等待一段时间后再次运行工具。 ### 问题 3:在使用 `-t` 参数时工具一直输出相同的内容 这个问题可能是由于您的系统中某个中断一直在持续产生,导致该中断一直处于输出列表的前几位。请尝试查看中断计数器值,并尝试找到哪个中断在持续产生,然后针对该中断进行处理。 ## 结论 本报告介绍了一种用 Python 编写的中断统计工具,它可以帮助用户查看 CPU 上的中断绑定和中断计数器值,并输出最近一段时间内产生最多的中断。在本报告中,我们介绍了中断的基本概念、x86 架构计算机系统中外设中断的原理、以及 /proc/interrupts 文件的原理。我们还展示了该工具的设计思路、代码实现以及使用方法,并针对一些常见问题给出了解决方案。 本工具的设计目的是帮助用户了解 CPU 上的中断情况,从而优化系统性能,解决可能出现的中断冲突问题。通过使用该工具,用户可以查看不同 CPU 上的中断计数器值,以及特定时间段内最活跃的中断。此外,用户也可以通过修改代码来适应不同系统的 /proc/interrupts 文件格式。 总的来说,该工具是一种简单易用的工具,适用于 Linux 系统中的中断统计和分析。它为用户提供了一种方便快捷的方式来了解系统中的中断情况,并为优化系统性能提供了帮助。