All the drivers that I had dealt with until today where written in just one source file. But today I had several problems trying to compile a driver for a 2.6 kernel that had several source files. Most of the info I found like in the LKMPG and in LDD3, did not work for me. The problem was with my Makefile that I was writing in this way (the tabs after the all and clean targets were removed due to formatting issues):
PWD = $(shell pwd) obj-m += modmain.o modmain-objs += file1.o all: make -C /lib/modules/$(shell uname -r)/build SUBDIRS=$(PWD) modules clean: make -C /lib/modules/$(shell uname -r)/build SUBDIRS=$(PWD) clean
The files in my dir were:
$ ls file1.c file1.h Makefile modmain.c
If you follow the LKMPG or other sources you see that this seems correct: I wanted to compile a couple of files, modmain.c that contains the module init/exit funcs, and file.c that contains funcs used in modmain.c, and generate a driver module modmain.ko..
After compiling and linking without problems, I insmod the module but I didn’t see any of the printk() I wrote, in fact, the driver can be inserted and removed, but it does nothing.
After a while, I use nm to check which symbols were inside the driver and to my surprise the only symbols inside the .ko were
00000000 r __func__.1640 00000020 r __mod_vermagic5 00000000 r __module_depends 00000000 D __this_module 00000000 T init_stuff U printk
No signs of init_module and friends. At this point I realized that the file modmain.c was not being compiled. In fact, my output from the Makefile was the following:
$ make make -C /lib/modules/188.8.131.52-42.fc8/build SUBDIRS=/home/piter/code/c modules make: Entering directory '/usr/src/kernels/184.108.40.206-42.fc8-i686' CC [M] /home/piter/code/c/file1.o LD [M] /home/piter/code/c/modmain.o Building modules, stage 2. MODPOST 1 modules CC /home/piter/code/c/modmain.mod.o LD [M] /home/piter/code/c/modmain.ko make: Leaving directory '/usr/src/kernels/220.127.116.11-42.fc8-i686'
modmain.c was not being compiled!
After playing around with the Makefile I got the right file (again, the tabs after the all and clean targets were removed due to formatting issues):
PWD = $(shell pwd) obj-m += mymod.o mymod-objs += file1.o modmain.o all: make -C /lib/modules/$(shell uname -r)/build SUBDIRS=$(PWD) modules clean: make -C /lib/modules/$(shell uname -r)/build SUBDIRS=$(PWD) clean
Now, the output when compiling and linking is the following:
$ make make -C /lib/modules/18.104.22.168-42.fc8/build SUBDIRS=/home/piter/code/c modules make: Entering directory '/usr/src/kernels/22.214.171.124-42.fc8-i686' CC [M] /home/piter/code/c/file1.o CC [M] /home/piter/code/c/modmain.o LD [M] /home/piter/code/c/mymod.o Building modules, stage 2. MODPOST 1 modules CC /home/piter/code/c/mymod.mod.o LD [M] /home/piter/code/c/mymod.ko make: Leaving directory '/usr/src/kernels/126.96.36.199-42.fc8-i686'
modmain.c is being compiled this time!
And nm says the following:
00000000 r __func__.1640 00000017 r __func__.8988 0000000b r __func__.8993 00000024 r __mod_author6 0000000c r __mod_description7 00000000 r __mod_license8 00000080 r __mod_vermagic5 00000060 r __module_depends 00000000 D __this_module 00000000 T cleanup_module 00000000 T init_module 00000000 T init_stuff 00000000 t my_mod_exit 00000000 t my_mod_init U printk
The symbols used in modmain.c appear normally.
I changed the final driver name to mymod.ko and the file modmain.c is now part of the mymod-objs variable, in this way I’m sure that it’s compiled. Notice that the final driver name is different from any of the source files, including the file that contains the module_init/exit funcs.
Since I had the above mentioned issues for compiling a driver that has multiple source files following commonly linux kernel drivers docs and I have seen other people in the same situation, I decided to share the procedure that worked for me, but this does not mean in any way that the references I used were mistaken, most probably I missed something.
Thank you very much for this post! It solved the same issue I had!
Was searching for more than 2 hours (in stackoverflow, etc.) before finding your post 🙂
Thank you! I had same problem!
Solved my problem — thank you for taking the time to post this.
Hi, thanks. It’s good to know that it was useful.
I am facing the same problem. I have tested the solution but it does not work for me. I am using kernel version 5.2, and GNU make version 4.1?
I haven’t tried with the 5.x kernels, but this procedure should work since it’s standard since the 2.6.x versions.
Have you checked that the file names are right? The .ko file should have a different name than the source files.