strap loop forever when 当值直接从缓冲区复制时
strscp loop forever when when the value is copied direcly from the buffer
问题
我正在学习 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
占CPU100%。为了让它停止,我必须找到 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,
const char *buf, size_t count,
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, buf,
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,
.write = hello_write,
};
static struct miscdevice misc_dev = {
MISC_DYNAMIC_MINOR,
"check",
&file_ops
};
上面的评论部分未评论。在这里,缓冲区首先被复制到一个临时变量。使用 strscpy
复制临时变量的值,效果很好。
我相信@Tsyvarev 评论了正确答案。
”至于循环,你声明了ssize_t len 变量,但从未初始化它。可能是0,所以你的write方法总是returns 0,这是用户解释的space 因为“没有字节被写入”并且用户部分一次又一次地重复写入。
重构后的代码为:
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;
}
问题
我正在学习 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
占CPU100%。为了让它停止,我必须找到 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,
const char *buf, size_t count,
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, buf,
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,
.write = hello_write,
};
static struct miscdevice misc_dev = {
MISC_DYNAMIC_MINOR,
"check",
&file_ops
};
上面的评论部分未评论。在这里,缓冲区首先被复制到一个临时变量。使用 strscpy
复制临时变量的值,效果很好。
我相信@Tsyvarev 评论了正确答案。
”至于循环,你声明了ssize_t len 变量,但从未初始化它。可能是0,所以你的write方法总是returns 0,这是用户解释的space 因为“没有字节被写入”并且用户部分一次又一次地重复写入。
重构后的代码为:
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;
}