ddd
ddd

Reputation: 285

How do I share data between kernel C programs and user level C programs?

I am using Ubuntu 9.04 with kernel 2.8.32. I created a simple system call that counts the number of clone and execve calls. When the user/shell calls this system call, I would like it to pass back to the user these two values. As of now I am using:

#include <linux/sched.h>
#include <linux/asmlinkage>

/* These two variables are extern longs which are defined in sched.h and initialized in process_32.c */

total_execve;
total_clones;

long mycall* (int i){
    int array[2];
    array[0] = total_execve;
    array[1] = total_clones;
    return array;
}

I am not able to compile this as I get an undefined reference.

Regarding returning the array: Will my new call be able to access the array, won't the array be located in kernel memory?

Upvotes: 4

Views: 1162

Answers (3)

Massimiliano Di Cavio
Massimiliano Di Cavio

Reputation: 131

You cannot return an array in this way. You need to declare static keyword to return a local array function. You could do something like this:

int *mycall (int i) {
    static int array[2];
    array[0] = total_execve;
    array[1] = total_clones;
    return array;        
}

Upvotes: 0

payne
payne

Reputation: 14177

Answering your last question first: the array is indeed in "kernel" memory, but it's stack allocated which means it wilL "go away" when the mycall() function exits. Your function may appear to work, but may fail in cases where the memory gets re-used quickly.

To return multiple values, the common pattern is for the caller to pass in pointers to user-space memory, and have the kernel routine to fill them in. For example, you could pass in two pointers for your two values, or define a single struct that contains the values you need and gets filled in by the kernel routine.

Upvotes: 4

nmichaels
nmichaels

Reputation: 50941

Don't return pointers into the stack. Have the caller pass pointers into the function. Also, your function declaration syntax is incorrect. Here's what you want to do:

void mycall (int *execve, int *clones)
{
    *execve = total_execve;
    *clones = total_clones;
}

Upvotes: 5

Related Questions