File write from linux kernel driver failed
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/fs.h>
stati开发者_StackOverflow中文版c int __init hello_start(void)
{
struct file* my_fd;
my_fd = filp_open ("/tmp/foobar", O_WRONLY | O_APPEND, 0);
if (IS_ERR (my_fd))
{
printk (KERN_ERR "Failed to open file. err: %d.\n", my_fd);
}
else
{
my_fd->f_op->write (my_fd, "some data", 10, &my_fd->f_pos);
}
printk(KERN_INFO "Loading hello module...\n");
return 0;
}
static void __exit hello_end(void)
{
printk(KERN_INFO "hello_end.\n");
}
module_init(hello_start);
module_exit(hello_end);
the above code is giving error -14 while writing in the file. what am I doing wrong here?
Here is the dmesg
output:
[19551.674999] Write returned: -14.
[19551.675004] Loading hello module...
The write
member of struct file_operations
(in include/linux/fs.h
) is declared like this:
ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
Note the __user
token on the second argument, which tells you it is expecting a user-space pointer. When you call it like you did from the kernel, you are passing a kernel-space pointer; hence your memory fault.
@ShinTakezou's link to the "acct.c" code is what you want to look at; in particular, the calls to set_fs
to trick the kernel into using its own data segment as the "user" data segment.
First, do not ignore warnings: your %d
is not good for my_fd
.
Then, I think in general it is not a good idea to do file I/O from kernel, except in "special" cases.
I've tried with O_CREAT and everything is fine except if the file already exists. Everything else (in particular O_WRONLY | O_APPEND
) gave me no chance.
I believe that in order to make file I/O in kernel "as" in user space requires to know more stuffs, and it is likely a bit tricky (or "dangerous").
However try to look at the acct.c code.
精彩评论