2011-07-14 53 views
2
#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を与えています。私はここで何が間違っていますか?ここでLinuxカーネルドライバからのファイル書き込みが失敗しました。

dmesg出力されます。

[19551.674999] Write returned: -14. 
[19551.675004] Loading hello module... 
+0

おそらく、エラーコード-14が何を意味しているかを調べることから始めようとします。 –

+0

@JSBangs、14はEFAULTですが、これは私がなぜそれが来るのか分からないことです。 –

答えて

5

struct file_operationsinclude/linux/fs.h中)のwriteメンバーは、このように宣言されています

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

注それはユーザ空間ポインタを期待しているあなたに伝え第二引数、上__userトークン。カーネルのように呼び出すときは、カーネルスペースポインタを渡しています。あなたの記憶障害。

@ ShinTakezouの "acct.c"コードへのリンクは、あなたが見たいものです。特に、set_fsへの呼び出しでは、カーネルが独自のデータセグメントを「ユーザー」データセグメントとして使用するようになります。

+0

+1エラーコードを調べるのもいい考えです: '$ grep 14 /usr/src/linux-headers-2.6.38-10/include/asm-generic/errno-base.h #define \t EFAULT \t/*不良アドレス*/' – user786653

+0

ありがとうございました。私はユーザー空間のバッファポインタを使用し、それは働いた。 :) –

+1

最近、 'set_fs()'に 'vfs_read/write'を安全にラップする' kernel_read() 'と' kernel_write() 'ヘルパーがあります。 (直接のファイルシステムアクセスではなく、sysfsなどを使用したいという側面の問題は無視してください)。 – domen

2

まず、警告を無視しないでください:あなたの%dmy_fdのために良いではありません。

次に、「特別な」ケースを除いて、カーネルからファイルI/Oを実行するのは良い考えではないと思います。

私はO_CREATで試してみましたが、ファイルが既に存在する場合を除いてすべて正常です。他のすべて(特にO_WRONLY | O_APPEND)は私にチャンスを与えませんでした。

私は、カーネルのファイルI/Oをユーザー空間で "as"にするためには、より多くのものを知る必要があり、それはやや難しいかもしれないと信じています。

しかし、acct.cコードを見てみてください。

+0

+1ありがとうございます。 acct.cコードは役に立ちましたが、O_CREATフラグを追加しても問題は解決されませんでした。しかし、ユーザー空間のバッファを使用して解決しました。 –