Thursday, January 23, 2014

Building Linux Kernel Modules Faster: Internal and external


*For Newbie Linux Kernel and Device Driver developers*.

Most repetitive activity for Kernel and Device Driver developers. is building modules they work on and installing them. So lets discuss few tricks to build them faster way.

Traditionally, when we change a source code of a module, we need to 


a) Build the entire kernel again
make; make module;make modules_install;make install
(optionally using "-jN" option to make)
b) reboot and use the new modules.

But we can avoid reboot by 

a) Build the entire kernel again
b) Remove the old module 
c) Insert the new module.

Building the kernel itself is a time consuming process, especially when we just want to update code specific to our module. So for that we make use linux kernel's support and procedures for building external modules  i.e., modules which are not present in the kernel tree for modules in the kernel tree. Sounds Confusing?

Lets say we have written a new module and wanted to compile it, then we write a makefile which invokes the kernel makefile with below option:

make modules M=<Dir_of_new_Module>

But to compile a internal module (module which is present in the kernel tree) we use the same trick, except the makefile is already present. Just follow the below procedure

Procedure: 

  1. make silentoldconfig  (Optional)
    • whenever Kconfig is changed., For other cases like make and make modules (without M=) this is run by kernel makefile itself.
  2. make modules M=<path_to_dir>
  3. make modules_install M=<path_to_dir>
  4. Remove the old module and Re-Insert the new one.

Still interested of know-how, see the steps in detail:

Details:


1) Whenever we change Kconfig, .config will be updated and we need to tell the kernel makefile to use the new .config instead of using old one.This does that.

2) This uses the makefile in the module sub directory and compiles the files w.r.t #1 .config options.

3) This will install the compiled modules in to the install path /lib/modules//`uname -r`/kernel/ (or) /lib/module/`uname -r`/extra/ depending on whether the module is internal/external. In our case its always extra as we are using "M=" option for building modules. We can add some prefix (extra folder name under the above paths).

Also it used the depmod utility (through a wrapper shell script: scripts/depmod.sh) to generate the below files which will later be used by modprobe.


  • /lib/modules/`uname -r`/modules.alias
  • /lib/modules/`uname -r`/modules.alias.bin
  • /lib/modules/`uname -r`/modules.builtin
  • /lib/modules/`uname -r`/modules.builtin.bin
  • /lib/modules/`uname -r`/modules.ccwmap
  • /lib/modules/`uname -r`/modules.dep
  • /lib/modules/`uname -r`/modules.dep.bin
  • /lib/modules/`uname -r`/modules.devname
  • /lib/modules/`uname -r`/modules.ieee1394map
  • /lib/modules/`uname -r`/modules.inputmap
  • /lib/modules/`uname -r`/modules.isapnpmap
  • /lib/modules/`uname -r`/modules.ofmap
  • /lib/modules/`uname -r`/modules.order
  • /lib/modules/`uname -r`/modules.pcimap
  • /lib/modules/`uname -r`/modules.seriomap
  • /lib/modules/`uname -r`/modules.softdep
  • /lib/modules/`uname -r`/modules.symbols
  • /lib/modules/`uname -r`/modules.symbols.bin
  • /lib/modules/`uname -r`/modules.usbmap

Lets discuss the important ones below: 
  • /lib/modules/`uname -r`/modules.dep
    • Depmod is a utility which will use the "System.map" and try to work out the dependencies between the modules and create a file called "modules.dep", used by modprobe to insert (insmod) the modules in proper order.
    • /lib/modules/`uname -r`/modules.order and /lib/modules/`uname -r`/modules.symbols will be used in that process.
  • /lib/modules/`uname -r`/modules.alias
    • It identifies the HW devices each device driver supports and writes to a file "module.alias" using which the linux kernel device model can insert the driver along with its dependencies (using modprobe and modules.dep) when it  enumerates a new HW device using PCI/USB ..
  • /lib/modules/`uname -r`/modules.builtin
    • This gives a list of modules which are staically linked to the kernel forming part of vmlinuz.
  • /lib/modules/`uname -r`/modules.<BUS>map
    • These files will the known drivers for devices and give informtion regarding the device like vendorid, subsystemid, deviceclass etc.
    • This is used to create module.alias
4) Now that we have all the necessary files, use below commands "-v" is for verbose and "-r" is for using rmmod. By default it used insmod.
  •     modprobe -v -r 
  •     modprobe -v 
Installing depmod and modprobe: Install the "https://www.kernel.org/pub/linux/utils/kernel/module-init-tools/" package with your distro specific instructions.


Common Caveats:


1) If you are not seeing the changes in the new module: 

Probably you are re-inserting the old modules add "-v" to the modprobe and check the timestamps in the path from where modprobe is insmod-ing the module and your module in the kernel tree.  
Running "make modules_install" again should do, if all else fails then try copying manually.

2) If you are seeing a warning about module version check, while inserting the module: 

Probably you are using the above procedure for two dependent modules, like changing a function in cfg80211 and using that one in mac80211. 
Its better to use a directory which hold the directory of both of these, in the above case use "make modules  modules_install M=net/". For more details read Module Versioning Section in R#3.


References:

1) Linux kernel Makefile :-) 
2) Building External Modules
3) Kernel Docs: Building Linux kernel

No comments:

Post a Comment