Develobeer
Develobeer

Reputation: 435

c - copy_to_user: how to read a struct type value of kernel space in the user space?

I have a kernel module where I would like to pass some values into User Space. Someone suggested me to use struct type to pass more values. In kernel space I have:

typedef struct data {
        int val_delta;
        int val_btn_status;
}data_t;

static ssize_t sample_read(struct file *filp, char *buffer, size_t length, loff_t * offset)
{
    int ret = 1;
    int delta = 10;
    data_t val;

    val.val_btn_status = gpio_get_value( BTN );
    val.val_delta = delta;

    copy_to_user( buffer, &val, sizeof(data_t)); 

    return( ret );
}

In User space how can I take the two values into data_t struct? I thought to declare also in User Space the data_t type as:

typedef struct data {
        int val_delta;
        int val_btn_status;
}data_t;

int main(int argc, char **argv)
{
    data_t str;
    char *app_name = argv[0];
    char *dev_name = "/dev/sample";
    int fd = -1;

    if ((fd = open(dev_name, O_RDWR)) < 0) 
    {
        fprintf(stderr, "%s: unable to open %s: %s\n", app_name, dev_name, strerror(errno));
        return( 1 );
    }

    x = read(fd, &str, 1);

    return 0;
}

but I don't like this because I wouldn't like to rewrite both on User Space and on Kernel Space the same typedef, and maybe this one doesn't work. There are other solutions?

Upvotes: 1

Views: 3115

Answers (3)

Skegg
Skegg

Reputation: 882

Have you tried other options, like marking your ECHO interrupt from the sensor (I'm assuming that it'll be an interrupt) as a fast interrupt so it won't be pre-empted by others at the same level. Or why not have it at the highest available interrupt level on your processor (beneath the hard coded ones). As Santosh says there has to be a different reason for the freeze. Perhaps have you looked at the alignment of your given structure? In accordance to your underlying processor's word length??

Upvotes: 0

askb
askb

Reputation: 6768

Firstly, you need to understand the copy_to_user() def.

unsigned long copy_to_user (    void __user * to,
    const void * from,
    unsigned long n);

In your sample sample_read() function should use char __user *buffer instead of char *buffer.

Put your typedef struct data definition into a header file which can be included both kernel module and user program instead of redefining it twice.

Refer to thread

Upvotes: 1

Santosh A
Santosh A

Reputation: 5351

You can add the common struct and the dev_name in to a header and include in the driver and the user space program.

Like: data.h

#ifndef DATA_H
#define DATA_H    

typedef struct data {
    int val_delta;
    int val_btn_status;
}data_t;

#define dev_name "/dev/sample"

#endif

Also change

read(fd, &str, 1);

to

read(fd, &str, sizeof(data_t));

Upvotes: 1

Related Questions