I'm very new to kernel module programming and right now I'm trying to run the most basic hello world module program, however I could not get any output.
I have written the hello world program introduced in Linux Device Drivers 3rd ed and got some help from this website and this one.
hello.c
#include <linux/module.h>
#include <linux/kernel.h>
MODULE_LICENSE("GPL");
static int hello_init(void){
printk("<1>Hello, world!\n");
return 0;
}
static void hello_exit(void){
printk(KERN_ALERT "Goodbye, world..\n");
}
module_init(hello_init);
module_exit(hello_exit);
The file is in /home/volkan/drive directory. Along with the c file, I have my Makefile
Makefile
obj-m += hello.o
From the terminal, I execute this command for compiling the module:
sudo make -C /lib/modules/3.8.0-19-generic/build M=/home/volkan/drive/ modules
Resulting in:
make: Entering directory `/usr/src/linux-headers-3.8.0-19-generic'
CC [M] /home/volkan/drive/hello.o
Building modules, stage 2.
MODPOST 1 modules
CC /home/volkan/drive/hello.mod.o
LD [M] /home/volkan/drive/hello.ko
make: Leaving directory `/usr/src/linux-headers-3.8.0-19-generic'
I assume up to this point, nothing went wrong. Now, I insert my module and then remove:
volkan#Varaquilex ~/drive $ sudo insmod ./hello.ko
volkan#Varaquilex ~/drive $ sudo rmmod hello
volkan#Varaquilex ~/drive $
There is no output. I also have little experience in linux, so explanatory answers are more than welcome. Am I doing something wrong? Why cannot I see any output?
The kernel messages are logged in the kern.log file located in /var/log. Depending on your system, it may also be in dmesg. So you have to cat accordingly.
Use the command cat /var/log/kern.log
Dec 9 18:51:10 Varaquilex kernel: [ 2818.079572] <1>Hello, world!
Dec 9 18:55:02 Varaquilex kernel: [ 3050.256134] Goodbye, world..
Related
Trying the simplest kernel module from LDD3 without any modification on custom built kernel v4.1.0-rc6 for Beagle Bone board with BusyBox v1.23.0. The code for the module is as follows:
#include <linux/init.h>
#include <linux/module.h>
MODULE_LICENSE("Dual BSD/GPL");
static int hello_init(void)
{
printk(KERN_ALERT "Hello, world\n");
return 0;
}
static void hello_exit(void)
{
printk(KERN_ALERT "Goodbye, cruel world\n");
}
module_init(hello_init);
module_exit(hello_exit);
The Makefile is:
ARCH := arm
CROSS_COMPILE := arm-cortex_a8-linux-gnueabi-
obj-m := hello.o
all:
make ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) -C /path/to/linux/source/tree M=$(PWD) modules
clean:
make ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) -C /path/to/linux/source/tree M=$(PWD) clean
The module is compiling and installing on the rootfs just fine. also it is loading:
$ insmod hello.ko
[ 30.692404] Hello, world
But when trying to remove it, I am getting:
$ rmmod hello.ko
Segmentation fault
$modprobe -r hello.ko
Segmentation fault
$ lsmod
hello 813 0 - Live 0xbf000000 (O)
The kernel is compiled with module unloading (both regular and forced) support enabled.
What can be the possible cause of this issue? What is the way to approach the investigation of it?
Update:
As suggested in the comments I have tried including linux/kernel.h, defining the MODULE,LINUX and __KERNEL__ symbols. Added the__init and __exit prefixes to the functions. Removed the static modifiers. Removed the printk lines. The result the same. dmesg shows only the initial greeting. Loading and unloading of the kernel's modules such a gpio_keys or crypto/ccm is working, surprisingly. So the only thing remaining to suspect is the way the module is compiled..
Update 2
Updating the kernel to the freshest snapshot didn't help. Compiled the module with different optimization settings didn't help. Next step, I guess, I am going to modify the BusyBox's rmmod to have some indication of the problem location..
Have a look at these tutorials:
http://www.tldp.org/HOWTO/Module-HOWTO/x839.html
http://www.tldp.org/LDP/lkmpg/2.4/html/x281.htm
Try adding:
#define MODULE
#define LINUX
#define __KERNEL__
#include <linux/kernel.h> /* Needed for KERN_ALERT */
I have managed to work around this problem. Using strace I've found out that the segfault is occurring somewhere when reading the BusyBox specific modules.dep.bb file. This file is used by BusyBox when it is compiled with the "Simplified modutils" option (CONFIG_MODPROBE_SMALL). By disabling the option, selecting the utils to be installed and rebuilding BusybBox I've got the module unloading work. I believe the problem root is near the fact the test module is compiled and stored outside the /lib/..../modules directory, so busybox with the simplified modutils is just getting confused.
I'm trying to compile my first "Hello World" application using GCC (build-on clang and stand-alone GCC-4.9.2) without any success:
OS version is OS X Yosemite 10.10.2.
I'm using the following code (main.c):
#include <stdlib.h>
#include <stdio.h>
int main (){
printf("Hello World!");
getchar();
return 0;
}
Then I compile it in terminal with a command (clang shipped with XCode):
gcc -o hello -c main.c
As a result I got following error whe running compiled hello file:
MBP-Andrii:cTest andrii$ gcc -o hello -c main.c
MBP-Andrii:cTest andrii$ hello
-bash: /Users/andrii/avrTest/cTest/hello: Permission denied
If I change the permissions for hello file to 777 and a new error again:
MBP-Andrii:cTest andrii$ chmod 777 hello
MBP-Andrii:cTest andrii$ hello
Killed: 9
MBP-Andrii:cTest andrii$
The same thing happens with stand-alone GCC-4.9.2.
I guess It might be something related to the output binary format or some missing flags for compiler.
Remove the -c from the command you're using to compile the application.
The -c tells the compiler to only compile and assemble but not link. You are not actually creating an application when using -c.
See the GCC Manual:
-c
Compile or assemble the source files, but do not link. The linking stage simply is not done. The ultimate output is in the form of an object file for each source file.
By default, the object file name for a source file is made by replacing the suffix ‘.c’, ‘.i’, ‘.s’, etc., with ‘.o’.
Unrecognized input files, not requiring compilation or assembly, are ignored.
Try executing it by typing ./hello
I am just starting with modular programming.
Above are my two files:
hello.c
#include <linux/init.h>
#include <linux/module.h>
static int hello_init(void)
{
printk(KERN_ALERT "TEST: Hello world\n");
return 0;
}
static void hello_exit(void)
{
printk(KERN_ALERT "TEST: Good Bye");
}
module_init(hello_init);
module_exit(hello_exit);
Makefile
obj-m += hello.o
KDIR = /usr/src/linux-headers-3.13.0-46-generic
all:
$(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules
clean:
rm -rf *.o *.ko *.mod.* *.symvers *.order
And here's my terminal output showing error in insmod command, kindly help.
anubhav#anubhav-Inspiron-3421:~/Desktop/os$ make
make -C /usr/src/linux-headers-3.13.0-46-generic SUBDIRS=/home/anubhav/Desktop/os modules
make[1]: Entering directory `/usr/src/linux-headers-3.13.0-46-generic'
Building modules, stage 2.
MODPOST 1 modules
make[1]: Leaving directory `/usr/src/linux-headers-3.13.0-46-generic'
anubhav#anubhav-Inspiron-3421:~/Desktop/os$ insmod hello.ko
insmod: ERROR: could not insert module hello.ko: Operation not permitted
If you have secure boot enabled, the newer kernels won't allow inserting arbitrary kernel modules. So, either you can disable secure boot in your BIOS or you need to sign the kernel modules you want to install.
Steps to securely sign your kernel modules:
Create a X509 certificate that can be imported in firmware
Enrolling the public key just created
Sign the module you want to install
Install the module
You need to be root to do steps 2 & 4. The detailed process is described in a nice Ubuntu blog.
As isowen mentioned only root can load or unload the module.
You see the print in hello_init() when you do insmod hello and you see the print in hello_exit() when you do rmmod hello.
execute cat /proc/sys/kernel/modules_disabled and if you see the result
1 then execute echo 'kernel.modules_disabled=1' >> /etc/sysctl.d/99-custom.conf then reboot and try again. ;) BR nu11secur1ty
I am following the following tutorial, trying to learn how to develop device drivers, and in Chapter 2, the focus is to develop a working module and insert it into the kernel. I used the following code (hello.c):
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
MODULE_LICENSE("Dual BSD/GPL");
static int hello_init(void)
{
printk(KERN_ALERT "Hello World!\n");
return 0;
}
static void hello_exit(void)
{
printk(KERN_ALERT "Goodbye, cruel world!\n");
}
module_init(hello_init);
module_exit(hello_exit);
And my this is the Makefile:
obj-m += hello.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
I then run the following in LXTerminal:
brian#brian-desktop:~/driver_stuff/hello$ su
root#brian-desktop:/home/brian/driver_stuff/hello# make
make -C /lib/modules/2.6.32-21-generic/build M=/home/brian/driver_stuff/hello modules
make[1]: Entering directory `/usr/src/linux-headers-2.6.32-21-generic'
Building modules, stage 2.
MODPOST 1 modules
make[1]: Leaving directory `/usr/src/linux-headers-2.6.32-21-generic'
root#brian-desktop:/home/brian/driver_stuff/hello# insmod ./hello.ko
root#brian-desktop:/home/brian/driver_stuff/hello# rmmod hello
root#brian-desktop:/home/brian/driver_stuff/hello# exit
However, after the insmod ./hello.ko command, one should expect that the terminal would print "Hello world!" and then "Goodbye, cruel world!" after the rmmod hello command. The book mentioned that this happens when you run the commands in the console, but not in an emulated terminal, could this be the problem?
I also checked under /var/log/messages and /var/log/messages.1 which had no record of either "Hello World!" nor "Good bye, cruel world!". Is it possible that these messages are in a different file, or is the issue that the messages aren't being pushed to the kernel in the first place?
If you need an info about the kernel I am running (Lubuntu 10.04, inside a VM):
brian#brian-desktop:~/driver_stuff/hello$ uname -r
2.6.32-21-generic
Thank you.
The output from kprintf is always to the kernel log. This may happen to also go to the system console (and, therefore, to the terminal you're using if you're on the console), but there's nothing to link it back to the specific terminal that you loaded the module in.
To read the kernel log, run dmesg.
I'm trying to get the examples from Linux Device Drivers, ed 3 (ldd3) working before I start working with the book so that I can have a set of working examples that I can use.... I'm getting the following errors (seeing error in Debian squeeze and also Crunchbang Linux):
inp.c:33:20: error: [u]asm/io.h:[/u] No such file or directory
when I looked at the makefile I found this (which I think is the problem):
KERNELDIR ?= /lib/modules/$(shell uname -r)/build
INCLUDEDIR = $(KERNELDIR)/include
contents of /lib/modules/uname -r/build which is a link to /usr/src/linux-headers-2.6.39-bpo.2-486/
$ uname -r
2.6.39-bpo.2-486
$ ls /lib/modules/`uname -r`/build
arch include Makefile Module.symvers scripts
$ ls /lib/modules/`uname -r`/build/include
config generated linux
The directory that make is looking does not have the required files. I found the files required under /usr/src/linux-headers-2.6.39-bpo.2-common/ and the missing asm/io.h file # /usr/src/linux-headers-2.6.39-bpo.2-common/include/asm-generic/
$ ls /usr/src/linux-headers-2.6.39-bpo.2-common/
arch include Kbuild Makefile scripts
$ ls /usr/src/linux-headers-2.6.39-bpo.2-common/include/
acpi crypto Kbuild linux media net rdma scsi staging trace xen
asm-generic drm keys math-emu mtd pcmcia rxrpc sound target video
Do I have to install any package to get the files in that directory... I've already installed linux-headers-uname -r package (in both Debian and Crunchbang)... In gnewsense I found the files in /lib/modules/$(shell uname -r)/build... but it was a older kernel... so not sure if the directory structure under linux change... or is it distro specific... please let me know how do I get the compilation going.... I'm not very good with Makefiles so how can I change the makefile so that it will look for the header files in the other directories....
Thanks,
asp5
First things first, LDD3 is quite old and I wouldn't be surprised if header files might have moved around. Javier Martinez Canillas has updated the LDD3 sources for more modern kernels.
When investigating this a little further, I found that the asm symlink has been broken for a while. (io.h appears to have stored in asm-generic/ for some reason.) In case you're curious, I filed a bug report at Ubuntu for the broken symlinks.
For whatever it's worth, I can build a module referencing either <asm/io.h> or <asm-generic/io.h> (though as Hasturkun reminds me, you shouldn't use asm-generic directly):
$ cat > Makefile
obj-m = foo.o
$ cat > foo.c
#include <linux/module.h>
#include <linux/sched.h>
#include <asm/io.h>
int init_module() { return 0; }
void cleanup_module() { }
$ make -C /lib/modules/`uname -r`/build M=$PWD
make: Entering directory `/usr/src/linux-headers-2.6.38-12-generic'
LD /home/sarnold/tmp/module/built-in.o
CC [M] /home/sarnold/tmp/module/foo.o
Building modules, stage 2.
MODPOST 1 modules
CC /home/sarnold/tmp/module/foo.mod.o
LD [M] /home/sarnold/tmp/module/foo.ko
make: Leaving directory `/usr/src/linux-headers-2.6.38-12-generic'
$ cat > foo.c
#include <linux/module.h>
#include <linux/sched.h>
#include <asm-generic/io.h>
int init_module() { return 0; }
void cleanup_module() { }
$ make -C /lib/modules/`uname -r`/build M=$PWD
make: Entering directory `/usr/src/linux-headers-2.6.38-12-generic'
CC [M] /home/sarnold/tmp/module/foo.o
Building modules, stage 2.
MODPOST 1 modules
CC /home/sarnold/tmp/module/foo.mod.o
LD [M] /home/sarnold/tmp/module/foo.ko
make: Leaving directory `/usr/src/linux-headers-2.6.38-12-generic'
$