从 Linux 内核驱动程序写入文件失败

发布于 2024-11-23 18:11:39 字数 816 浏览 1 评论 0原文

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/fs.h>

static 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);

上面的代码在写入文件时给出错误-14。我在这里做错了什么?

这是 dmesg 输出:

[19551.674999] Write returned: -14.
[19551.675004] Loading hello module...
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/fs.h>

static 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...

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

土豪我们做朋友吧 2024-11-30 18:11:39

struct file_operationswrite 成员(在 include/linux/fs.h 中)声明如下:

 ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);

注意 __user第二个参数上的 code> 标记,告诉您它需要一个用户空间指针。当您像从内核中那样调用它时,您正在传递一个内核空间指针;因此是你的记忆错误。

@ShinTakezou 到“acct.c”代码的链接就是您想要查看的内容;特别是,调用 set_fs 来欺骗内核使用自己的数据段作为“用户”数据段。

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.

橪书 2024-11-30 18:11:39

首先,不要忽略警告:您的 %d 不适合 my_fd

然后,我认为一般来说从内核进行文件 I/O 不是一个好主意,除非在“特殊”情况下。

我尝试过 O_CREAT ,一切都很好,除非文件已经存在。其他一切(特别是O_WRONLY | O_APPEND)都没有给我机会。

我相信,为了使内核中的文件 I/O 与用户空间中的“一样”,需要了解更多的东西,而且这可能有点棘手(或“危险”)。

但是尝试查看 acct.c 代码。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文