Linux 设备驱动程序 - 我的 device_read() 有什么问题?

发布于 2024-08-29 12:22:50 字数 2173 浏览 7 评论 0原文

我一直在编写一个设备 dev/my_inc ,该设备旨在采用 ASCII 字符串表示的正整数 N 并将其存储在内部。从设备进行的任何读取都应生成整数 (N+1) 的 ASCII 字符串表示形式。

但是,当我 cat /dev/my_inc 时,我似乎只将 myinc_value 消息缓冲区的前半部分返回到用户空间。

  • 如果 myinc_value 为 48,cat /dev/my_inc 生成 4。

  • 如果 myinc_value 是 489324,cat /dev/my_inc 产生 489。

但是,bytes_read 表示整个消息已复制到用户空间。以下是 dmesg 的输出:

[54471.381170] my_inc opened with initial value 489324 = 489324.
[54471.381177] my_inc device_read() called with value 489325 and msg 489324.
[54471.381179] my_inc device_read() read 4.
[54471.381182] my_inc device_read() read 8.
[54471.381183] my_inc device_read() read 9.
[54471.381184] my_inc device_read() read 3.
[54471.381185] my_inc device_read() read 2.
[54471.381186] my_inc device_read() read 5. my_inc device_read() returning 7.
[54471.381192] my_inc device_read() called with value 489325 and msg 489325.

当从 shell 调用时:

root@rbst:/home/rob/myinc_mod# cat /dev/my_inc
489

来源:

// Read from the device
//
static ssize_t device_read(struct file * filp, char * buffer, 
    size_t length, loff_t * offset)
{
    char c;
    int bytes_read = 0;
    int value = myinc_value + 1;

    printk(KERN_INFO "my_inc device_read() called with value %d and msg %s.\n", 
        value, msg);

    // Check for zero pointer
    if (*msg_ptr == 0) 
    {
        return 0;
    }
    // Put the incremented value in msg 
    snprintf(msg, MAX_LENGTH, "%d", value);

    // Copy msg into user space
    while (length && *msg_ptr) 
    {
        c = *(msg_ptr++);
        printk(KERN_INFO "%s device_read() read %c. ", DEV_NAME, c);
        if(put_user(c, buffer++))
        {
            return -EFAULT;
        }
        length--;
        bytes_read++;
    }

    // Nul-terminate the buffer
    if(put_user('\0', buffer++))
    {
        return -EFAULT;
    }
    bytes_read++;
    printk("my_inc device_read() returning %d.\n", bytes_read);
    return bytes_read;
}

I've been writing a device dev/my_inc that's meant to take a positive integer N represented as an ASCII string, and store it internally. Any read from the device should produce the ASCII string representation of the integer (N+1).

However, when I cat /dev/my_inc, I only seem to be getting the first half of the myinc_value message buffer back in user space.

  • If myinc_value is 48, cat /dev/my_inc yields 4.

  • If myinc_value is 489324, cat /dev/my_inc yields 489.

However, bytes_read indicates the entire message was copied into user space. Here is the output from dmesg:

[54471.381170] my_inc opened with initial value 489324 = 489324.
[54471.381177] my_inc device_read() called with value 489325 and msg 489324.
[54471.381179] my_inc device_read() read 4.
[54471.381182] my_inc device_read() read 8.
[54471.381183] my_inc device_read() read 9.
[54471.381184] my_inc device_read() read 3.
[54471.381185] my_inc device_read() read 2.
[54471.381186] my_inc device_read() read 5. my_inc device_read() returning 7.
[54471.381192] my_inc device_read() called with value 489325 and msg 489325.

And when called from the shell:

root@rbst:/home/rob/myinc_mod# cat /dev/my_inc
489

And the source:

// Read from the device
//
static ssize_t device_read(struct file * filp, char * buffer, 
    size_t length, loff_t * offset)
{
    char c;
    int bytes_read = 0;
    int value = myinc_value + 1;

    printk(KERN_INFO "my_inc device_read() called with value %d and msg %s.\n", 
        value, msg);

    // Check for zero pointer
    if (*msg_ptr == 0) 
    {
        return 0;
    }
    // Put the incremented value in msg 
    snprintf(msg, MAX_LENGTH, "%d", value);

    // Copy msg into user space
    while (length && *msg_ptr) 
    {
        c = *(msg_ptr++);
        printk(KERN_INFO "%s device_read() read %c. ", DEV_NAME, c);
        if(put_user(c, buffer++))
        {
            return -EFAULT;
        }
        length--;
        bytes_read++;
    }

    // Nul-terminate the buffer
    if(put_user('\0', buffer++))
    {
        return -EFAULT;
    }
    bytes_read++;
    printk("my_inc device_read() returning %d.\n", bytes_read);
    return bytes_read;
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

眼泪淡了忧伤 2024-09-05 12:22:50

可能 put_user() 被定义为一个宏,因此后增量运算符

if(put_user(c, buffer++))

搞砸了 - 尽管我不明白它如何解释您所看到的内容。

无论如何,使用 copy_to_user() 复制整个消息会更方便、更高效。

It may be that put_user() is defined as a macro so that the post increment operator in

if(put_user(c, buffer++))

is screwing up - though I don't see how it explains what you are seeing.

Anyway it would be more convenient and more efficient to use copy_to_user() to copy the whole msg.

昵称有卵用 2024-09-05 12:22:50

它只显示 1 个字节的原因是因为您在将 msg_ptr 设置为等于 c 之前递增了 msg_ptr。它需要是 c = *msg_ptr++;或 c = *msg_ptr; msg_ptr++;这样增量就发生在赋值之后

The reason it only shows 1 byte is because you are incrementing the msg_ptr before setting it equal to c. It needs to be c = *msg_ptr++; or c = *msg_ptr; msg_ptr++; so that the increment happens after the assignment

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文