Thread: Linux kernel module help

  1. #1
    Registered User Annonymous's Avatar
    Join Date
    Apr 2011
    Location
    Jackson, New Jersey, United States
    Posts
    302

    Linux kernel module help

    I am trying learn to program linux kernel modules and smoothly transition in device driver programming. I have a year worth of programming in C and have been using linux for years!! But my question is how do i compile a module? I got as far as coding it but am stuck as of now. I need to learn how to write the make file. Then compile it on the command line and run the hello_world module. I have Googled it extensively and every how to or example that I come across is really confusing or not elaborate enough!

  2. #2
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    So it sounds like you need to start with some makefile tutorials. They can be quite daunting, but the basics really aren't too bad. It also sounds like you're not under any sort of time constraint, so take the time to really learn Makefiles. It's a good skill to have around, especially since you're a big time Linux user. I'm no expert in make, but I get along alright, and there are several others around here that can help you too. Post up your hello world source and make file, what commands you ran to compile/load it, and any error messages you got. We'll see what we can do.

  3. #3
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Do what the real kernel developers do: steal the makefile from some other module and tweak it.
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

  4. #4
    Registered User Annonymous's Avatar
    Join Date
    Apr 2011
    Location
    Jackson, New Jersey, United States
    Posts
    302
    Ok here is my code for my make file:

    I saved the makefile as hello_world.o
    Code:
    # Makefile for compiling Kernel
    obj-m = hello_world.o
    KVERSION = $(shell uname -r)
    all:
            make -C /lib/modules/$(KVERSION)/build M=$(PWD) modules
    clean:
            make -C /lib/modules/$(KVERSION)/build M=$(PWD) clean
    Now here is my hello_world source:

    I saved this as hello_world-r.o

    Code:
    #include <linux/module.h>   
    #include <linux/kernel.h> 
    #include <linux/init.h>
    
    MODULE_LICENSE("GPL");
    MODULE_AUTHOR("Annonymous");
    
    static int hello_init(void) {
            printk(KERN_ALERT "Hello world!\n");  
            return 0;                             
    }
    
    static void hello_exit(void) {
            printk(KERN_ALERT "Goodbye world!\n");
    }
    
    module_init(hello_init);
    module_exit(hello_exit);
    Terminal input/output:
    Code:
    I cd'd into the dir where the hello_world source is in. Then i tried this on the command line ==> gcc -D__KERNEL__ -DMODULE -I/usr/src/linux-2.4/include -O2 -c hello_world-r.o
    
    It gave the error: gcc: hello_world-r.o: linker input file unused because linking not done
    Am I supposed to be doing something with the makefile first?? I'm stumped!!

    @brewbuck, that is exactly what I did. I stole the makefile from a random makefile tutorial.

    TRY #2:
    Code:
    I tried renaming the file with the (dot)c extension and then ran this on the command line ==> gcc hello_world-r.c -o hello2
    I was given these errors ==> 
    hello_world.c:1:3: error: invalid preprocessing directive #Makefile
    hello_world.c:2:3: error: invalid preprocessing directive #modules
    hello_world.c:3:4: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘-’ token
    TRY #3:
    Code:
    I even tried ==> make -C ~/LKM/
    
    NOTHING
    Last edited by Annonymous; 04-28-2011 at 07:37 PM.

  5. #5
    &TH of undefined behavior Fordy's Avatar
    Join Date
    Aug 2001
    Posts
    5,793
    Have you tried just typing the command "make"?

  6. #6
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Quote Originally Posted by Annonymous View Post
    Am I supposed to be doing something with the makefile first?? I'm stumped!!
    You have done this really, really, really wrong.

    Let's start from the beginning. Create an empty directory. Go into it. Create an empty file called "Makefile". With a capital M. Do not name it "hello_world.o". .o files are compiled binary objects, not makefiles. In order to work, the makefile must be called "Makefile".

    "Makefile" should look like the file you posted, except for the "clean" part. Instead, that part should be:

    Code:
    clean:
    	-rm hello_world.ko  hello_world.mod.c  hello_world.mod.o  hello_world.o modules.order  Module.symvers \
    		.hello_world.ko.cmd .hello_world.mod.o.cmd  .hello_world.o.cmd .tmp_versions/*
    	rmdir .tmp_versions
    Hopefully you can understand the significance of this difference. As anduril462 says, if you have been programming in C for a year and you are working on linux, now is the time when you should start learning to use "make":

    GNU `make'

    Make is whitespace sensitive. Lines that are indented should begin with tabs, not spaces. If you open a file called "Makefile" in vim, vim will syntax highlight it and you can see the difference between using spaces and tabs.

    The other file you need in that directory is "hello_world.c". That is exactly what it should be called in order to work with your makefile. The code you posted for that is fine. Now:

    Code:
    [root~/C/kernel/tmp] make
    make -C /lib/modules/2.6.35.12-90.fc14.x86_64/build M=/root/C/kernel/tmp modules
    make[1]: Entering directory `/usr/src/kernels/2.6.35.12-90.fc14.x86_64'
      CC [M]  /root/C/kernel/tmp/hello_world.o
      Building modules, stage 2.
      MODPOST 1 modules
      CC      /root/C/kernel/tmp/hello_world.mod.o
      LD [M]  /root/C/kernel/tmp/hello_world.ko
    make[1]: Leaving directory `/usr/src/kernels/2.6.35.12-90.fc14.x86_64'
    If you got errors, it is probably because you don't have your kernel headers and source in place. If everything worked, there should now be a file called "hello_world.ko" (among other things) in the directory:

    Code:
    [root~/C/kernel/tmp]ls -a1
    .
    ..
    hello_world.c
    hello_world.ko
    .hello_world.ko.cmd
    hello_world.mod.c
    hello_world.mod.o
    .hello_world.mod.o.cmd
    hello_world.o
    .hello_world.o.cmd
    Makefile
    makefile
    modules.order
    Module.symvers
    .tmp_versions
    .ko is for kernel object. That is the module. Notice also that "hello_world.o", a binary object created by make (not by renaming a makefile), is there now too. That is used in the build process make performed.

    Now install:

    Code:
    [root~/C/kernel/tmp] insmod ./hello_world.ko
    "Hello world!" might appear on your screen, but probably not. Where it will appear is at the end of /var/log/messages:

    Code:
    [root~/C/kernel/tmp] tail /var/log/messages
    [ ... ]
    Apr 29 06:52:12 mint kernel: [ 4213.046679] Hello world!
    So it worked. Now remove the module:

    Code:
    [root~/C/kernel/tmp] rmmod hello_world
    In my opinion, unless you have some hands on interest in electronics -- the kind of electronics you can mail order or buy in a specialty store for hobbyists, which come with the necessary specifications -- going further than this with device driver programming on linux is a waste of time. You cannot get the specifications for normal consumer hardware such as webcams, usb devices, and audio cards. You will have to "reverse engineer" them. You are not qualified to attempt that. Honestly.

    You can write some clever non hardware related drivers for (eg) memory manipulation. There are some ideas in this free online book:

    Linux Device Drivers, Third Edition [LWN.net]

    The material is outdated, but it worked last time I tried it. If you are serious, go to amazon and find a newer book. If you cannot do that, give up now. If you are interested in the kernel, this book is great:

    Amazon.com: Professional Linux Kernel Architecture (Wrox Programmer to Programmer) (9780470343432): Wolfgang Mauerer: Books

    However, it is not a guide to device drivers, which, as I said, are probably a waste of time. You will learn more about programming, and be less frustrated, doing something else.
    Last edited by MK27; 04-29-2011 at 07:38 AM.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  7. #7
    Registered User Annonymous's Avatar
    Join Date
    Apr 2011
    Location
    Jackson, New Jersey, United States
    Posts
    302
    Well all this is just a hobby MK27. I am a 2stroke dirt bike mechanic. And sometimes you need a change of scenery. This is my change of scenery, programming. I enjoy programming in C! It's just I want to go in a different direction. I have 3 books to choose from; Assembly, Linux/Unix Sockets, and Advanced C. I thought that maybe LKM and device driver programming would be interesting! Even tho I don't have a book on it. Do you really think this is a waste of time for me? All I really want is to program small key board device drivers is all. I just want to move on from regular C to keep it interesting! Im gonna keep at it tho
    Last edited by Annonymous; 04-29-2011 at 01:29 PM.

  8. #8
    &TH of undefined behavior Fordy's Avatar
    Join Date
    Aug 2001
    Posts
    5,793
    If you are doing it as a hobby then how can it be a waste of time? Keep going.

    You might not have hardware to design for right now, but poking around in the Linux kernel is rather interesting anyway.

    There's some decent stuff on the web, just do a search. Also, have a look at the kernel source as there's some decent documentation that comes with it

  9. #9
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Quote Originally Posted by Annonymous View Post
    All I really want is to program small key board device drivers is all.
    The issue, like I said, is whether you have the specs for the device. I'm not trying to discourage you, I'm just trying to warn you. If you have a device that was intended to be low level programmed for, by the end user, and you have the appropriate docs, go for it. You might find this interesting:

    Writing a Simple USB Driver | Linux Journal

    Given an infinite amount of time, space, and money, I could totally get into stuff like that -- you get to tool around a bit, and I imagine it could lead to very crazy stuff (robots, etc). I don't have infinite time and resources, so I haven't, but if it interests you, go for it. Just do not expect to be writing drivers for normal consumer hardware. I have even asked manufacturers for specs before -- they would not give them to me. At that point you are up a creek without a paddle.

    Kernel space programming is a great way to get exposed some really nice C code. Not that I've done it much, but that was my impression.

    I do think doing it without a book will be difficult, but everybody learns differently. There are quite a few of these that have come out in the past few years. I have "Essential Linux Device Drivers", by Sreekrishnan Ventateswaran, it is exhaustive and has a lot of interesting stuff in it. The kernel changes constantly. Do not get anything published prior to 2008. That free PDF book from my other post is older, but like I said, it still works. It's also well written and organized.

    Anyway good luck! And enjoy cboard
    Last edited by MK27; 04-29-2011 at 02:48 PM.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  10. #10
    &TH of undefined behavior Fordy's Avatar
    Join Date
    Aug 2001
    Posts
    5,793
    >>I have "Essential Linux Device Drivers", by Sreekrishnan Ventateswaran, it is exhaustive and has a lot of interesting stuff in it.

    I have that too. Just to prove about the kernel going out of date, the edition I have is 2008 and already one of the first examples wont compile due to the a change with "device_create". You just need to read as much as you can from the web and the docs and read what books you have.

    Its definitely worth messing with as its all very interesting stuff. I'm trying to mess with an AVR microcontroller, getting it to link up to a Linux driver via USB. I'm not trained in electronics and my soldering skills are so bad that I apply more heat to my hands than the components, but its all good fun!

  11. #11
    Registered User Annonymous's Avatar
    Join Date
    Apr 2011
    Location
    Jackson, New Jersey, United States
    Posts
    302
    Yeah, I am definitely going to continue as far as I can! I need to look for a damn book to help me out! Maybe Barns & Nobles will have something. I just got a chance to sit down and work with the module. I get the concept thanks to MK27. Unfortunately, I am getting some errors. I made a directory and put my .c file in it. I also put my Makefile, with no extension and a capital M (MK27). I then cd'd into that directory and entered "make" on the command line. Here are the errors:
    Code:
    annonymous@annonymous3000:~/sys/log$ make
    make -C /lib/modules/2.6.38-8-generic-pae/build M=/home/annonymous/sys/log modules
    make[1]: Entering directory `/usr/src/linux-headers-2.6.38-8-generic-pae'
    make[2]: *** No rule to make target `/home/annonymous/sys/log/hello_world3.o', needed by `/home/annonymous/sys/log/hello_world2.o'.  Stop.
    make[1]: *** [_module_/home/annonymous/sys/log] Error 2
    make[1]: Leaving directory `/usr/src/linux-headers-2.6.38-8-generic-pae'
    make: *** [all] Error 2
    Here is my makefile:
    Code:
    obj-m += hello_world2.o
    
    hello_world2-objs := hello_world3.o hello_world4.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
    Any feedback?
    Last edited by Annonymous; 05-01-2011 at 01:16 AM.

  12. #12
    &TH of undefined behavior Fordy's Avatar
    Join Date
    Aug 2001
    Posts
    5,793
    >>hello_world2-objs := hello_world3.o hello_world4.o

    What's this line? That's only needed if you have multiple source files. If you have 1 file, named say "hello_world2.c" that line can be removed.

  13. #13
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Quote Originally Posted by Annonymous View Post
    Here are the errors:
    Looks like maybe you don't have a file named hello_world3.c?

    I wouldn't worry about the makefile too much. The first one you posted -- except for the "clean" part -- is fine if you are only working with one source file. Beyond that, I can tell you what's worked for me:

    The entry and exit functions registered with module_init() and module_exit() must have static signatures, meaning they have to be defined in the same file they are registered in. From there, you can call whatever else is in your build tree normally. If you split the hello_world module into 2 parts -- hello.c and main.c, and use a header for hello.c, like this:

    Code:
    /* main.c */
    #include "hello.h"
    
    MODULE_LICENSE("GPL");
    MODULE_AUTHOR("Annonymous");
    
    static int hello_init(void) {
    	hello_func();
    	return 0;
    }
    
    static void hello_exit(void) {
    	printk(KERN_ALERT "Goodbye world!\n");
    }
    
    module_init(hello_init);
    module_exit(hello_exit);
    Code:
    /* hello.h */
    #include <linux/module.h>   
    #include <linux/kernel.h> 
    #include <linux/init.h>
    
    void hello_func ();
    Code:
    /* hello.c */
    #include "hello.h"
    
    void hello_func () {
            printk(KERN_ALERT "Hello world!\n");
    }
    You can compile this with a makefile like this:

    Code:
    obj-m := hello_world.o
    hello_world-objs := hello.o main.o
    KVERSION = $(shell uname -r)
    
    all:
    		make -C /lib/modules/$(KVERSION)/build M=$(PWD) modules
    
    clean:
    	-rm *.ko *.mod.c *.mod.o *.o .* modules.order  Module.symvers *.cmd .tmp_versions/*
    	rmdir .tmp_versions
    I'm no make wiz and I know you are completely new to it, but there is some magic in the recipe for "all" such that you do not need to write any rules for the .o targets. However, those targets should have a corresonding .c file. And do get your "clean" right and use it: calling "make clean" should remove everything from the directory except your sources and the makefile. Do that before you call "make" again after having built in the directory.
    Last edited by MK27; 05-01-2011 at 02:51 AM.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  14. #14
    Registered User Annonymous's Avatar
    Join Date
    Apr 2011
    Location
    Jackson, New Jersey, United States
    Posts
    302
    OK finally got it. I did not realize it was that easy. I kind of feel somewhat special now lol I made the proper directory. The dir included both the Makefile and the (dot)c file. I cd'd into the dir then entered make on the command line. It made all of the proper necessary files. I then insmod'd the (dot)ko file. Although I cannot find the file, I am sure everything worked out because I did not receive any errors.

    Well I did not have the file dir /var/log/messages. I was getting errors when i tried to cd in to the dir. I opened up the var folder and found log and did not see messages. I did find the file kern.log here it is:
    Code:
    May  1 03:18:04 codecaine3000 kernel: [ 3660.891698] usb 1-8: USB disconnect, address 5
    May  1 11:20:18 codecaine3000 kernel: [32594.649668] hello_world1: module license 'Dual DSD/GPL' taints kernel.
    May  1 11:20:18 codecaine3000 kernel: [32594.649675] Disabling lock debugging due to kernel taint
    May  1 11:20:18 codecaine3000 kernel: [32594.650326] Hello, world
    May  1 11:26:31 codecaine3000 kernel: [32967.727418] Goodbye, cruel world
    I am definitely sketched out by the message for "taints kernel" on the end of line 2!
    Last edited by Annonymous; 05-01-2011 at 10:38 AM.

  15. #15
    &TH of undefined behavior Fordy's Avatar
    Join Date
    Aug 2001
    Posts
    5,793
    run "lsmod | grep <your module name here>" to see if its loaded

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. linux kernel module programming
    By circuit in forum Linux Programming
    Replies: 10
    Last Post: 12-01-2004, 06:08 PM
  2. Kernel Module Programming in 2.6
    By KneeLess in forum Linux Programming
    Replies: 1
    Last Post: 04-13-2004, 11:51 AM
  3. linux kernel compile
    By mart_man00 in forum Tech Board
    Replies: 13
    Last Post: 04-30-2003, 04:31 PM
  4. Linux kernel not compiling
    By frenchfry164 in forum Tech Board
    Replies: 2
    Last Post: 04-29-2003, 04:10 PM
  5. linux kernel 2.5
    By ygfperson in forum A Brief History of Cprogramming.com
    Replies: 4
    Last Post: 07-31-2002, 11:17 PM

Tags for this Thread