【问题标题】:Can't implement write() and read() in Character Device Driver无法在字符设备驱动程序中实现 write() 和 read()
【发布时间】:2022-10-19 05:35:13
【问题描述】:

我正在尝试创建一个简单的字符设备 LKM,但我已经被困了好几天,试图让我的读写正常工作。目前当我做类似的事情时:

echo hi > /dev/simple_character_device 

我能够看到我正在写入正确数量的字节。

但是当我试图找出该设备的内容时,它会不断循环 hi 直到到达一个错误的地址。目前我正在尝试跟踪我在全局计数器中写入了多少字节。但这似乎不对。任何有关实现读写的帮助将不胜感激。

#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/slab.h>
#include <linux/string.h>

MODULE_LICENSE("GPL");

#define BUFFER 1024
char * buffer_data;

// Count open and closed
size_t current_count;

int my_open(struct inode *, struct file *);
int my_release(struct inode *, struct file *);
ssize_t my_read(struct file *, char __user *, size_t count, loff_t *);
ssize_t my_write(struct file *, const char __user *, size_t count, loff_t *offp); 

static struct file_operations fops = {
    .owner = THIS_MODULE,
    .open = my_open,
    .release = my_release,
    .read = my_read,
    .write = my_write
};


int reg_init(void)
{
    // Allocate memory to store information 
    buffer_data = kmalloc(BUFFER, GFP_KERNEL);  // Use Kernel Flag

    register_chrdev(240, "simple_character_device", &fops);
    
    printk(KERN_ALERT "Init Allocating Memory");
    return 0;
}

void reg_exit(void)
{
    // Free and unregister device and data
    kfree(buffer_data);
    unregister_chrdev(240, "simple_character_device");
    printk(KERN_ALERT "Deregister Simple Character Device");
}


int my_open(struct inode *inode, struct file *file){
    printk(KERN_ALERT "Open File Device.\n");
    return 0;
}

int my_release(struct inode *inode, struct file *file){
    printk(KERN_ALERT "Close File Device.\n");
    return 0;
}

ssize_t my_read(struct file *filp, char __user *buff, size_t count, loff_t *offp){
    // Check if we are reading within the Buffer Size
    if(BUFFER - *offp < 0){
        printk(KERN_ALERT "Out of buffer range.\n");
        return -EFAULT;
    }
    
    // Check if we fail to copy to user
    if (copy_to_user(buff, buffer_data, current_count) != 0){
        printk(KERN_ALERT "Failed to send character to user\n");
        return -EFAULT;
    }

    (*offp) += current_count;

    printk(KERN_ALERT "Read %zu bytes.\n", current_count);
    return current_count;
}

ssize_t my_write(struct file *filp, const char __user *buff, size_t count, loff_t *offp){
    // We need to get data FROM the user space
    
    // Make sure we are reading within the buffer
    if (*offp >= BUFFER || BUFFER - count < *offp){
        printk(KERN_ALERT "ATTEMPTING TO WRITE TO OUSIDE OF BUFFER!\n");
        return EFAULT;
    }
    
    // Get the amount of bytes from the user
    copy_from_user(buffer_data + *offp, buff, count);

    *offp += count;

    printk(KERN_ALERT "Wrote %zu to the device.\n", count);
    current_count = count;
    return current_count;
}
 
module_init(reg_init);
module_exit(reg_exit);

【问题讨论】:

  • my_read() 中,您不需要像在my_write() 中那样将*offp 添加到buffer_data 吗?
  • 我不完全确定你想用current_count 做什么,但my_read() 返回那个值。当count 不为零时,文件结束条件由返回值 0 指示。 cat 将继续读取文件,直到文件结束或出现错误。此外,my_read() 在每次调用中不得将超过count 字节复制到buff(即它不应访问buff[count] 及以上)。
  • 我试过修改 my_read 但仍然没有运气。它现在停止循环,但不显示输出并且计数非常大。 copy_to_user(buff, buffer_data + *offp, count); my_write 肯定也有问题:copy_from_user(buffer_data + *offp, buff, count);
  • 驱动程序打算建模什么样的数据结构?像随机访问数据块这样的东西,就像管道一样?
  • 更像是一个可以写入和读取的简单文件。例如,我们的测试用例脚本会向设备写入“hello”。然后从设备中读取并期望返回与您刚刚写入的字节数相同的字节数

标签: c linux


【解决方案1】:

在 my_read 中,您必须不允许在 current_count 之后(在初始化数据结束点之后)读取缓冲区。如果请求的计数更远,您必须首先修剪通过的计数。如果结果计数 <= 0,或者如果偏移量在 current_count 之后,则必须返回 0 以指示文件结束。

我希望您使用 echo 和 cat 进行测试。但是,如果您使用自己的代码进行测试,通过按顺序读取和写入,请不要忘记在读取和写入之间使用 lseek() 重置偏移量。

据我所知,您的代码看起来是一个好的开始,但计数和文件位置管理需要一些清理。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-05-04
    • 2021-12-13
    • 2017-12-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多