c - copy_to_user:如何在用户空间中读取内核空间的结构类型值?

时间:2014-12-30 06:18:46

标签: c linux linux-kernel kernel-module

我有一个内核模块,我想将一些值传递给用户空间。有人建议我使用struct type来传递更多的值。 在内核空间中我有:

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 );
}

在用户空间中,如何将这两个值放入data_t结构中? 我还想在User Space中将data_t类型声明为:

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;
}

但我不喜欢这个,因为我不想在User Space和Kernel Space上重写相同的typedef,也许这个不起作用。还有其他解决方案吗?

3 个答案:

答案 0 :(得分:1)

您可以将common structdev_name添加到标题中,并包含在驱动程序和用户空间程序中。

赞: 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

同时更改

read(fd, &str, 1);

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

答案 1 :(得分:1)

首先,您需要了解copy_to_user() def

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

在您的示例中,sample_read()函数应使用char __user *buffer而不是char *buffer

将您的typedef struct data定义放入头文件中,该文件可以包含在内核模块和用户程序中,而不是重新定义两次。

Refer to thread

答案 2 :(得分:0)

您是否尝试过其他选项,例如将来自传感器的ECHO中断标记(我假设它将是一个中断)作为快速中断,因此它不会被同级别的其他人抢占。 或者为什么不将它放在处理器上最高的可用中断级别(在硬编码的中断级别之下)。 正如桑托什所说,必须有一个不同的原因来冻结。也许你看过你给定结构的对齐方式了吗?根据你的底层处理器的字长??