简体   繁体   中英

Undefined functions while compiling linux kernel module

I am trying to work with linux softirq. A have a simple program that uses linux system calls defined in linux/interrupt.h :

//
// 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" );

When I try to compile this module I get linker errors that functions open_softirq() and raise_softirq() are not defined:

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'

The interesting thing is that functions request_irq() etc are also defined in interrupt.h file, but they don't cause any problem.

Here is my Makefile:

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

So can anyone help me please with my problem.

PS i googled my problem and found some advice that I should add KBUILD_EXTRA_SYMBOLS=*module path*/Module.symvers when compiling, but it didn't help.

The problem is that the open_softirq and raise_softirq functions are not exported , and so you cannot link to them. Exported functions are marked with the EXPORT_SYMBOL or EXPORT_SYMBOL_GPL macros.

On the other side, you will see how request_irq is exported (actually, it is inlined to request_threaded_irq , which is exported).

You can find plenty of information about the EXPORT_SYMBOL macros. For instance, here's an explanation from Robert Love.

Now, you are probably wondering why those functions aren't exported. Well, softirqs are a low-level mechanism, meant to be used by other higher-level facilities, so the intention is to prevent its usage in non-core kernel code.

Modules should use higher-level facilities instead (timers for instance).

It is interesting to check how many softirqs users the kernel has.

$ 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);

Just 12!

This pattern repeats across the kernel: stuff that maintainers consider lowish-level is not exported and meant for core kernel code only.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM