Device Drivers, Part 2: Writing Your First Linux Driver in the Classroom

138
53865
Sketching a driver

Sketching a driver

This article, which is part of the series on Linux device drivers, deals with the concept of dynamically loading drivers, first writing a Linux driver, before building and then loading it.

Shweta and Pugs reached their classroom late, to find their professor already in the middle of a lecture. Shweta sheepishly asked for his permission to enter. An annoyed Professor Gopi responded, “Come on! You guys are late again; what is your excuse, today?”

Pugs hurriedly replied that they had been discussing the very topic for that day’s class — device drivers in Linux. Pugs was more than happy when the professor said, “Good! Then explain about dynamic loading in Linux. If you get it right, the two of you are excused!” Pugs knew that one way to make his professor happy was to criticise Windows.

He explained, “As we know, a typical driver installation on Windows needs a reboot for it to get activated. That is really not acceptable; suppose we need to do it on a server? That’s where Linux wins. In Linux, we can load or unload a driver on the fly, and it is active for use instantly after loading. Also, it is instantly disabled when unloaded. This is called dynamic loading and unloading of drivers in Linux.”

This impressed the professor. “Okay! Take your seats, but make sure you are not late again.” The professor continued to the class, “Now you already know what is meant by dynamic loading and unloading of drivers, so I’ll show you how to do it, before we move on to write our first Linux driver.”

Dynamically loading drivers

These dynamically loadable drivers are more commonly called modules and built into individual files with a .ko (kernel object) extension. Every Linux system has a standard place under the root of the file system (/) for all the pre-built modules. They are organised similar to the kernel source tree structure, under /lib/modules/<kernel_version>/kernel, where <kernel_version> would be the output of the command uname -ron the system, as shown in Figure 1.

Linux pre-built modules
Figure 1: Linux pre-built modules

To dynamically load or unload a driver, use these commands, which reside in the /sbin directory, and must be executed with root privileges:

  • lsmod — lists currently loaded modules
  • insmod <module_file> — inserts/loads the specified module file
  • modprobe <module> — inserts/loads the module, along with any dependencies
  • rmmod <module> — removes/unloads the module

Let’s look at the FAT filesystem-related drivers as an example. Figure 2 demonstrates this complete process of experimentation. The module files would be fat.ko, vfat.ko, etc., in the fat (vfat for older kernels) directory under /lib/modules/`uname -r`/kernel/fs. If they are in compressed .gz format, you need to uncompress them with gunzip, before you can insmodthem.

Linux module operations
Figure 2: Linux module operations

The vfat module depends on the fat module, so fat.ko needs to be loaded first. To automatically perform decompression and dependency loading, use modprobe instead. Note that you shouldn’t specify the .ko extension to the module’s name, when using the modprobe command. rmmod is used to unload the modules.

Our first Linux driver

Before we write our first driver, let’s go over some concepts. A driver never runs by itself. It is similar to a library that is loaded for its functions to be invoked by a running application. It is written in C, but lacks a main() function. Moreover, it will be loaded/linked with the kernel, so it needs to be compiled in a similar way to the kernel, and the header files you can use are only those from the kernel sources, not from the standard /usr/include.

One interesting fact about the kernel is that it is an object-oriented implementation in C, as we will observe even with our first driver. Any Linux driver has a constructor and a destructor. The module’s constructor is called when the module is successfully loaded into the kernel, and the destructor when rmmod succeeds in unloading the module. These two are like normal functions in the driver, except that they are specified as the init and exit functions, respectively, by the macros module_init() and module_exit(), which are defined in the kernel header module.h.

/* ofd.c – Our First Driver code */
#include <linux/module.h>
#include <linux/version.h>
#include <linux/kernel.h>

static int __init ofd_init(void) /* Constructor */
{
    printk(KERN_INFO "Namaskar: ofd registered");
    return 0;
}

static void __exit ofd_exit(void) /* Destructor */
{
    printk(KERN_INFO "Alvida: ofd unregistered");
}

module_init(ofd_init);
module_exit(ofd_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Anil Kumar Pugalia <email_at_sarika-pugs_dot_com>");
MODULE_DESCRIPTION("Our First Driver");

Given above is the complete code for our first driver; let’s call it ofd.c. Note that there is no stdio.h (a user-space header); instead, we use the analogous kernel.h (a kernel space header). printk() is the equivalent of printf(). Additionally, version.h is included for the module version to be compatible with the kernel into which it is going to be loaded. The MODULE_* macros populate module-related information, which acts like the module’s “signature”.

Building our first Linux driver

Once we have the C code, it is time to compile it and create the module file ofd.ko. We use the kernel build system to do this. The following Makefile invokes the kernel’s build system from the kernel source, and the kernel’s Makefile will, in turn, invoke our first driver’s Makefile to build our first driver.

To build a Linux driver, you need to have the kernel source (or, at least, the kernel headers) installed on your system. The kernel source is assumed to be installed at /usr/src/linux. If it’s at any other location on your system, specify the location in the KERNEL_SOURCE variable in this Makefile.

# Makefile – makefile of our first driver

# if KERNELRELEASE is defined, we've been invoked from the
# kernel build system and can use its language.
ifneq (${KERNELRELEASE},)
    obj-m := ofd.o
# Otherwise we were called directly from the command line.
# Invoke the kernel build system.
else
    KERNEL_SOURCE := /usr/src/linux
    PWD := $(shell pwd)
default:
    ${MAKE} -C ${KERNEL_SOURCE} SUBDIRS=${PWD} modules

clean:
    ${MAKE} -C ${KERNEL_SOURCE} SUBDIRS=${PWD} clean
endif

With the C code (ofd.c) and Makefile ready, all we need to do is invoke make to build our first driver (ofd.ko).

$ make
make -C /usr/src/linux SUBDIRS=... modules
make[1]: Entering directory `/usr/src/linux'
  CC [M]  .../ofd.o
  Building modules, stage 2.
  MODPOST 1 modules
  CC      .../ofd.mod.o
  LD [M]  .../ofd.ko
make[1]: Leaving directory `/usr/src/linux'

Summing up

Once we have the ofd.ko file, perform the usual steps as the root user, or with sudo.

# su
# insmod ofd.ko
# lsmod | head -10

lsmod should show you the ofd driver loaded.

While the students were trying their first module, the bell rang, marking the end of the session. Professor Gopi concluded, “Currently, you may not be able to observe anything other than the lsmod listing showing the driver has loaded. Where’s the printk output gone? Find that out for yourselves, in the lab session, and update me with your findings. Also note that our first driver is a template for any driver you would write in Linux. Writing a specialised driver is just a matter of what gets filled into its constructor and destructor. So, our further learning will be to enhance this driver to achieve specific driver functionalities.”

138 COMMENTS

  1. when I run make command, i got the following error

    make: Nothing to be done for `default’.

    I guess it could be the problem because of KERNEL_SOURCE. In my make file i have set KERNEL_SOURCE as follows:

    KERNEL_SOURCE := /usr/src/linux-headers-2.6.38-10

    • I had the same problem.
      For me the problem was copy and pasting the Makefile.
      Make sure that in front of the ${MAKE}… commands is an tab and not multiple spaces.
      After replacing spaces with tabs it worked for me. 

    • Just noticed:
      I don’t know if you use *buntu. But KERNEL_SOURCE := /usr/src/linux-headers-2.6.38-10 produces some errors.

      KERNEL_SOURCE := /usr/src/linux-headers-2.6.38-10-generic seems to work.

      • # Use this file as your “Makefile”

        obj-m +=ofd.o

        ofd-objs := ofd.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

  2. I also had the same problem.

    So i manually complied it.

    make was like

    obj-m := ofd.o

    and compilation was :

    make -C /usr/src/linux-headers-2.6.38-10 SUBDIRS=$PWD modules.

  3. hi pugs, all is well. But I need to know a little more about the Makefile syntax and how it works line by line… I can’t digest some code which is alien to me. I would be grateful if you can throw some light on this….

  4. when ubuntu is installed on desktop

    what does /usr/src/ dir contains ? i.e kerner source OR kernel headers?

    in my pc linux-headers-2.6.38-10-generic and linux-headers-2.6.38-10 directories are there. what are they.? they dont have any c source . if they are headers why there are two directories i.e what is generic means?

    • I understand you mean the kernel source location. Typically, it would be under /usr/src (linux or build or …). Also, it may not be installed by default. So, you may have to install it first.

  5. root@ubuntu:/usr/src# make -C /usr/src/linux-headers-3.2.0-29 SUBDIRS=$PWD modules.
    I run above command & found this error pls help as soon as possible .. pls

    make: Entering directory `/usr/src/linux-headers-3.2.0-29′

    ERROR: Kernel configuration is invalid.
    include/generated/autoconf.h or include/config/auto.conf are missing.
    Run ‘make oldconfig && make prepare’ on kernel src to fix it.

  6. i was trying to build my driver …i got this error … :-

    root@ubuntu:/home/ayush/device# make -C /usr/src/linux-headers-3.2.0-29-generic-pae SUBDIRS=$PWD modules

    make: Entering directory `/usr/src/linux-headers-3.2.0-29-generic-pae’

    Building modules, stage 2.

    MODPOST 0 modules

    make: Leaving directory `/usr/src/linux-headers-3.2.0-29-generic-pae’

    Pls reply any solution … thnx in advance :)

    • I believe you current directory /home/ayush/device contains the C files which you are trying to build. And your current kernel configuration is set to build & use drivers, i.e. “grep CONFIG_MODULE /usr/src/linux-headers-3.2.0-29-generic-pae/.config” should not be not set or empty.

      • I am also facing same problem as mentioned.. it’s showing

        CONFIG_MODULES=y
        # CONFIG_MODULE_FORCE_LOAD is not set
        CONFIG_MODULE_UNLOAD=y
        # CONFIG_MODULE_FORCE_UNLOAD is not set
        CONFIG_MODULE_SRCVERSION_ALL=y

        • Use a makefile as suggested in the article. Basically you need the obj-m … line for a module to be built, i.e. obj-m := ofd.o. So, just giving make on command line may not work.

  7. why every function in the device driver is named as static. As static fuction are not visible outside of the file scope. Then, How these driver function gets called by user space application..

    • You are correct that when static, functions are not visible outside of the file scope, but only by their names. Note that, they could be still accessed anywhere by their addresses, and that’s what we do with all these driver functions – populate their addresses into the struct file_operations and make it available to VFS & hence userspace, through the struct cdev.

  8. when i do make this error comes

    please tell solution

    sai@ubuntu:~/tushar$ make

    make -C /usr/src/linux-headers-3.5.0-17 SUBDIRS=/home/sai/tushar modules

    make[1]: Entering directory `/usr/src/linux-headers-3.5.0-17′

    ERROR: Kernel configuration is invalid.

    include/generated/autoconf.h or include/config/auto.conf are missing.

    Run ‘make oldconfig && make prepare’ on kernel src to fix it.

    WARNING: Symbol version dump /usr/src/linux-headers-3.5.0-17/Module.symvers

    is missing;

    modules will have no dependencies and modversions.

    Building modules, stage 2.

    /usr/src/linux-headers-3.5.0-17/scripts/Makefile.modpost:42:

    include/config/auto.conf: No such file or directory

    make[2]: *** No rule to make target `include/config/auto.conf’. Stop.

    make[1]: *** [modules]

    Error 2

    make[1]: Leaving directory `/usr/src/linux-headers-3.5.0-17′

    make: *** [default] Error 2

        • 1> when i do make oldconfig in linux-headers-3.5..0-17 folder i got this error

          HOSTCC scripts/basic/fixdep

          scripts/basic/fixdep.c:433:1: fatal error: opening dependency file scripts/basic/.fixdep.d: Permission denied

          compilation terminated.

          make[1]: *** [scripts/basic/fixdep] Error 1

          make: *** [scripts_basic] Error 2

          tushar@Sai:/usr/src/linux-headers-3.5.0-17$

          2> and after that if i do make modules_prepare i got this error

          HOSTCC scripts/basic/fixdep

          scripts/basic/fixdep.c:433:1: fatal error: opening dependency file scripts/basic/.fixdep.d: Permission denied

          compilation terminated.

          make[2]: *** [scripts/basic/fixdep] Error 1

          make[1]: *** [scripts_basic] Error 2

          make: *** No rule to make target `modules_prepare’. Stop.

          tushar@Sai:/usr/src/linux-headers-3.5.0-17$

          i am using ubuntu 12.10
          kernel version 3.5.0-17-generic

          PLZ PROVIDE SOLUTION SIR

          • 1)when i do sudo make oldconfig then it is fine

            2) but when i do sudo make modules_prepare i got fooliowing error

            tushar@Sai:/usr/src/linux-headers-3.5.0-17$ sudo make modules_prepare

            scripts/kconfig/conf –silentoldconfig Kconfig

            make[1]: *** No rule to make target `/usr/src/linux-headers-3.5.0-17/arch/x86/syscalls/syscall_32.tbl’, needed by `arch/x86/syscalls/../include/generated/asm/unistd_32.h’. Stop.

            make: *** [archheaders] Error 2

            tushar@Sai:/usr/src/linux-headers-3.5.0-17$

            pls tell solution sir

          • hi.. i am facing the same problem Tushar was facing and got exact same error. I desperately want to move forward to next tutorial but can get rid of this compile issue…

            I know u said about headers package. But can you please point out exact issue..

            Here is my system info:

            Linux sunilshahu 3.5.0-17-generic #28-Ubuntu SMP Tue Oct 9 19:32:08 UTC 2012 i686 athlon i686 GNU/Linux

            and after doing what you suggested here is the error log i got:

            root@sunilshahu:/usr/src/linux-headers-3.5.0-17# make oldconfig
            HOSTCC scripts/basic/fixdep
            HOSTCC scripts/kconfig/conf.o
            SHIPPED scripts/kconfig/zconf.tab.c
            SHIPPED scripts/kconfig/zconf.lex.c
            SHIPPED scripts/kconfig/zconf.hash.c
            HOSTCC scripts/kconfig/zconf.tab.o
            HOSTLD scripts/kconfig/conf
            scripts/kconfig/conf –oldconfig Kconfig
            #
            # using defaults found in /boot/config-3.5.0-17-generic
            #
            #
            # configuration written to .config
            #
            root@sunilshahu:/usr/src/linux-headers-3.5.0-17#
            root@sunilshahu:/usr/src/linux-headers-3.5.0-17#
            root@sunilshahu:/usr/src/linux-headers-3.5.0-17# make prepare
            scripts/kconfig/conf –silentoldconfig Kconfig
            make[1]: *** No rule to make target `/usr/src/linux-headers-3.5.0-17/arch/x86/syscalls/syscall_32.tbl’, needed by `arch/x86/syscalls/../include/generated/asm/unistd_32.h’. Stop.
            make: *** [archheaders] Error 2
            root@sunilshahu:/usr/src/linux-headers-3.5.0-17# make prepare
            make[1]: *** No rule to make target `/usr/src/linux-headers-3.5.0-17/arch/x86/syscalls/syscall_32.tbl’, needed by `arch/x86/syscalls/../include/generated/asm/unistd_32.h’. Stop.
            make: *** [archheaders] Error 2

            Thanks…(it will we while(1){thanks;} if anybody will help to sort this out)

            Sunil.

          • Does make modules_prepare also give the same problem? If yes, then as I said earlier, you also have the some issue with the headers package installation. Try reinstalling the linux-headers package using apt-get.

          • ok. I did what Ajey said int the above discussion and changed make file as below

            KERNEL_SOURCE := /lib/modules/3.5.0-17-generic/build

            And it worked.. It compiled the ofd.c and i loaded and unloaded it successfully on my ubuntu 12.10.

            So, does it means my linux sources or headers are at above directory and not at /usr/src/linux-headers-3.5.0-17-generic and /usr/src/linux-source-3.5.0 , because i tried both earlier?

          • Typically /lib/modules/…/build is a link to the corresponding source, these modules are built from – making it work with high probability. Please check the link and post here what does it point to. That would definitely give insight into this common problem.

          • hi, i have to change the system after above comment and missed to see the link on that system.

            now i am using
            Linux sunils 3.2.0-23-generic #36-Ubuntu SMP Tue Apr 10 20:39:51 UTC 2012 x86_64 x86_64 x86_64 GNU/Linux

            my code compiled with this with make file
            obj-m += ofd.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

            and when looking at the lib/modules/…/buld i find as below. but source link (/build/buildd/linux-3.2.0) was red colored(dont know why) and when looking what it points to i found that there is no such directory(but still i got my module compiled)

            total 1088

            drwxr-xr-x 7 root root 4096 Jul 2 13:54 ./

            drwxr-xr-x 5 root root 4096 Jun 26 16:05 ../

            drwxr-xr-x 3 root root 4096 Apr 25 2012 arch/

            lrwxrwxrwx 1 root root 31 May 31 16:57 block -> ../linux-headers-3.2.0-23/block/

            -rw-r–r– 1 root root 140241 Jul 2 13:53 .config

            -rw-r–r– 1 root root 140241 Jul 2 12:25 .config.old

            lrwxrwxrwx 1 root root 32 May 31 16:57 crypto -> ../linux-headers-3.2.0-23/crypto/

            lrwxrwxrwx 1 root root 39 May 31 16:57 Documentation -> ../linux-headers-3.2.0-23/Documentation/

            lrwxrwxrwx 1 root root 33 May 31 16:57 drivers -> ../linux-headers-3.2.0-23/drivers/

            lrwxrwxrwx 1 root root 34 May 31 16:57 firmware -> ../linux-headers-3.2.0-23/firmware/

            lrwxrwxrwx 1 root root 28 May 31 16:57 fs -> ../linux-headers-3.2.0-23/fs/

            drwxr-xr-x 5 root root 4096 Apr 25 2012 include/

            lrwxrwxrwx 1 root root 30 May 31 16:57 init -> ../linux-headers-3.2.0-23/init/

            lrwxrwxrwx 1 root root 29 May 31 16:57 ipc -> ../linux-headers-3.2.0-23/ipc/

            lrwxrwxrwx 1 root root 32 May 31 16:57 Kbuild -> ../linux-headers-3.2.0-23/Kbuild

            lrwxrwxrwx 1 root root 33 May 31 16:57 Kconfig -> ../linux-headers-3.2.0-23/Kconfig

            drwxr-xr-x 2 root root 4096 Jul 2 12:27 kernel/

            lrwxrwxrwx 1 root root 29 May 31 16:57 lib -> ../linux-headers-3.2.0-23/lib/

            lrwxrwxrwx 1 root root 34 May 31 16:57 Makefile -> ../linux-headers-3.2.0-23/Makefile

            -rw-r–r– 1 root root 608 Apr 11 2012 .missing-syscalls.d

            lrwxrwxrwx 1 root root 28 May 31 16:57 mm -> ../linux-headers-3.2.0-23/mm/

            -rw-r–r– 1 root root 0 Jul 2 11:21 modules.order

            -rw-r–r– 1 root root 791023 Apr 11 2012 Module.symvers

            lrwxrwxrwx 1 root root 29 May 31 16:57 net -> ../linux-headers-3.2.0-23/net/

            lrwxrwxrwx 1 root root 33 May 31 16:57 samples -> ../linux-headers-3.2.0-23/samples/

            drwxr-xr-x 7 root root 4096 Apr 25 2012 scripts/

            lrwxrwxrwx 1 root root 34 May 31 16:57 security -> ../linux-headers-3.2.0-23/security/

            lrwxrwxrwx 1 root root 31 May 31 16:57 sound -> ../linux-headers-3.2.0-23/sound/

            lrwxrwxrwx 1 root root 25 May 31 16:57 source -> /build/buildd/linux-3.2.0

            drwxr-xr-x 2 root root 4096 Apr 11 2012 .tmp_versions/

            lrwxrwxrwx 1 root root 31 May 31 16:57 tools -> ../linux-headers-3.2.0-23/tools/

            lrwxrwxrwx 1 root root 32 May 31 16:57 ubuntu -> ../linux-headers-3.2.0-23/ubuntu/

            lrwxrwxrwx 1 root root 29 May 31 16:57 usr -> ../linux-headers-3.2.0-23/usr/

            lrwxrwxrwx 1 root root 30 May 31 16:57 virt -> ../linux-headers-3.2.0-23/virt/

          • Here is the output:

            root@sunils:~# ls -l /lib/modules/`uname -r`/

            total 4276

            lrwxrwxrwx 1 root root 39 May 31 16:56 build -> /usr/src/linux-headers-3.2.0-23-generic

            drwxr-xr-x 2 root root 4096 Apr 25 2012 initrd

            drwxr-xr-x 10 root root 4096 Apr 25 2012 kernel

            -rw-r–r– 1 root root 685840 Apr 25 2012 modules.alias

            -rw-r–r– 1 root root 667167 Apr 25 2012 modules.alias.bin

            -rw-r–r– 1 root root 5724 Apr 11 2012 modules.builtin

            -rw-r–r– 1 root root 7132 Apr 25 2012 modules.builtin.bin

            -rw-r–r– 1 root root 69 Apr 25 2012 modules.ccwmap

            -rw-r–r– 1 root root 314947 Apr 25 2012 modules.dep

            -rw-r–r– 1 root root 463653 Apr 25 2012 modules.dep.bin

            -rw-r–r– 1 root root 186 Apr 25 2012 modules.devname

            -rw-r–r– 1 root root 889 Apr 25 2012 modules.ieee1394map

            -rw-r–r– 1 root root 295 Apr 25 2012 modules.inputmap

            -rw-r–r– 1 root root 4624 Apr 25 2012 modules.isapnpmap

            -rw-r–r– 1 root root 1421 Apr 25 2012 modules.ofmap

            -rw-r–r– 1 root root 128682 Apr 11 2012 modules.order

            -rw-r–r– 1 root root 451186 Apr 25 2012 modules.pcimap

            -rw-r–r– 1 root root 2815 Apr 25 2012 modules.seriomap

            -rw-r–r– 1 root root 131 Apr 25 2012 modules.softdep

            -rw-r–r– 1 root root 260900 Apr 25 2012 modules.symbols

            -rw-r–r– 1 root root 330555 Apr 25 2012 modules.symbols.bin

            -rw-r–r– 1 root root 998947 Apr 25 2012 modules.usbmap

          • I hope that clarifies all the doubts. The link is correctly pointing to the headers, which are working for you. Pasting it here for reference:
            lrwxrwxrwx 1 root root 39 May 31 16:56 build -> /usr/src/linux-headers-3.2.0-23-generic

  9. I use your code and compile successfully.
    But when insmod by “sudo insmod ofd.ko”, error prompt-” insmod: error inserting ‘ofd.ko’: -1 Invalid module format”.
    Can you tell me why?
    Thx.

  10. I use your code and compile by make command then i got following error

    tushar@tushar-SVE14112ENW:~/devdrv$ make
    make -C /usr/src/linux-headers-3.5.0-17 SUBDIRS=/home/tushar/devdrv modules
    make[1]: Entering directory `/usr/src/linux-headers-3.5.0-17′
    WARNING: Symbol version dump /usr/src/linux-headers-3.5.0-17/Module.symvers is missing;
    modules will have no dependencies and modversions.
    Building modules, stage 2.

    MODPOST 0 modules

    /bin/sh: 1: scripts/mod/modpost: not found

    make[2]: *** [__modpost] Error 127

    make[1]: *** [modules] Error 2

    make[1]: Leaving directory `/usr/src/linux-headers-3.5.0-17′

    make: *** [default] Error 2

    • In this particular case, even := is fine as, we are limiting the build to the drivers directory and more to our driver, alone.

  11. I use your code and compile by make command then i got following errors

    make -C /usr/src/linux-headers-3.2.0-29 SUBDIRS=/home/shivaram/jani modules
    make[1]: Entering directory `/usr/src/linux-headers-3.2.0-29′

    ERROR: Kernel configuration is invalid.
    include/generated/autoconf.h or include/config/auto.conf are missing.
    Run ‘make oldconfig && make prepare’ on kernel src to fix it.

    WARNING: Symbol version dump /usr/src/linux-headers-3.2.0-29/Module.symvers
    is missing; modules will have no dependencies and modversions.

    Building modules, stage 2.
    /usr/src/linux-headers-3.2.0-29/scripts/Makefile.modpost:42: include/config/auto.conf: No such file or directory
    make[2]: *** No rule to make target `include/config/auto.conf’. Stop.
    make[1]: *** [modules] Error 2
    make[1]: Leaving directory `/usr/src/linux-headers-3.2.0-29′
    make: *** [default] Error 2s

    And also i tried with make oldconfig&&make prepare then i got problem like

    make: *** No rule to make target `oldconfig’. Stop.

    i installed ubuntu through vmware. one of my friend said it’s the problem u should install normal way..

  12. sir,i have created a makefile and added obj-m := ofd.o in it.

    After saving and exiting the terminal,i have given command like this

    make -C /usr/src/linux-headers-generic-pae-3.2.0-12 SUBDIRS=$PWD modules

    but it is showing “no rule to make”…pls help me.
    regards,
    uday.

    • Make sure that you use *only tabs* to indent your makefile. You get such errors, if you have used spaces instead.

  13. Namaste, When I used Kernel_Source as KERNEL_SOURCE := /usr/src/linux-header-3.5.0-30-generic –> I get an error No such file or directory and when I change Kernel_Source as KERNEL_SOURCE := /lib/modules/3.5.0-30-generic/build (this was recommended in one of comments below), then I get following error. Not able to proceed beyond this ….

    make -C /lib/modules/3.5.0-30-generic/build SUBDIRS=/ modules
    make[1]: Entering directory `/usr/src/linux-headers-3.5.0-30-generic’
    scripts/Makefile.build:128: kbuild: Makefile.build is included improperly
    make[2]: *** No rule to make target `kernel/bounds.c’, needed by `kernel/bounds.s’. Stop.
    make[1]: *** [_module_] Error 2
    make[1]: Leaving directory `/usr/src/linux-headers-3.5.0-30-generic’
    make: *** [default] Error 2

    • Seems like, there is some problem with the installation of the kernel headers with this version of the distro you are using.

    • I too got this error, the problem was that I had created a folder Linux Device Driver and under this HelloWorld, When i remove Space and Change Folder name as LinuxDeviceDriver, everything works fine, Hoping you too had done same thing.
      Hope this help.

      Very Nice Tutorial:-)

  14. After I upgraded to Ubuntu 13.04, the problem got rectified, only thing is, in the sample Makefile, I had to change Kernel_Source := /lib/modules//3.8.0-23-generic/build. Thanks for this article.

  15. hi sir, i can compile on ubuntu version 8, but when i use ubuntu 12.04 lts, i tried every way to compile but still cannot compile:
    user@ubuntu:~/Study$ make
    make: Nothing to be done for `default’.

    Then i add “default: ofd.o” to our Makefile but it raise another error:
    cc -c -o ofd.o ofd.c
    ofd.c:2:26: fatal error: linux/module.h: No such file or directory compilation terminated.

    Later, i must use command (type manually to terminal) like this to compile :
    make -C /lib/modules/3.5.0-37-generic/build SUBDIRS=/home/user/Study modules

    And the result is OK:
    make: Entering directory `/usr/src/linux-headers-3.5.0-37-generic’
    CC [M] /home/nobita/Study/ofd.o
    Building modules, stage 2.
    MODPOST 1 modules
    CC /home/nobita/Study/ofd.mod.o
    LD [M] /home/nobita/Study/ofd.ko
    make: Leaving directory `/usr/src/linux-headers-3.5.0-37-generic’

    Could you help me how to handle this, and why cant i use Makefile??
    Thanks in advance!

    • And there is a slight problem here, when using Ubuntu 8.x (kernel 2.6x) with your Makefile, everything ok. When insmod -> dmesg -> get line “Namaskar: ofcd registered”, when rmmod -> dmesg -> get line “Alvida: ofcd unregistered”. But with ubuntu 12.04 LTS (kernel 3.5x), compile with method state above, when When insmod -> dmesg -> nothing, but when rmmod -> dmesg -> get 2 line “Namaskar… and Alvida…” <= confuse?? line Namaskar must be appear after insmod, right?

      When trying you example in part 5 (still compile like above), everything's gone smoothly apart from when dmesg, all line involve in open, close … appear correctly but still 2 line "Namaskar… and Alvida…" appear only when i rmmod. I dont know why, the code is exactly the same like you.

      Another problem: with example in part 5, when using Ubuntu 8.x (actually i use virtual machine to run this OS), compile ok, but when insmod got error: Segmentation fault, …. address 0x00000…., i tried to debug it (still not familiar with it) and i figured problem involving in device_create, so i cant get mynull. But with Ubuntu 12 (installed in my laptop by wubi) everything work well except the problem about message line i mentioned before.

      • Hardware access through virtual box is not recommended and you have the segfault kind of issues, as mentioned by you.

        Regarding the dmesg output, its a delayed buffer flush issue. Put a “n” at the end of each of the strings, and things should work fine.

    • Change the KERNEL_SOURCE variable in the Makefile to /lib/modules/3.5.0-37-generic/build and you should be able to use your Makefile – it just that the kernel source path is different on your system.

  16. Hi sir,
    I am getting there error plz help me out

    ajay@ubuntu:~/module$ make
    make -C /usr/src/linux-headers-3.5.0-17-generic SUBDIRS-/home/ajay/module module
    make[1]: Entering directory `/usr/src/linux-headers-3.5.0-17-generic’
    HOSTCC scripts/basic/fixdep
    scripts/basic/fixdep.c:433:1: fatal error: opening dependency file scripts/basic/.fixdep.d: Permission denied
    compilation terminated.
    make[3]: *** [scripts/basic/fixdep] Error 1
    make[2]: *** [scripts_basic] Error 2
    make[1]: *** No rule to make target `SUBDIRS-/home/ajay/module’. Stop.
    make[1]: Leaving directory `/usr/src/linux-headers-3.5.0-17-generic’
    make: *** [all] Error 2

  17. Hi sir,
    I am getting there error plz help me out

    ajay@ubuntu:~/module$ make
    make -C /usr/src/linux-headers-3.5.0-17-generic SUBDIRS-/home/ajay/module module
    make[1]: Entering directory `/usr/src/linux-headers-3.5.0-17-generic’
    HOSTCC scripts/basic/fixdep
    scripts/basic/fixdep.c:433:1: fatal error: opening dependency file scripts/basic/.fixdep.d: Permission denied
    compilation terminated.
    make[3]: *** [scripts/basic/fixdep] Error 1
    make[2]: *** [scripts_basic] Error 2
    make[1]: *** No rule to make target `SUBDIRS-/home/ajay/module’. Stop.
    make[1]: Leaving directory `/usr/src/linux-headers-3.5.0-17-generic’
    make: *** [all] Error 2

  18. peter@Ubuntu2:~$
    peter@Ubuntu2:~$ rm ofd.mod.o
    peter@Ubuntu2:~$ rm ofd.ko
    peter@Ubuntu2:~$
    peter@Ubuntu2:~$ make -f makefile
    make: Nothing to be done for `default’.
    peter@Ubuntu2:~$ make -f Makefile
    make -C /usr/src/linux-headers-3.2.0-56-generic SUBDIRS=/home/peter modules
    make[1]: Entering directory `/usr/src/linux-headers-3.2.0-56-generic’
    Building modules, stage 2.
    MODPOST 1 modules
    CC /home/peter/ofd.mod.o
    LD [M] /home/peter/ofd.ko
    make[1]: Leaving directory `/usr/src/linux-headers-3.2.0-56-generic’
    peter@Ubuntu2:~$

    makefile( indented lines have 4 leading spaces – using cut&paste from this article)

    ifneq (${KERNELRELEASE},)
    obj-m := ofd.o
    # Otherwise we were called directly from the command line.
    # Invoke the kernel build system.
    else
    KERNEL_SOURCE := /usr/src/linux-headers-3.2.0-56-generic
    PWD := $(shell pwd)
    default:
    ${MAKE} -C ${KERNEL_SOURCE} SUBDIRS=${PWD} modules

    clean:
    ${MAKE} -C ${KERNEL_SOURCE} SUBDIRS=${PWD} clean
    endif

    Makefile ( indented lines have 1 leading tab after editing)

    ifneq (${KERNELRELEASE},)
    obj-m := ofd.o
    # Otherwise we were called directly from the command line.
    # Invoke the kernel build system.
    else
    KERNEL_SOURCE := /usr/src/linux-headers-3.2.0-56-generic
    PWD := $(shell pwd)
    default:
    ${MAKE} -C ${KERNEL_SOURCE} SUBDIRS=${PWD} modules

    clean:
    ${MAKE} -C ${KERNEL_SOURCE} SUBDIRS=${PWD} clean
    endif

    Sooooooo … if you cut and paste from this tutorial to create your makefile edit it so that the leading white space is one Tab – this is with Ububtu 12.04

    hope this helps

    nice work Anil

    pjm

  19. Hello,

    I am trying to compile USB driver code, but getting following
    warnings:

    root@ubuntu:/opt/linux-cortexm-1.4.1/projects/developer/app/driver#
    make
    make -C /opt/linux-cortexm-1.4.1/linux M=`pwd` modules CFLAGS=””
    LDFLAGS=””
    make[1]: Entering directory `/opt/linux-cortexm-1.4.1/linux’
    CC [M] /opt/linux-cortexm-1.4.1/projects/developer/app/driver/vcom.o
    Building modules, stage 2.
    MODPOST 1 modules
    WARNING: “usb_register_driver”
    [/opt/linux-cortexm-1.4.1/projects/developer/app/driver/vcom.ko]
    undefined!
    WARNING: “usb_register_dev”
    [/opt/linux-cortexm-1.4.1/projects/developer/app/driver/vcom.ko]
    undefined!
    WARNING: “usb_get_dev”
    [/opt/linux-cortexm-1.4.1/projects/developer/app/driver/vcom.ko]
    undefined!
    WARNING: “usb_put_dev”
    [/opt/linux-cortexm-1.4.1/projects/developer/app/driver/vcom.ko]
    undefined!
    WARNING: “usb_deregister_dev”
    [/opt/linux-cortexm-1.4.1/projects/developer/app/driver/vcom.ko]
    undefined!
    WARNING: “usb_find_interface”
    [/opt/linux-cortexm-1.4.1/projects/developer/app/driver/vcom.ko]
    undefined!
    WARNING: “usb_bulk_msg”
    [/opt/linux-cortexm-1.4.1/projects/developer/app/driver/vcom.ko]
    undefined!
    WARNING: “usb_deregister”
    [/opt/linux-cortexm-1.4.1/projects/developer/app/driver/vcom.ko]
    undefined!
    CC /opt/linux-cortexm-1.4.1/projects/developer/app/driver/vcom.mod.o
    LD [M]
    /opt/linux-cortexm-1.4.1/projects/developer/app/driver/vcom.ko
    make[1]: Leaving directory `/opt/linux-cortexm-1.4.1/linux’

    I searched all these functions, these are defind in following files.

    1> usb_register_driver -> Defined /usb/core/driver.c, line 824.
    2> usb_register_dev -> Defined /usb/core/file.c, line 160
    3> usb_get_dev -> Defined /usb/core/usb.c, line 492
    4> usb_put_dev -> Defined /usb/core/usb.c, line 518
    5> usb_deregister_dev -> Defined /usb/core/usb.c, line 240
    6> usb_find_interface -> Defined /usb/core/usb.c, line 198

    It is clear from above these functions are defined somewhere.

    Let us know how to solve it.

    • Why did you set the CFLAGS & LDFLAGS to “” in your Makefile? Please remove both the CFLAGS & LDFLAGS in make invocation, and try out.

  20. Hello,
    I have already created .ko file and i have inserted to target using insmod and led is blinking but
    I want to build driver into the kernel image(not as a module). First,
    I have selected a /misc directory in drivers directory
    .drivers/misc/I
    have copied ledblink.c and lpc178x.h files into this directory and in
    Kconfig present indrivers/misc/ directory, I have wriitten.

    config LEDDRIVER
    bool “led blink”
    default n
    help
    This is a test driver.

    Save the file and open Makefile in the same directory. Goto end of
    the file and add the following entry.

    obj-$(CONFIG_LEDDRIVER) += ledblink.o

    make kmenuconfig and I have selected led blink

    But make command gives following error:
    LD drivers/media/built-in.o
    LD drivers/mfd/built-in.o
    make[3]: *** No rule to make target `drivers/misc/ledblink.o’, needed
    by `drivers/misc/built-in.o’. Stop.
    make[2]: *** [drivers/misc] Error 2
    make[1]: *** [drivers] Error 2
    make[1]: Leaving directory `/opt/linux-cortexm-1.4.1/linux’
    make: *** [_prepare_modules] Error 2
    Please let me know what is missing.

    • What you are doing is correct. Check out your Makefile, if something else is needed. Also, try make modules_prepare, before make.

  21. Hi,
    I have just installed linux on VM.
    When I do “make” it shows the following error:
    make[1]: *** No rule to make target `/usr/src/linux-headers-3.8.0-29-generic/arch/x86/syscalls/syscall_32.tbl’, needed by `arch/x86/syscalls/../include/generated/uapi/asm/unistd_32.h’. Stop.
    make: *** [archheaders] Error 2

      • I think I’ve installed whatever is needed. ‘Cause whenever I try to install the headers, it says “nothing upgraded”. Is that the only cause to this?

        • Okay, where exactly are you doing make. Also, make sure that your Makefile as appropriate tabs, not spaces – Makefiles are very tab sensitive.

  22. what is KERNELRELEASE in the Makefile……?? someone told me that it’s the kernel version, which we are using !!! is it so???……if it’s so, then why we are not using the `uname -r` instead of this….!!!

    • This is the makefile variable defined in the kernel source, which defines the kernel release version for that particular kernel source, which need not have any relation with the running kernel.

  23. @anil sir…..what’s the meaning of API??? like spinlock API, semaphore API, completion API in device drivers????

    • API as such stands for “Application Programming Interface”, but in our context, it means the set of functions provided by kernel for programming the particular functionalities.

      • @anil sir,,I want to interface a RapidIO driver with a T4240 processor. I have setup the host system in Ubuntu 12.04 and initially I want to test the mport(master port) driver so that I can gradually create the rapidio interface.
        Kindly offer some suggestions.

        • Is RapidIO interface more like a network interface? If yes, you may write a network (vertical) driver, or otherwise you may start with writing a character (vertical) driver.

          • Rapidio is a chip to chip or board to board interface. Also the driver was already implemented in 2005 but I want to know if it is compatible with T4240.
            If so what are steps to integrate with Ubuntu 12.04. If no then where I can go for a suitable rapdio driver.
            Kindly provide some suggestions.
            Thanks.

          • Okay. So then for compatibility, just load the driver and check out. Or, it is not part of the distro, download the source and compile for it, and then try out.

  24. Hi there,
    I am linux beginner. I install debian in virtualbox
    I saw several directories /usr/src/

    #KERNEL_SOURCE := /usr/src/linux-headers-3.2.0-4-686-pae
    #KERNEL_SOURCE := /usr/src/linux-headers-3.2.0-4-common
    #KERNEL_SOURCE := /usr/src/virtualbox-guest-4.1.18
    # KERNEL_SOURCE := /usr/src/linux-kbuild-3.2

    I not sure what is kernel source? I try to make all of them. But i got :
    make: Nothing to be done for `default’.
    What’s going on here? Please give me any idea

    Thank you!

        • Okay. So, now you are building the drivers, and not the kernel – that can be done using the headers. And I think, that’s what you have resolved. But then, you need to make sure that you use the headers corresponding to your running kernel version. Check that using uname -r

          • uname –all Linux debian-vir1 3.2.0-4-486 #1 Debian 3.2.60-1+deb7u3 i686 GNU/Linux

            i typed dmesg
            ofd: disagrees about version of symbol module_layout

            modinfo
            vermagic: 3.2.0-4-686-pae SMP mod_unload modversions 686

            In “/lib/module/”. we had 2 directories
            – 3.2.0-4-686-pae
            – 3.2.0-4-486

            I saw that some differences from version. But, i can not find out “build” folder in /lib/modules/3.2.0-4-486

            what’s going on here?I missed something?

          • It may not have the build folder, but still the other stuff at the top level may be there. Just give the top folder itself as the path.

          • Went to root folder and typed
            find -name -build
            this result:
            ./lib/modules/3.2.0-4-686-pae/build

            may be, i missed “build” directory. How can i recover it?
            or maybe, when i install OS to virtual box. It’s difference with real machine?

          • Hi there

            I fixed it.

            1. Download kernel soucre code from debina website
            http://security.debian.org/debian-security/pool/updates/main/l/linux/linux-headers-3.2.0-4-486_3.2.60-1+deb7u3_i386.deb

            2. Extract downloaded file. Then
            – Copy “build” and “source” to /lib/modules/3.2.0-4-486
            – copy “usr/src/linux-headers-3.2.0-4-486” to “/usr/src/”
            3. Edit Makefile
            KERNEL_SOURCE := /lib/modules/3.2.0-4-486/build
            4. Check modinfo and re insmod

            Thank for all,
            Sincerely,
            Tahi

          • Great about your fixing the stuff.

            About testing, it depends on what functionality your driver provides, and how does it provide.

  25. Wonderful startup tutorial for junior linux programmers. However had to search around to actually link the /lib/modules… to the KERNEL_SOURCE, and I also had to substitute M= instead of SUBDIRS=

  26. hi there,
    under my /usr/src directory there are three directories

    linux-headers-3.13.0-24
    linux-headers-3.13.0-24-generic
    virtualbox-guest-4.3.10

    i tried using first two as linux headers but output is

    make: Entering directory `/usr/src/linux-headers-3.13.0-24′

    ERROR: Kernel configuration is invalid.
    include/generated/autoconf.h or include/config/auto.conf are missing.
    Run ‘make oldconfig && make prepare’ on kernel src to fix it.

    mkdir: cannot create directory ‘…’: Permission denied

    WARNING: Symbol version dump /usr/src/linux-headers-3.13.0-24/Module.symvers
    is missing; modules will have no dependencies and modversions.

    scripts/Makefile.build:44: /usr/src/linux-headers-3.13.0-24/…/Makefile: No such file or directory
    make[1]: *** No rule to make target `/usr/src/linux-headers-3.13.0-24/…/Makefile’. Stop.
    make: *** [_module_…] Error 2
    make: Leaving directory `/usr/src/linux-headers-3.13.0-24′

    so, what’s going on here? plz help me.

    • Which distro is it? Before try those paths, go into those folders and do the following steps:
      make oldconfig
      make modules_prepare

      • it’s linux mint.
        and these commands are not working

        output is—
        HOSTCC scripts/basic/fixdep
        scripts/basic/fixdep.c:462:1: fatal error: opening dependency file scripts/basic/.fixdep.d: Permission denied
        }
        ^
        compilation terminated.
        make[2]: *** [scripts/basic/fixdep] Error 1
        make[1]: *** [scripts_basic] Error 2
        make: *** No rule to make target `modules_prepare’. Stop.

          • sudo make oldconfig outputs:
            HOSTCC scripts/basic/fixdep
            HOSTCC scripts/kconfig/conf.o
            HOSTCC scripts/kconfig/zconf.tab.o
            HOSTLD scripts/kconfig/conf
            scripts/kconfig/conf –oldconfig Kconfig
            #
            # configuration written to .config
            #

            but sudo make modules_prepare outputs:
            make[1]: *** No rule to make target `/usr/src/linux-headers-3.13.0-24-generic/arch/x86/syscalls/syscall_32.tbl’, needed by `arch/x86/syscalls/../include/generated/uapi/asm/unistd_32.h’. Stop.
            make: *** [archheaders] Error 2

          • Seems like the source tree doesn’t contain the correct headers &/or Makefile scripts. Try “sudo make prepare”

          • actually i have a doubt
            i have 3 folders under /usr/src/
            1) linux-headers-3.13.0-24
            2) linux-headers-3.13.0-24-generic
            3) virtualbox-guest-4.3.10
            in which folder do i run the commands…1 or 2?

            BTW….i run ‘sudo make prepare’ in both of them
            output is—
            scripts/kconfig/conf –silentoldconfig Kconfig
            make[1]: *** No rule to make target `/usr/src/linux-headers-3.13.0-24-generic/arch/x86/syscalls/syscall_32.tbl’, needed by `arch/x86/syscalls/../include/generated/uapi/asm/unistd_32.h’. Stop.
            make: *** [archheaders] Error 2

          • Difference between 1 & 2 may not be much except the extra version.

            Errors point to something missing in the folders – may be try building your driver without this *prepare commands.

          • this command “make -C /usr/src/linux-headers-3.13.0-24-generic SUBDIRS=…modules”

            outputs—
            make: Entering directory `/usr/src/linux-headers-3.13.0-24-generic’

            /usr/src/linux-headers-3.13.0-24-generic/arch/x86/Makefile:113: CONFIG_X86_X32 enabled but no binutils support

            mkdir: cannot create directory ‘…modules’: Permission denied

            scripts/Makefile.build:44: /usr/src/linux-headers-3.13.0-24-generic/…modules/Makefile: No such file or directory

            make[1]: *** No rule to make target `/usr/src/linux-headers-3.13.0-24-generic/…modules/Makefile’. Stop.

            make: *** [_module_…modules] Error 2

            make: Leaving directory `/usr/src/linux-headers-3.13.0-24-generic’

          • Yes, it is because of the version mismatch.

            Now, you may compile & install this new downloaded kernel and have your system boot with that. And then, you should be able to play around with your drivers.

  27. I like to bash windows as the next guy BUT, M$ has been using hybrid kernels not needing restart for most drivers succesfully since NT4.0 (around 1996), 98 had a monolith kernel and needed restarts but XP(2001) used the hybrid approach and could load and unload drivers as well. Otherwise a very good post. Cheers

  28. Hi Anil

    Nice article series! Nevertheless, I have a doubt (don’t we all ;))

    I’ve forgotten quite a few things and hence your posts are a wonderful revision. Now as far as I remember, one could not compile drivers without “linking against” a pre-compiled kernel since all those module related glue functions are defined there isn’t it? I was wondering why so many are asking about Linux Headers perhaps it is because by default only the headers are present (since we need those for applications) but then a more pertinent problem is of the version mismatch between the modules and the kernel.

    Could you elaborate a bit more on that please? What that problem is and how do we typically resolve it?

    • Also more than just the module related glue functions, one typically uses a bunch of kernel functions and helpers for which we need to link against the kernel. So now what would happen if my ‘KERNEL_SRC’ would point to a version other than the running one? Will it still work in the sense will one be able to insert the module etc?

  29. First thank you so much for this article, I am facing problem while running Make file, it’s through error as
    Error: ubuntu@ubuntu:~/kernel$ sudo make
    [sudo] password for ubuntu:
    makefile:1: *** missing separator. Stop.
    Am waiting for your reply

  30. Makefiles should compulsorily have tabs not spaces, so make sure that once you copy paste the Makefile, replace the bunch of spaces by a tab. Hope that helps.

LEAVE A REPLY

Please enter your comment!
Please enter your name here