1
votes

I'm trying to link a kernel module to a non-LKM source file. The problem is, I'm running into some issues. The names of the two files are chardev.c (the LKM) and foo.c.

My Makefile:

obj-m += chardev.o
obj-y += foo.o

all:
    make -C /lib/modules/$(shell uname -r)/build/ M=$(PWD) modules
    $(CC) test.c -o test
clean:
    make -C /lib/modules/$(shell uname -r)/build/ M=$(PWD) clean
    rm test 

Inside of chardev.c I've the following line of code: extern int foo;, and inside foo I've the following line of code: int foo = 123;. (Both lines are at file-scope.)

When running make I'm getting the following output:

make -C /lib/modules/4.4.0-31-generic/build/ M=/home/kylemart/Desktop/Device-Driver modules
make[1]: Entering directory `/usr/src/linux-headers-4.4.0-31-generic'
  CC [M]  /home/kylemart/Desktop/Device-Driver/chardev.o
  Building modules, stage 2.
  MODPOST 1 modules
WARNING: "foo" [/home/kylemart/Desktop/Device-Driver/chardev.ko] undefined!
  CC      /home/kylemart/Desktop/Device-Driver/chardev.mod.o
  LD [M]  /home/kylemart/Desktop/Device-Driver/chardev.ko
make[1]: Leaving directory `/usr/src/linux-headers-4.4.0-31-generic'
cc test.c -o test

Seems things aren't linking properly. What am I doing wrong?

EDIT:

This seems to work, but there's a problem:

obj-m += chardev.o
chardev-objs += foo.o

all:
    make -C /lib/modules/$(shell uname -r)/build/ M=$(PWD) modules
    $(CC) test.c -o test
clean:
    make -C /lib/modules/$(shell uname -r)/build/ M=$(PWD) clean
    rm test  

Although it compiles without warnings, after installing the compiled module (i.e. sudo insmod chardev.ko) there isn't a new device present in /dev. Previously, without trying to link source files, installing kernel modules as previously stated created a device file. That said, the device is present when running lsmod.

1
you are probably missing EXPORT_SYMBOL(foo) - ensc
@ensc Tried that and it didn't seem to make a difference while using either of the above Makefile implementations. - kylemart

1 Answers

2
votes

Your all target builds only the module, but not the kernel so that the foo symbol does not exist there.

When compiling a source (here: foo.c) into the kernel, you have to integrate the makefile into the kernel source. E.g. you have to add

obj-y += my-driver/

to the makefile in the previous directory and build the whole kernel. You should probably remove your all: and clean: targets from the makefile to avoid conflicts with kernel builtin rules.

foo.c must contain

EXPORT_SYMBOL(foo);

or

EXPORT_SYMBOL_GPL(foo);

The second makefile...

will generate only the chardev.ko module which is built from only foo.c; chardev.c will not be used for it. When you really want this, you have to change file names; e.g.

obj-m += chardev.o
chardev-objs = chardev-core.o foo.o