如何解决当直接从缓冲区复制值时,strscp 将永远循环
问题
我正在学习 Linux 内核模块开发并试图理解为什么当缓冲区中的值被复制时 strscp 会无限循环。
代码
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/miscdevice.h>
#include <linux/module.h>
#include <linux/proc_fs.h>
#include <linux/uaccess.h>
#include <linux/slab.h>
#include <linux/string.h>
#define LEN 13
#define ID "ABCDEF2103a5"
static char buffer[LEN];
static ssize_t hello_write(struct file *file,const char *buf,size_t count,loff_t *ppos)
{
ssize_t len;
if (count != LEN)
return -EINVAL;
// This loops forever when 0 returned!
strscpy(buffer,buf,LEN);
return len;
}
static const struct file_operations file_ops = {
.owner = THIS_MODULE,.write = hello_write,};
static struct miscdevice misc_dev = {
MISC_DYNAMIC_MINOR,"check",&file_ops
};
当值“ABCDEF2103a5”(或任何相同长度的值)通过 echo ABCDEF2103a5 > /dev/check
传递给模块时,它只会连续打印该值。
以下是 dmesg -wH
的输出:
[ +0.000002] ABCDEF2103a5
[ +0.000003] ABCDEF2103a5
[ +0.000003] ABCDEF2103a5
[ +0.000002] ABCDEF2103a5
[ +0.000003] ABCDEF2103a5
[ +0.000002] ABCDEF2103a5
[ +0.000003] ABCDEF2103a5
[ +0.000002] ABCDEF2103a5
[ +0.000003] ABCDEF2103a5
[ +0.000003] ABCDEF2103a5
[ +0.000002] ABCDEF2103a5
[ +0.000008] ABCDEF2103a5
它占用 CPU 100%。为了让它停止,我必须找到 shell 的 PID 并杀死它。
当返回 0 时(len 被赋值为 0 或 return 0
),没有打印任何东西并且 bash 挂起。
当返回其他值(非 0)时,bash: echo: write error:...
会抛出某种形式的错误消息,但不会挂起。
应该返回什么值?我们不能只做return;
。
工作正常
完整的功能代码,首先将缓冲区复制到临时数组,然后将其复制到全局变量。
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/miscdevice.h>
#include <linux/module.h>
#include <linux/proc_fs.h>
#include <linux/uaccess.h>
#include <linux/slab.h>
#include <linux/string.h>
#define LEN 13
#define ID "ABCDEF2103a5"
static char buffer[LEN];
static ssize_t hello_write(struct file *file,loff_t *ppos)
{
ssize_t len;
char *msg = kmalloc (count + 1,GFP_KERNEL);
if (!msg)
return -ENOMEM;
if (count != LEN)
return -EINVAL;
len = simple_write_to_buffer(msg,count,ppos,count);
if ( strncmp(msg,ID,LEN-1 ) != 0 )
return -EINVAL;
// Copied from the temporary variable
// which works fine.
strscpy(buffer,msg,LEN);
return len;
}
static const struct file_operations file_ops = {
.owner = THIS_MODULE,&file_ops
};
上面的评论部分没有评论。在这里,缓冲区首先被复制到临时变量。使用 strscpy
复制临时变量的值,效果很好。
解决方法
我相信@Tsyvarev 评论了正确答案。
“至于循环,您声明了 ssize_t len 变量,但从未对其进行初始化。可能它是 0,因此您的 write 方法始终返回 0,这被用户空间解释为“没有写入字节”和用户部分一遍又一遍地重复写作。”
重构后的代码是:
static ssize_t hello_write(struct file *file,const char *buf,size_t count,loff_t *ppos)
{
ssize_t len;
ssize_t copy_len;
char *msg = kmalloc(count + 1,GFP_KERNEL);
if (!msg)
return -ENOMEM;
if (count != LEN)
goto einval;
len = simple_write_to_buffer(msg,count,ppos,buf,count);
if (len <= 0) {
kfree(msg);
return len;
}
if (strncmp(msg,ID,LEN-1) != 0)
goto einval;
copy_len = strscpy(buffer,strim(msg),LEN);
if (copy_len < 0) {
kfree(msg);
return copy_len;
}
return len;
einval:
kfree(msg);
return -EINVAL;
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。