我正在编写一个设备驱动程序。如果有人调用写操作,我希望它被推迟(使用tasklet或workqueue(。代码应该是这样的:
static ssize_t dev_write(struct file *filp, const char *buff, size_t len, loff_t *off) {
packed_work *the_task;
the_task = kzalloc(sizeof(packed_work), GFP_ATOMIC);
if (the_task == NULL) {
printk(KERN_ERR "%s: tasklet buffer allocation failuren", MODNAME);
return -1;
}
the_task->buffer = the_task;
the_task->buff = buff;
the_task->len = len;
INIT_WORK(&(the_task->the_work), (void*)deferred_write);
schedule_work(&the_task->the_work);
return len;
}
void deferred_write(struct work_struct *data) {
printk(“the text: %sn”, container_of(data, packed_work, the_work)->buff);
//copy_from_user(&(the_object->stream_content), container_of(data, packed_work, the_work)->buff, len);
kfree((void*)container_of(data,packed_work,the_work));
}
结构看起来像这样:
typedef struct _packed_work{
void *buffer;
const char *buff;
size_t len;
struct work_struct the_work;
} packed_work;
问题是内核崩溃了。它甚至在copy_from_user之前就崩溃了(这就是我评论它的原因(。在deferred_write((中,我可以打印字符串的长度,但不能打印字符串本身。是否因为缓冲区在用户空间内存中而出现问题?
我知道,作为一种变通方法,我可以复制任务结构中的用户缓冲区(使用函数write((中的copy_from_user(((,然后使用deferred_write((函数中的strcpy((。但我真的很想在deferred_write((中使用copy_from_user((。有可能吗?我能做什么?
即使有可能(肯定有办法(,用户进程也可能在deferred_write
运行之前更改了缓冲区的内容。请注意,用户程序经常在堆栈上分配这些缓冲区,因此当调用write
的函数返回并调用其他函数时,它们会被覆盖。
更糟糕的是:用户进程可能已经取消了缓冲区的映射,也可能已经退出。
因此,您不应该延迟读取缓冲区。您应该读取write
调用内部的缓冲区,而不是其他任何地方。