我对内核模块的开发很陌生,在我的学习过程中,我转向了中断。我的任务是为IRQ 8编写一个中断处理程序模块,它将简单地计算发生在这一行上的中断数量,并将值存储在kobject中。乍一看,这项任务听起来相对容易,但我遇到了一些奇怪的行为。我编写了一个处理程序函数,它简单地增加计数器并在处理时返回中断。
static int ir=0;
static irq_handler_t my_handler(int irq_no, void *dev_id, struct pt_regs *regs)
{
ir++;
return (irq_handler_t) IRQ_HANDLED;
}为了连接中断处理程序,我在我的request_irq()中调用了__init函数,第一个参数是8,因此处理IRQ 8 (由rtc保留)行中断。
#define RTC_IRQ 8
[...]
int err;
err = request_irq(RTC_IRQ, (irq_handler_t) my_handler,IRQF_SHARED,"rtc0",NULL);
if (err != 0)
return -1;有了上面所示的实现,加载内核模块给出的err等于-22,即EINVAL。在googling之后,我发现对于IRQF_SHARED标志,最后一个参数不能被赋值为NULL。我试图在模块中找到获取rtc->dev_id的方法,但在一些示例中,他们只是将处理程序键入到(void *)中,所以我尝试传递(void *) my_handler。这给了我一个insmod上的标志不匹配警告。
genirq: Flags mismatch irq 8. 00000080 (rtc0) vs. 00000000 (rtc0)并将错误值设置为-16,我从某些源中读取的内容意味着“繁忙”。在试图找到获得设备id的方法时,我发现中断是由rtc0设备发送的,该设备是从rtc-cmos父设备“继承”的。
在这个问题上,我在互联网上发现了不同的争议线索。有人说内核在软件时钟同步之后禁用rtc,但情况并非如此,因为在sudo bash -c ' echo +20 > /sys/class/rtc/rtc0/wakealarm '行上使用/proc/interrupts和读取IRQ 8显示中断正常工作。
其他来源指出,指向该行的所有request_irq都必须安装IRQF_SHARED标志才能共享中断行。读取rtc-cmos的源文件没有给我任何帮助,因为它们通过直接读写CMOS来设置中断。
我花了很多时间试图找出解决这个问题的方法,但似乎RTC中断在内核模块的开发中并不常见,因此很难找到与此相关的最新信息,大多数讨论和示例都与使用SA_SHIRQ-like标志和/drivers/examples文件夹的实现有关,而内核源文件是围绕内核版本2.6的。从那时起,中断和rtc内核实现都发生了变化。
任何有助于解决这一问题的提示或建议都将不胜感激。这是我的第一个StackOverflow问题,所以如果任何形式的问题是错误的或令人不安的,欢迎您在评论中指出。
提前感谢您的帮助
发布于 2022-05-26 15:43:39
我很久以前就解决了这个问题,但以下是我这样的新手的一些解释。@斯塔克为这个问题提供了一个很好的提示。
主要要理解的是,内核空间中不负责任的行为很快就会导致某种“灾难”。从表面上看,这是Linux开发人员关闭越来越多的用户/开发人员的主要原因。
在这里阅读解决方案
因此,在现代内核版本中,您不会随机地将处理程序绑定到一行,并将中断标记为已解决。但是,您仍然可以使用IRQF_SHARED标志“侦听”它们,在处理程序的末尾,通过返回IRQ_NONE使中断保持不变,因此如果中断对其他事情至关重要,则不会破坏内核其余部分的正确操作。
解决方案的端,关于下一步内核开发的一些额外建议。
首先,重要的是要了解,这不是一个用户空间,您的操作最多会导致内存泄漏或某些文件损坏。在这里,您的操作将很容易损坏您的内核。如果Windows出现了类似的情况,那么除了完全重新安装整个操作系统之外,您别无选择,但是在GNU/Linux中,情况并非如此。您可以切换到另一个内核,而不需要像以前那样经历一个恢复一切的繁琐过程,因此,如果您是一个非常懒于使用VM的铁杆爱好者,那么学习交换内核很快就会派上用场:)
https://stackoverflow.com/questions/71981461
复制相似问题