简体   繁体   English

从内核写入用户空间的问题-Linux设备驱动程序

[英]Problem with writing from kernel to user space - linux device driver

I'm trying to write a simple Raspberry Pi GPIO driver, with four switches connected to four of the GPIO pins, that reads each switch state. 我正在尝试编写一个简单的Raspberry Pi GPIO驱动程序,将四个开关连接到四个GPIO引脚,以读取每个开关的状态。 The problem is, I'm not sure how to write from kernel to user space, I'm not getting anything when I insert my device kernel module and try to read the device file with cat command. 问题是,我不确定如何从内核写入用户空间,当我插入设备内核模块并尝试使用cat命令读取设备文件时,我什么也没得到。 The device_read function is as follows: device_read函数如下:

static ssize_t gpio_driver_read(struct file *filp, char *buf, size_t len, loff_t *f_pos)
{
    /* Size of valid data in gpio_driver - data to send in user space. */
    int data_size = 0;

    /* Counter for 'for' loop. */
    int i;

    /* Print to kernel space. */
    printk(KERN_INFO "Reading active Switch state...\n");

    for (i = 0; i < 4; i = i+1)
    {
        printk(KERN_INFO "Loop number %d...\n", i);
        /* TODO: fill gpio_driver_buffer here. */
        if (i == 0 && mySwitches[0])
            sprintf(gpio_driver_buffer, "gpio_driver: gpio12 value: %d\n", GetGpioPinValue(GPIO_12));
        else if (i == 1 && mySwitches[1])
            sprintf(gpio_driver_buffer, "gpio_driver: gpio16 value: %d\n", GetGpioPinValue(GPIO_16));
        else if (i == 2 && mySwitches[2])
            sprintf(gpio_driver_buffer, "gpio_driver: gpio20 value: %d\n", GetGpioPinValue(GPIO_20));
        else if (i == 3 && mySwitches[3])
            sprintf(gpio_driver_buffer, "gpio_driver: gpio21 value: %d\n", GetGpioPinValue(GPIO_21));

        printk(KERN_INFO "%s\n", gpio_driver_buffer);

        /* Get size of valid data. */
        data_size = strlen(gpio_driver_buffer);

        printk(KERN_INFO "%d\n", data_size);


        /* Send data to user space. */
        if (copy_to_user(buf, gpio_driver_buffer, data_size) != 0)
        {
            return -EFAULT;
        }
    }

    return 0;
}

gpio_driver_buffer is an array of some default size (I put it to 80). gpio_driver_buffer是一些默认大小的数组(我将其设置为80)。
mySwitches is an array of 4 elements, each one with value 0 or 1 (I'm passing that as an argument when inserting the kernel module, 1 meaning I want to watch the state of the switch and 0 meaning I'm not watching the switch). mySwitches是一个由4个元素组成的数组,每个元素的值为0或1(在插入内核模块时,我将其作为参数传递,1表示我要监视开关的状态,0表示我不监视开关的状态。开关)。
GetGpioPinValue is a function that returns switch state. GetGpioPinValue是一个返回开关状态的函数。

The problem is, when I try to read the device file with cat command, I'm not getting anything. 问题是,当我尝试使用cat命令读取设备文件时,什么也没得到。 However, as you can see, I kind of debugged the program with printk commands and everything is written correctly in kernel space. 但是,如您所见,我使用printk命令调试了程序,并且一切都正确地写入了内核空间。 Where could the problem be? 问题可能在哪里?

It doesn't look like you are ever writing to the actual file. 看起来您从未写入实际文件。 Since you don't mention how you are generating the file, I'm assuming you are writing to an arbitrary file, not one created by the driver for /proc or something. 由于您没有提及如何生成文件,因此我假设您正在写入任意文件,而不是驱动程序为/ proc或其他内容创建的文件。

Review the post here: Read/write files within a Linux kernel module 在此处查看文章: 在Linux内核模块中读取/写入文件

You can try this: 您可以尝试以下方法:

int file_write(struct file *file, unsigned long long offset, unsigned char *data, unsigned int size) 
{
    mm_segment_t oldfs;
    int ret;

    oldfs = get_fs();
    set_fs(get_ds());

    ret = vfs_write(file, data, size, &offset);

    set_fs(oldfs);
    return ret;
}

Then call it instead of 'copy_to_user': 然后调用它而不是“ copy_to_user”:

/* Send data to user space. */
        if (file_write(filep, 0, gpio_driver_buffer, data_size) != 0)
        {
            return -EFAULT;
        }

这里看看示例代码。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM