云题海 - 专业文章范例文档资料分享平台

当前位置:首页 > Linux内核中断管理和延迟函数(BH)

Linux内核中断管理和延迟函数(BH)

  • 62 次阅读
  • 3 次下载
  • 2026/4/23 12:45:12

Linux Interrupt Management

}; IPI_RESCHEDULE, IPI_CALL_FUNC, IPI_CALL_FUNC_SINGLE, IPI_CPU_STOP, January 1, 2013

发送IPI使用如下函数:

void send_ipi_message(const struct cpumask *mask, enum ipi_msg_type msg) 1.8 MSI和MSI-X中断

MSI全称Message Signaled Interrupt。当设备向一个特殊地址写入时,会向CPU产生一个中断,即也MSI中断。

MSI能力最初在PCI 2.2里定义,在PCI 3.0里被强化,使得每个中断都可以单独控制。PCI 3.0还引入了MSI-X能力,相比MSI,每个设备可以支持更多的中断,并且可以独立配置。设备可以同时支持MSI和MSI-X,但同一时刻只能使能其中一种。

1.8.1 为什么使用MSI

与传统引脚中断相比,有三个方面的优势。

基于引脚的PCI中断经常在几个设备间共享,内核必须调用与该中断相关的每一个中断处理函数,降低了效率。MSI不是共享的,所以不存在这个问题。

当设备向内存写入数据,然后发起引脚中断时,有可能在CPU收到中断时,数据还未到达内存(在PCI-PCI桥后的设备更有可能如此)。为了保证数据已达 内存,中断处理程序必须轮询产生该中断的设备的一个寄存器,PCI事务保序规则会确保所有数据到达内存后,寄存器才会返回值。

使用MSI时,产生中断的写不能越过数据写,因而避免了这个问题。当中断产生时,驱动可以确信所有数据已经到达内存。

PCI的每个功能设备只支持一个基于引脚的中断,驱动常常需要查询设备来确定发生的事件,降低了中断处理的效率。通过MSI,一个设备可以支持多个中断,这样可以为不同的使用不同的中断。比如:

1. 给不常发生的事件(如错误)指定独立的中断,这样驱动可以正常中断路径进行更有效的处理。

2. 给网卡的每个报文队列或者存储控制器的每个端口分配中断。

44

Linux Interrupt Management January 1, 2013

1.8.2 如何使用MSI

PCI设备初始化为使用基于引脚的中断,设备驱动需要将设备配置为使用MSI或MSI-X。不是所有的设备可以完整支持MSI,下面有些API就直接返回失败,因此仍然使用基于引脚的中断。

1.8.3 内核提供MSI支持

内核需要配置CONFIG_PCI_MSI以支持MSI或者MSI-X,该配置是否可以配置受架构和其它一些配置的影响。

大部分工作在PCI层的驱动里完成,只需要请求PCI层为设备设置MSI能力即可。

int pci_enable_msi(struct pci_dev *dev) int pci_enable_msi_block(struct pci_dev *dev, int count) void pci_disable_msi(struct pci_dev *dev) 1.8.4 MSI-X

MSI-X能力比MSI更为灵活,它支持2048个中断,每个中断都可以单独控制。要支持这种能力,驱动必须使用结构数组struct msix_entry。

int pci_enable_msix(struct pci_dev *dev, struct msix_entry *entries, int nvec) void pci_disable_msix(struct pci_dev *dev) 1.9 典型的中断处理方式实例

/* intrpt.c - An interrupt handler. * * Copyright (C) 2001 by Peter Jay Salzman */ /* The necessary header files */ /* Standard in kernel modules */ #include /* We're doing kernel work */ #include /* Specifically, a module */ /* Deal with CONFIG_MODVERSIONS */ #if CONFIG_MODVERSIONS==1 #define MODVERSIONS #include #endif #include #include 45

Linux Interrupt Management January 1, 2013

