我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)写入任何内容并且我们不需要知道其中的位置(至少在这个例子中),为什么我们需要?
read因为两者都是由用户空间程序报告的,分别作为调用/的最后一个参数传递write。如果你用手指解释,它会echo说“我有一个 6 字节长的缓冲区,我想将它写入设备”,并cat告诉系统“我有一个 128k 的缓冲区,我想尽可能多地读入它在设备上”。读取到结束循环的典型“整个文件”如下所示:
那些。文件结束符号是
read返回0的。在问题的情况下,这永远不会发生,即 文件以同样的方式变成无限的,例如,/dev/zero或/dev/urandom;并cat挂在同一个周期...loff_t是设备提供的虚拟文件中的偏移量。如果设备没有存储任何内部状态,那么需要重点关注它,以免每次返回相同的数据。例如,在此示例中,将其解释为缓冲区偏移量是合理的。鉴于上述情况,读取函数将如下所示: