2

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.

2
  • you are probably missing EXPORT_SYMBOL(foo) Commented Apr 6, 2018 at 20:59
  • @ensc Tried that and it didn't seem to make a difference while using either of the above Makefile implementations. Commented Apr 6, 2018 at 21:08

1 Answer 1

3

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
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks! So when creating a module from multiple source files, none of the file names should match module name

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.