【发布时间】:2017-12-18 06:58:41
【问题描述】:
我已经为我的内核模块实现了一个字符设备,并为它实现了一个读取功能。读取函数调用copy_to_user 将数据返回给调用者。我最初以阻塞方式(使用wait_event_interruptible)实现了读取功能,但即使我以非阻塞方式实现读取,问题也会重现。我的代码在 MIPS 处理器上运行。
用户空间程序打开 char 设备并读入分配在堆栈上的缓冲区。
我发现偶尔copy_to_user 将无法复制任何字节。此外,即使我将 copy_to_user 替换为对 memcpy 的调用(仅用于检查......我知道这不是正确的做法),然后立即打印出目标缓冲区,我明白了memcpy 未能复制任何字节。
我不确定如何进一步调试 - 我如何确定内存没有被复制的原因?会不会是进程上下文不对?
编辑:下面是一些伪代码,概述了代码当前的样子:
用户模式(重复运行):
char buf[BUF_LEN];
FILE *f = fopen(char_device_file, "rb");
fread(buf, 1, BUF_LEN, f);
fclose(f);
内核模式:
char_device =
create_char_device(char_device_name,
NULL,
read_func,
NULL,
NULL);
int read_func(char *output_buffer, int output_buffer_length, loff_t *offset)
{
int rc;
if (*offset == 0)
{
spin_lock_irqsave(&lock, flags);
while (get_available_bytes_to_read() == 0)
{
spin_unlock_irqrestore(&lock, flags);
if (wait_event_interruptible(self->wait_queue, get_available_bytes_to_read() != 0))
{
// Got a signal; retry the read
return -ERESTARTSYS;
}
spin_lock_irqsave(&lock, flags);
}
rc = copy_to_user(output_buffer, internal_buffer, bytes_to_copy);
spin_unlock_irqrestore(&lock, flags);
}
else rc = 0;
return rc;
}
【问题讨论】:
-
你的代码有问题,但你没有显示出来。
-
@Tsyvarev 添加了一些伪代码,希望它能充分说明代码所做的事情。不幸的是,我(还)无法将其缩小到一个小的、可复制的示例。
-
@YSK 你已经声明了两次
int rc。从int rc = copy_to_user(output_buffer, internal_buffer, bytes_to_copy);行中删除int。 -
与任何其他“可能阻止”函数一样,不应使用自旋锁调用
copy_to_user。 -
@Gaurav 好点 - 不幸的是我没有伪代码编译器:)
标签: c linux-kernel mips embedded-linux