Tuesday, January 31, 2012

C code optimization benchmark

Can you believe that the code above can be optimized to run 14 times faster on Intel Core i7 CPU and to run 40 times faster on AMD Athlon X2?


#define X_SIZE 60
#define Y_SIZE 30
int matrix[X_SIZE][Y_SIZE];
void initmatrix(void)
{
int x,y;
for (x = 0; x < X_SIZE; ++x){
for (y = 0; y < Y_SIZE; ++y){
matrix[x][y] = -1;
}
}
}
void main()
{
initmatrix();
}

Wednesday, January 25, 2012

Writing device drivers in Linux: A brief tutorial - Compiling Errors and Warnings

The article:

Writing device drivers in Linux: A brief tutorial

Is a great starting point for Linux Kernel Development but it needs some simple updates. The first error you will find when compiling is:


/home/peter/devel/kdpeter/2012/bricks/original-post/memory.c:3:26: fatal error: linux/config.h: No such file or directory compilation terminated.


To fix, remove the line from the source code:
#include <linux/config.h>
Then some warnings:
/home/peter/devel/kdpeter/2012/bricks/original-post/memory.c:28:3: warning: initialization from incompatible pointer type [enabled by default]
/home/peter/devel/kdpeter/2012/bricks/original-post/memory.c:28:3: warning: (near initialization for ‘memory_fops.write’) [enabled by default]
/home/peter/devel/kdpeter/2012/bricks/original-post/memory.c: In function ‘memory_write’:
/home/peter/devel/kdpeter/2012/bricks/original-post/memory.c:110:17: warning: ignoring return value of ‘copy_from_user’, declared with attribute warn_unused_result [-Wunused-result]
/home/peter/devel/kdpeter/2012/bricks/original-post/memory.c: In function ‘memory_read’:
/home/peter/devel/kdpeter/2012/bricks/original-post/memory.c:94:15: warning: ignoring return value of ‘copy_to_user’, declared with attribute warn_unused_result [-Wunused-result]

To fix the warning with the "memory_write function" change the line from:
ssize_t memory_write(struct file *filp, char *buf, size_t count, loff_t *f_pos);
To:
ssize_t memory_write(struct file *filp, const char *buf, size_t count, loff_t *f_pos);
And change the line from:
ssize_t memory_write( struct file *filp, char *buf, size_t count, loff_t *f_pos) {
To:
ssize_t memory_write(struct file *filp, const char *buf, size_t count, loff_t *f_pos) {
To fix the warnings about ignoring return value of "copy_from_user" and "copy_to_user", create a long inside both memory_read() and memory_write() to store the return value of copy_to/from_user.
ssize_t memory_read(struct ... )
{
        long ret;
        ret = copy_to_user(...);
        ...
}
ssize_t memory_write(struct ...)
{
        long ret;
        ...
        ret = copy_from_user(...);
        ...
}

Trying to compile again, other warning will be shown:
 /home/peter/devel/kdpeter/2012/bricks/original-post/memory.c:112:6: warning: assignment discards ‘const’ qualifier from pointer target type [enabled by default]
The error is on the line:
        tmp=buf+count-1;
buf is defined as "const char *buf" while tmp is defined as "char *tmp". Assigning const char * to char * can be considered an error. To fix it, make tmp also const char *. From:
   char *tmp;
To:
        const char *tmp;
The updated version of the source code is available here

Creating Linux Kernel Module made easy

Can you believe that a two line C source code can become a Linux module?

$ cat simplest_module.c
#include <linux/module.h>
MODULE_LICENSE("GPL");

$ cat Makefile
obj-m := simplest_module.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


Just "make".
$ make

To install your brand new bogus module:
$ sudo insmod simplest_module.ko

The lsmod command show that your module has been loaded:
$ lsmod |grep simplest_module
simplest_module          689  0
To remove the module:
$ sudo rmmod simplest_module
It is very simple to create a Linux Kernel Module. If you want more than a do nothing module, follow the links:

Source: Writing device drivers in Linux: A brief tutorial
Recommended: Writing a Simple USB Driver