RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 966005
Accepted
Антон
Антон
Asked:2020-04-05 23:20:49 +0000 UTC2020-04-05 23:20:49 +0000 UTC 2020-04-05 23:20:49 +0000 UTC

字符驱动程序中 read() 函数的奇怪行为

  • 772

我read()的角色驱动程序功能

static ssize_t my_driver_read(struct file *filp, char *buf, size_t count, loff_t *f_pos)
{
    printk(KERN_ALERT "Function read() works and received %zu characters\n", count);

    if (copy_to_user(buf, my_driver_buf, count)) {
        printk(KERN_ALERT "Error in function copy_to_user()\n");
        return -EFAULT;
    }

    *f_pos += count;
    return count; 
}

好吧,一个功能write()以防万一

static ssize_t my_driver_write(struct file *filp, const char *buf, size_t count, loff_t *f_pos)
{
    printk(KERN_ALERT "Function write() works and received %zu characters\n", count);

    if (copy_from_user(my_driver_buf, buf, count)) {
        printk(KERN_ALERT "Error in function copy_from_user()\n");
        return -EFAULT;
    }

    *f_pos += count;
    return count;
}

我的缓冲区被声明为全局的

static char my_driver_buf[140000]; 

这些函数的实际问题(由file_operations字符驱动程序中的结构成员指出):

当我编写这样一个命令strace echo hello > /dev/my_driver(设备文件)时,我得到以下输出(修剪到最后几行)

write(1, "hello\n", 6)                  = 6
close(1)                                = 0
close(2)                                = 0
exit_group(0)                           = ?
+++ exited with 0 +++

而当我写这样一个命令strace cat /dev/my_driver时,输出是这样的(从上面和下面截掉文字)

read(3, "hello\n\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 131072) = 131072
write(1, "hello\n\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 131072hello
) = 131072
read(3, "hello\n\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 131072) = 131072
write(1, "hello\n\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 131072hello
) = 131072
read(3, "hello\n\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 131072) = 131072
write(1, "hello\n\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 131072hello
) = 131072

(重复直到我按下 Ctrl+C)

问题正在酝酿:

1)为什么count函数中的变量write()等于6(hello\n),而当我调用函数时read(),count它等于131072(hello\n\0\0\0....),而不是6?

2)为什么函数read()进入循环并再次被调用,虽然我写return count;在函数的末尾read(),这是最好的选择(所有数据都被接收)?

loff_t *f_pos3)如果我们仍然不向文件(если я правильно понимаю, то мы работаем с буфером пользовательского пространства, который предоставляет ядро и с буфером, который мы сами создаем, в нашем случае - my_driver_buf)写入任何内容并且我们不需要知道其中的位置(至少在这个例子中),为什么我们需要?

linux
  • 1 1 个回答
  • 10 Views

1 个回答

  • Voted
  1. Best Answer
    Fat-Zer
    2020-04-06T10:47:48Z2020-04-06T10:47:48Z

    1)为什么count函数中的变量write()等于6(hello\n),而当我调用函数时read(),count它等于131072(hello\n\0\0\0....),而不是6?

    read因为两者都是由用户空间程序报告的,分别作为调用/的最后一个参数传递write。如果你用手指解释,它会echo说“我有一个 6 字节长的缓冲区,我想将它写入设备”,并cat告诉系统“我有一个 128k 的缓冲区,我想尽可能多地读入它在设备上”。

    2)为什么函数read()进入循环并再次被调用,虽然我写return count;在函数的末尾read(),这是最好的选择(所有数据都被接收)?

    读取到结束循环的典型“整个文件”如下所示:

    char buf[BUF_SZ];
    
    do {
      ssize_t sz = read(fd, buf,BUF_SZ);
      if (sz<0) {
        perror("read failed");
        exit(EXIT_FAILURE);
      } else if (sz==0) {
        break
      } else {
        processData(buf);
      }
    } while (1);
    

    那些。文件结束符号是read返回0的。在问题的情况下,这永远不会发生,即 文件以同样的方式变成无限的,例如,/dev/zero或/dev/urandom;并cat挂在同一个周期...

    loff_t *f_pos3)如果我们仍然不向文件(если я правильно понимаю, то мы работаем с буфером пользовательского пространства, который предоставляет ядро и с буфером, который мы сами создаем, в нашем случае - my_driver_buf)写入任何内容并且我们不需要知道其中的位置(至少在这个例子中),为什么我们需要?

    loff_t是设备提供的虚拟文件中的偏移量。如果设备没有存储任何内部状态,那么需要重点关注它,以免每次返回相同的数据。例如,在此示例中,将其解释为缓冲区偏移量是合理的。


    鉴于上述情况,读取函数将如下所示:

    static ssize_t my_driver_read(struct file *filp, char *buf, size_t count, loff_t *f_pos)
    {
        printk(KERN_ALERT "Function read() works and received %zu characters\n", count);
    
        if (*f_pos >= sizeof (my_driver_buf)) {
          printk(KERN_DEBUG "Trying to read beyond buffer end, returning 0 to indicate EOF\n");
          return 0;
        } else if (*f_pos+count > sizeof (my_driver_buf)) {
          count = sizeof (my_driver_buf) - *f_pos;
          printk(KERN_DEBUG "count is bigger than buffer size, trimed it to %d\n", count);
        }
    
        if (copy_to_user(buf, my_driver_buf+*f_pos, count)!=0) {
            printk(KERN_ALERT "Error in function copy_to_user()\n");
            return -EFAULT;
        }
    
        *f_pos += count;
        return count; 
    }
    
    • 2

相关问题

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    根据浏览器窗口的大小调整背景图案的大小

    • 2 个回答
  • Marko Smith

    理解for循环的执行逻辑

    • 1 个回答
  • Marko Smith

    复制动态数组时出错(C++)

    • 1 个回答
  • Marko Smith

    Or and If,elif,else 构造[重复]

    • 1 个回答
  • Marko Smith

    如何构建支持 x64 的 APK

    • 1 个回答
  • Marko Smith

    如何使按钮的输入宽度?

    • 2 个回答
  • Marko Smith

    如何显示对象变量的名称?

    • 3 个回答
  • Marko Smith

    如何循环一个函数?

    • 1 个回答
  • Marko Smith

    LOWORD 宏有什么作用?

    • 2 个回答
  • Marko Smith

    从字符串的开头删除直到并包括一个字符

    • 2 个回答
  • Martin Hope
    Alexandr_TT 2020年新年大赛! 2020-12-20 18:20:21 +0000 UTC
  • Martin Hope
    Alexandr_TT 圣诞树动画 2020-12-23 00:38:08 +0000 UTC
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5