我正在尝试使用 linux softirq。 A 有一个使用 linux/interrupt.h
中定义的 linux 系统调用的简单程序:
//
// Created by kivi on 24.09.16.
//
#include <linux/module.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/stat.h>
#define SHARED_IRQ 17
static int irq = SHARED_IRQ, my_dev_id, irq_counter = 0;
module_param( irq, int, S_IRUGO );
/* The interrupt handler */
static irqreturn_t xxx_interrupt( int irq, void *dev_id ) {
printk( KERN_INFO "In the top-half: counter = %d\n", irq_counter );
raise_softirq( XXX_SOFT_IRQ );
return IRQ_HANDLED;
}
/* The bottom half */
void xxx_analyze(struct softirq_action *str) {
irq_counter++;
printk( KERN_INFO "In the bottom-half: counter = %d\n", irq_counter );
}
static int __init my_init( void ) {
request_irq( irq, xxx_interrupt, 0, "xxx", NULL );
open_softirq( XXX_SOFT_IRQ, xxx_analyze);
printk( KERN_INFO "Successfully set softirq handler on IRQ %d\n", irq );
return 0;
}
static void __exit my_exit( void ) {
synchronize_irq( irq );
free_irq( irq, &my_dev_id );
printk( KERN_INFO "Successfully unloading, irq_counter = %d\n", irq_counter );
}
module_init( my_init );
module_exit( my_exit );
MODULE_LICENSE( "GPL v2" );
当我尝试编译此模块时,出现链接器错误,未定义函数 open_softirq()
和 raise_softirq()
:
kivi@kivi-pc:~/sp_labs/irq_exc/softirq$ make
make -C /lib/modules/4.7.5-custom/build M=/home/kivi/sp_labs/irq_exc/softirq modules
make[1]: Entering directory '/home/kivi/Downloads/linux-4.7.5'
Building modules, stage 2.
MODPOST 1 modules
WARNING: "open_softirq" [/home/kivi/sp_labs/irq_exc/softirq/softirq.ko] undefined!
WARNING: "raise_softirq" [/home/kivi/sp_labs/irq_exc/softirq/softirq.ko] undefined!
make[1]: Leaving directory '/home/kivi/Downloads/linux-4.7.5'
有趣的是函数 request_irq()
等。 interrupt.h
文件中也有定义,但它们不会造成任何问题。
这是我的生成文件:
obj-m += softirq.o
all:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
所以任何人都可以帮我解决我的问题。
附言我用谷歌搜索了我的问题,发现了一些建议,我应该在编译时添加 KBUILD_EXTRA_SYMBOLS=*module path*/Module.symvers
,但它没有帮助。
最佳答案
问题是 open_softirq
和 raise_softirq
函数未导出,因此您无法链接到它们。导出的函数标有 EXPORT_SYMBOL
或 EXPORT_SYMBOL_GPL
宏。
另一方面,你会看到request_irq
是如何导出的(实际上是inlined到request_threaded_irq
,is导出)。
您可以找到大量关于 EXPORT_SYMBOL
宏的信息。例如,here's来自 Robert Love 的解释。
现在,您可能想知道为什么不导出这些函数。好吧,softirqs 是一种低级机制,旨在供其他更高级别的设施使用,因此目的是防止它在非核心内核代码中使用。
模块应该使用更高级别的工具(例如计时器)。
检查内核有多少软中断用户是很有趣的。
$ git grep open_softirq
block/blk-softirq.c: open_softirq(BLOCK_SOFTIRQ, blk_done_softirq);
include/linux/interrupt.h:extern void open_softirq(int nr, void (*action)(struct softirq_action *));
kernel/rcu/tiny.c: open_softirq(RCU_SOFTIRQ, rcu_process_callbacks);
kernel/rcu/tree.c: open_softirq(RCU_SOFTIRQ, rcu_process_callbacks);
kernel/sched/fair.c: open_softirq(SCHED_SOFTIRQ, run_rebalance_domains);
kernel/softirq.c:void open_softirq(int nr, void (*action)(struct softirq_action *))
kernel/softirq.c: open_softirq(TASKLET_SOFTIRQ, tasklet_action);
kernel/softirq.c: open_softirq(HI_SOFTIRQ, tasklet_hi_action);
kernel/time/timer.c: open_softirq(TIMER_SOFTIRQ, run_timer_softirq);
lib/irq_poll.c: open_softirq(IRQ_POLL_SOFTIRQ, irq_poll_softirq);
net/core/dev.c: open_softirq(NET_TX_SOFTIRQ, net_tx_action);
net/core/dev.c: open_softirq(NET_RX_SOFTIRQ, net_rx_action);
只有 12 岁!
这种模式在整个内核中重复出现:维护者认为低级别的内容不会导出,并且仅用于核心内核代码。
关于c - 编译linux内核模块时未定义的函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39691131/