为啥在尝试“cat”我的 char 设备驱动程序时收到错误消息?

Posted

技术标签:

【中文标题】为啥在尝试“cat”我的 char 设备驱动程序时收到错误消息?【英文标题】:Why am I getting an error message when trying to "cat" my char device driver?为什么在尝试“cat”我的 char 设备驱动程序时收到错误消息? 【发布时间】:2017-11-13 16:21:56 【问题描述】:

我为 Linux 编写了一个简单的字符设备驱动程序。

这是一个简单的消息存储/检索系统,消息存储在内核空间中。

我应该可以这样做:

echo "message 1" > /dev/mydevice

然后用

检索消息
cat /dev/mydevice

消息存储在队列中。

当我尝试检索硬编码用于测试的消息(消息是“hello”)时,我得到以下命令行输出:

cat /dev/mydevice
hellocat: /dev/mydevice: Resource temporarily unavailable

所以我按预期收到了 hello 消息,但显然我做的不是很正确。

这是处理设备读取的函数。

static ssize_t device_read(struct file *filp, char *buffer,
               size_t length, loff_t * offset) 
  unsigned long result;
  int message_size;
  struct message_list* message = pop_message(&global_message_list);

  if (!message) return -EAGAIN;

  message_size = message -> message_length;

  result = copy_to_user(buffer, message -> message, message_size);

  printk(KERN_ALERT "res: %lu, msg_size: %d, len: %d\n", result, message_size, length);
  if (result == 0) return message_size;
  else return message_size - result;

【问题讨论】:

我认为cat 一直在尝试读取,直到到达 EOF(read 返回 0)。在这种情况下,一旦您没有消息,您会立即转到EAGAIN。尝试在队列中的"hello" 之后硬编码一条空消息,看看是否有效? (如果这是实际问题,那可能不是最好的解决方案,但它更容易测试;一方面,很难以这种方式以线程安全的方式将一条消息准确地返回给每个读者。) 在没有更多消息时返回 EAGAIN 是我的作业要求的一部分。鉴于我需要为 EOF 返回 0,我对如何克服这个问题感到有些困惑。 @DanielH 也是,这是否意味着 cat 会多次调用我的读取函数?我认为读取传统上返回读取的字节数。 如果将队列硬编码为"hello",然后是"",那么第一次读取将得到hello,第二次将得到一个长度为0的空字符串,表示EOF,而第三个将获得 EAGAIN。 是的,read 返回读取的字节数。但这可能不是整个文件,原因有两个: 1. 很明显,如果传入read 的缓冲区小于可供读取的字节数,那么您没有全部内容,需要调用@ 987654334@ 再次获得休息。 2. 您reading 的文件可能是管道、TTY 或其他无法同时提供所有数据的设备;在这种情况下,read 将返回任何可用的数据,而下一个将阻塞,直到有更多数据为止。 【参考方案1】:

cat 实用程序对每个文件多次调用 read,直到到达 EOF(即 signified by read returning 0)。

这是因为并非所有数据都可以立即获得。如果文件大于cats 内部缓冲区,当然需要多次调用read 才能获取完整数据。即使read 返回的字节数小于缓冲区的长度,它也需要再次调用read,以防以后有更多数据可用(如果输入是 TTY 或管道,则可能是这种情况)。因此,您需要返回 0 才能让 cat 认为它位于文件末尾并停止读取。

(有关cat 工作原理的更多详细信息,您可以查看the source code 和safe_read function。)

处理此问题的一种简单方法是在每个“真实”消息之后在队列中放置一条长度为零的消息,以便下一个read 将返回 EOF。但是,如果您同时有多个阅读器,这将无法正常工作;在这种情况下,一个阅读器可能会阅读一条消息,然后另一个阅读器阅读 EOF,然后第一个阅读器阅读另一条消息,这样一个阅读器会收到两条消息,另一个阅读器会收到零。是否让您的设备线程安全取决于您和/或您的讲师。¹

这也表明您的代码存在另一个潜在问题,您只处理了部分问题:如果您的消息大于传递给read 的缓冲区,则丢弃其余消息而不是保存它以供下一个@ 987654336@。同样,这可能是一个可以接受的缺点,或者不是。


¹我不确定是否可以使它成为线程安全的;这取决于您对不同阅读器的区分程度,而我对内核代码或编写字符设备的了解还不够,无法说明这是否可能。

【讨论】:

以上是关于为啥在尝试“cat”我的 char 设备驱动程序时收到错误消息?的主要内容,如果未能解决你的问题,请参考以下文章

为啥我在设备或模拟器上运行我的应用程序时屏幕是黑色的

为啥我的 iPhone 应用程序的发布版本在安装后第一次运行时会在设备上崩溃?

获取 cat:/dev/mydevice1:尝试在驱动程序中通信时将无效参数作为输出

为啥我的简单反向 char* 不起作用?

当我使用“cat”写入字符设备时,“cat: write error: No space left on device”

为啥我无法在 Android 设备上接收来自 GCM 的消息