我正在尝试为char *分配一些内存,如下所示。
static ssize_t memo_write(struct file *filp, const char __user *buf,
size_t count, loff_t *f_pos){
ssize_t retval = -ENOMEM;
printk("write function\n");
if((data = kmalloc(strlen(buf), GFP_KERNEL)) == NULL)
printk("kmalloc fail\n");
if(copy_from_user(data, buf, strlen(buf))){
retval = -EFAULT;
goto out;
}
*f_pos += strlen(buf);
retval = strlen(buf);
out:
return retval;
}
在头文件中将“数据”声明为
char *data;
当我调用write函数时,没有到达'kmalloc fail'行,这使我相信kmalloc成功了,但是当我再次尝试从'data'变量中读取数据时,则没有显示数据。
更令人困惑的是,如果我完全摆脱了kmalloc位,则可以从驱动程序读取数据。尽管问题出在那儿,但随后又加载了其他数据,因为我没有机会对其进行memset()处理。
我是否正确使用kmalloc?大概不是。我应该怎么做?
另外,我的读取功能如下。
static ssize_t memo_read(struct file *f, char __user *buf,
size_t count, loff_t *f_pos){
ssize_t retval = 0;
printk("read function\n");
printk("data = %s\n", data);
if(*f_pos >= strlen(data)){
printk("EOF\n");
goto out;
}
if(copy_to_user(buf, data, strlen(data))){
retval = -EFAULT;
goto out;
}
printk("copy_to_user success\n");
*f_pos += strlen(data);
retval = strlen(data);
out:
return retval;
}
谢谢。
最佳答案
您应该在用户空间指针上使用strlen_user()
而不是strlen()
-您应该只调用一次,并保持结果不变(否则,您可能会利用内核,因为第二个用户空间线程可能会在您使用时更改缓冲区努力)。
另外,您可以使用strncpy_from_user()
。
除此之外,kmalloc
看起来还可以。
(但实际上,正如ephemient所说,您应该重新考虑整个方法,并使用count
参数而不是将输入视为字符串)。
由于您不能依赖于写入文件的数据为以n结尾的字符串,因此您需要在data_len
旁边保留一个data
length参数。然后,您的read
/write
实现将遵循以下原则:
static char *data = NULL;
static size_t data_len;
static DEFINE_MUTEX(data_mutex);
static ssize_t memo_read(struct file *f, char __user *buf, size_t count, loff_t *f_pos
{
ssize_t retval = 0;
char *start;
mutex_lock(&data_mutex);
if (!data)
{
retval = -EINVAL; /* Or whatever you want to do here... */
goto out;
}
if (*f_pos >= data_len)
goto out; /* EOF */
start = data + *f_pos;
retval = data_len - *f_pos;
if (retval > count)
retval = count;
if (copy_to_user(buf, start, retval))
{
retval = -EFAULT;
goto out;
}
*f_pos += retval;
out:
mutex_unlock(&data_mutex);
return retval;
}
static ssize_t memo_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos)
{
ssize_t retval = -ENOMEM;
mutex_lock(&data_mutex);
if (data)
kfree(data);
data = kmalloc(count, GFP_KERNEL);
if (!data)
goto out;
if (copy_from_user(data, buf, count))
{
kfree(data);
retval = -EFAULT;
goto out;
}
*f_pos = count;
retval = count;
data_len = count;
out:
mutex_unlock(&data_mutex);
return retval;
}