/* We want an interrupt */ #include #include /* In 2.2.3 /usr/include/linux/version.h includes a macro for this, but * 2.0.35 doesn't - so I add it here if necessary. */ #ifndef KERNEL_VERSION #define KERNEL_VERSION(a,b,c) ((a)*65536+(b)*256+(c)) #endif /* Bottom Half - this will get called by the kernel as soon as it's safe * to do everything normally allowed by kernel modules. */ static void got_char(void *scancode) { printk(\ (int) *((char *) scancode) & 0x7F, *((char *) scancode) & 0x80 ? \} /* This function services keyboard interrupts. It reads the relevant * information from the keyboard and then scheduales the bottom half * to run when the kernel considers it safe. */ void irq_handler(int irq, void *dev_id, struct pt_regs *regs) { /* This variables are static because they need to be * accessible (through pointers) to the bottom half routine. */ static unsigned char scancode; static struct tq_struct task = {NULL, 0, got_char, &scancode}; unsigned char status; /* Read keyboard status */ status = inb(0x64); scancode = inb(0x60); /* Scheduale bottom half to run */ #if LINUX_VERSION_CODE > KERNEL_VERSION(2,2,0) queue_task(&task, &tq_immediate); #else queue_task_irq(&task, &tq_immediate); #endif mark_bh(IMMEDIATE_BH); } /* Initialize the module - register the IRQ handler */ int init_module() { /* Since the keyboard handler won't co-exist with another handler, 46

Linux Interrupt Management January 1, 2013

* such as us, we have to disable it (free its IRQ) before we do * anything. Since we don't know where it is, there's no way to * reinstate it later - so the computer will have to be rebooted * when we're done. */ free_irq(1, NULL); /* Request IRQ 1, the keyboard IRQ, to go to our irq_handler. * SA_SHIRQ means we're willing to have othe handlers on this IRQ. * SA_INTERRUPT can be used to make the handler into a fast interrupt. */ return request_irq(1, /* The number of the keyboard IRQ on PCs */ irq_handler, /* our handler */ SA_SHIRQ, \} /* Cleanup */ void cleanup_module() { /* This is only here for completeness. It's totally irrelevant, since * we don't have a way to restore the normal keyboard interrupt so the * computer is completely useless and has to be rebooted. */ free_irq(1, NULL); } 2 可延迟函数

2.1 软中断 - BH(Bottom Half) 2.1.1 实现

软中断是利用硬件中断的概念,用软件方式进行模拟,实现宏观上的异步执行效果。很多情况下,软中断和\信号\有些类似,同时,软中断又是和硬中断相对应的,\硬中断是外部设备对CPU的中断\,\软中断通常是硬中断服务程序对内核的中断\,\信号则是由内核(或其他进程)对某个进程的中断\。

软中断是静态分配的; tasklet也是一个软中断,在它上面的函数的分配和初始化可以动态进行。

可延迟函数基本操作:初始化、激活、屏蔽、执行 Linux 2.6 使用的软中断:

/*他们的优先级递减(即由软中断编码决定)*/ enum { HI_SOFTIRQ=0, 47

搜索更多关于: Linux内核中断管理和延迟函数(BH) 的文档
  • 收藏
  • 违规举报
  • 版权认领
下载文档10.00 元 加入VIP免费下载
推荐下载
本文作者:...

共分享92篇相关文档

文档简介:

Linux Interrupt Management }; IPI_RESCHEDULE, IPI_CALL_FUNC, IPI_CALL_FUNC_SINGLE, IPI_CPU_STOP, January 1, 2013 发送IPI使用如下函数: void send_ipi_message(const struct cpumask *mask, enum ipi_msg_type msg) 1.8 MSI和MSI-X中断 MSI全称Message Signaled Interrupt。当设备向一个特殊地址写入时,会向CPU产生一个中断,即也MSI中断。 MSI能力最初在PCI 2.2里定义,在PCI 3.0里被强化,使得每个中断都可以单独控制。PCI 3.0还引入了MSI-X能力,相比M

× 游客快捷下载通道(下载后可以自由复制和排版)
单篇付费下载
限时特价:10 元/份 原价:20元
VIP包月下载
特价:29 元/月 原价:99元
低至 0.3 元/份 每月下载150
全站内容免费自由复制
VIP包月下载
特价:29 元/月 原价:99元
低至 0.3 元/份 每月下载150
全站内容免费自由复制
注:下载文档有可能“只有目录或者内容不全”等情况,请下载之前注意辨别,如果您已付费且无法下载或内容有问题,请联系我们协助你处理。
微信:fanwen365 QQ:370150219
Copyright © 云题海 All Rights Reserved. 苏ICP备16052595号-3 网站地图 客服QQ:370150219 邮箱:370150219@qq.com