Porting C++ code to Linux kernel

April 5, 2009 at 1:01 am 3 comments

We all know writing Linux kernel module in C++ is not a good idea, but sometimes we don’t have options, especially when porting a existing project from Windows to Linux.
The main constrains are:
1) There is no C++ runtime in kernel. Most features of C++ will work, virtual functions, templates, operators, etc. But their is no default implementation of new and delete operators, so you need to write your own.
2) Stack space is very limited. In Linux kernel, default size of stack is 2 pages. That is 8k for 32-bit systems and 16k for 64-bit ones. Actually, stack is a little bit smaller than that, because the task structure for the thread also reside in these 2 pages. Due to this constrain, you can’t use exceptions in kernel, because exception needs too much space in stack. There are some open source C++ runtimes for kernel, which support exception, but I haven’t tried any of them.

Here are some tips I learned in a recent project:
1) Implement you own new and delete operators.
2) Do not use exceptions. If you are porting a Windows driver, probably you don’t have to worry about this.
3) Do not use global non-trival variables. Since there is no C++ runtime in kernel, nobody will construct those variable for you. There are better ways to do it, singleton, factory, etc.
4) Implement platform-dependent functions. Making C++ code work with kerenl headers is not a simple job. I wrote this part in C. If you know a better way, plese let me know.
5) Compile your c++ code with -fno-builtin -fno-exceptions -fno-rtti -nostdinc, and link obj files to your platform-dependent part.

Ok, that’s it. I attached a sample project. If I missed anything, hopefully the code can explain it. (Why wordpress does not allow zip files? Is there any better way to post code including several files?)

// =======================================
// new.h, implement new and delete

#ifndef NEW_H
#define NEW_H

#include “kernel_api.h”

inline void *operator new(size_t s) {
return my_alloc(s);
}

inline void operator delete(void *p) {
return my_free(p);
}

// you may need other forms of new and delete
#endif

// =========================================
// kernel_api.h.
#ifndef KERNEL_API_H
#define KERNEL_API_H

#ifdef __cplusplus
extern “C” {
#endif

typedef unsigned int size_t;
#define KERN_INFO    “<6>”
#define NULL    0UL

extern void printk(const char *fmt, …);
extern void *my_alloc(size_t size);
extern void my_free(void *p);

#ifdef __cplusplus
}
#endif

#endif

//==========================================
// kernel_api.c
#include <linux/module.h>

void *my_alloc(size_t s) {
return kmalloc(s, GFP_KERNEL);
}

void my_free(void *p) {
return kfree(p);
}

//==========================================
// interface.c, required interface for every kernel module
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include “cppmod.h”

static int __init cppmod_init(void)
{
printk(KERN_INFO “cpp module installed\n”);
return 0;
}

static void __exit cppmod_exit(void)
{
printk(KERN_INFO “cpp module removed\n”);
}

module_init(cppmod_init);
module_exit(cppmod_exit);

MODULE_LICENSE(“GPL”);

//==========================================
// cppmod.h, exported C interface from C++ code
#ifndef CPP_MOD_H
#define CPP_MOD_H

#ifdef __cplusplus
extern “C” {
#endif

extern int start_driver(void* data);
extern void stop_driver(void);

#ifdef __cplusplus
}
#endif

#endif

//==========================================
//  cppmod.cpp, finally, my C++ code
#include “kernel_api.h”
#include “new.h”
#include “cppmod.h”

class Driver {
public:
Driver(unsigned int dev_id) : _id(dev_id) { printk(KERN_INFO “C++ driver started\n”); }
~Driver(void) { printk(KERN_INFO “Goodbye C++ driver\n”); }
private:
unsigned int _id;
};

static Driver *g_driver = NULL;

extern “C” int start_driver(void *data) {
g_driver = new Driver(*(unsigned int*)data);
if(!g_driver)
return -1;
return 0;
}

extern “C” void stop_driver(void) {
if(g_driver)
delete g_driver;
}

#####################################################
# Makefile
obj-m += mydrv.o
mydrv-objs := interface.o cppmod.o kernel_api.o
list-multi := mydrv.o

all: cppmod.o module
module:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules

clean:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean

cppmod.o : cppmod.cpp new.h kernel_api.h cppmod.h
$(CC) -c -o $@ -fno-builtin -fno-exceptions -fno-rtti -nostdinc $<

About these ads

Entry filed under: kernel programming. Tags: , .

Object in Javascript, a C++ programmer’s point of view Thread Building Block test drive

3 Comments Add your own

  • 1. Nathan Cooprider  |  July 22, 2011 at 7:48 am

    This example does not seem to work for me. Is this code rot or am I doing something wrong?

    ncooprider@machine:~/sandbox/try3$ ls
    cppmod.cpp cppmod.h interface.c kernel_api.c kernel_api.h Makefile new.h
    ncooprider@machine:~/sandbox/try3$ make
    cc -c -o cppmod.o -fno-builtin -fno-exceptions -fno-rtti -nostdinc cppmod.cpp
    In file included from cppmod.cpp:4:
    new.h:6: error: ‘operator new’ takes type ‘size_t’ (‘long unsigned int’) as first parameter
    make: *** [cppmod.o] Error 1

  • 2. korisk  |  June 25, 2013 at 12:54 am

    Thank you for the great job! I made some modifications and put it on githab if you do not mind. (https://github.com/korisk/fpw)

  • 3. Vrushali  |  October 17, 2013 at 1:04 pm

    Hi,
    Im working on a similar project trying to port quite a large piece of code into the kernel. A lot of it is in c++ using classes and some other OOP features. Can you point me to any more resources that will help me acheieve this?
    In short how does one even start the process of “porting” C++ code into the kernel

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Trackback this post  |  Subscribe to the comments via RSS Feed


Calendar

April 2009
M T W T F S S
« Mar   May »
 12345
6789101112
13141516171819
20212223242526
27282930  

Most Recent Posts


Follow

Get every new post delivered to your Inbox.

%d bloggers like this: