Hi all,
I've been working with a userland program writeread.c
(referred here), utilizing the ftdi_sio
Linux driver.
I had worked with the default ftdi_sio
that comes with Ubuntu Lucid that I use - and then, as a sanity check, decided to rebuild ftdi_sio
from source. I did not want to download the entire kernel source, so I opted for so called "building out-of-tree modules":
- Howto: Build Linux Kernel Module Against Installed Kernel w/o Full Kernel Source Tree
- Debian Linux Kernel Handbook - Common kernel-related tasks: Building out-of-tree kernel modules
- Building a custom kernel - FedoraProject: Building Only Kernel Modules (Out Of Tree Modules)
... which means you can only have installed linux-headers-*
packages (instead of having entire linux-source-*
installed) - and the respective kernel module source - in order to build a kernel module.
So, I basically got the following files in a folder:
- ftdi_sio.c
- ftdi_sio.h
- ftdi_sio_ids.h
- Makefile (included below)
and ran make
- and a ftdi_sio.ko
kernel objects compiles, which also can be insmod
-ed without a problem.
The problem is now here - as long as I work with low speeds (115200 bps), there is no observable difference between: loading the 'vanilla' driver (using sudo modprobe ftdi_sio
); and loading the newly built driver (using sudo modprobe usbserial; sudo insmod /path/to/ftdi_sio.ko
) - in respect to the performance of the userland program (writeread.c
).
However, if I try the same at 2000000 bps, then the 'vanilla' driver works fine - while the build driver causes a segfault of the userland program (writeread.c
). In particular, this segfault happened at free()
-ing memory resources - because the driver would end up reading more bytes from the loopback connection, than it itself would write! However, that in itself is not that relevant for this discussion, because I finally found a way to get the built ftdi_sio
to work (Edit: just noticed that a similar procedure is also given in External Linux kernel module dependencies R#2238581 - Stack Overflow):
$ sudo modprobe -r ftdi_sio # remove 'vanilla' driver from memory
...
# build the driver
$ cd /path/to/ftdi_sio_2.6.32/
$ make clean && make
# check vanilla version
$ ls -la /lib/modules/2.6.32-25-generic/kernel/drivers/usb/serial/ftdi_sio.ko
-rw-r--r-- 1 root root 102396 2010-10-17 01:47 /lib/modules/2.6.32-25-generic/kernel/drivers/usb/serial/ftdi_sio.ko
# (re)move the 'vanilla' kernel object
$ sudo mv /lib/modules/2.6.32-25-generic/kernel/drivers/usb/serial/ftdi_sio.ko ~/Desktop/ftdi_sio_orig.ko
# symlink our built version, as if it is the 'vanilla' one
$ sudo ln -s /path/to/ftdi_sio_2.6.32/ftdi_sio.ko /lib/modules/2.6.32-25-generic/kernel/drivers/usb/serial/
# check
$ ls -la /lib/modules/2.6.32-25-generic/kernel/drivers/usb/serial/ftdi_sio.ko
lrwxrwxrwx 1 root root 57 2010-10-26 12:49 /lib/modules/2.6.32-25-generic/kernel/drivers/usb/serial/ftdi_sio.ko -> /path/to/ftdi_sio_2.6.32/ftdi_sio.ko
# call depmod
$ sudo depmod
# !! plug in USB at this point, built driver autoloads;
# however, running `writeread.c` will segfault!
# !! REBOOT at this point
# after reboot:
# !! plug in USB at this point, built driver autoloads;
# and `writeread.c` runs without segfault
So, my question is: can anyone clarify to me, why - even after running depmod
- do I still have to reboot, to have the built driver behave properly? In other words: is there any other command I could call (maybe after depmod
), so that the driver works properly when it's loaded, without rebooting?
The reason I'm asking, is that I suspect that upon each recompilation of the kernel module, the symbol table will change - so to ensure that it works properly, I'd have to run depmod
and reboot after each time the driver is built - which I think would be kind of tedious :) So, it would be nice to be able to rebuild the kernel module, and use it in the same session - without having to reboot.
Well, thanks in advance for any answers,
Cheers!!
Makefile:
CONFIG_MODULE_FORCE_UNLOAD=y
# flags passed to gcc for compilation - -v:verbose, -H:show include files
# KBUILD_CFLAGS += -v
# for debugging make itself, use --debug=i in make command for targets
# debug build:
EXTRA_CFLAGS=-g -O0
KVERSION = $(shell uname -r)
obj-m += ftdi_sio.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