2009-07-26 233 views
73

我知道關於爲什麼不應該從內核讀取/寫入文件的所有討論,而是如何使用/ proc或netlink來做到這一點。無論如何,我想讀/寫。我也讀過 Driving Me Nuts - Things You Never Should Do in the Kernel如何在Linux內核模塊中讀取/寫入文件?

但是,問題是2.6.30不導出sys_read()。而是它包裹在SYSCALL_DEFINE3。所以,如果我在我的模塊中使用,我得到以下警告:

WARNING: "sys_read" [xxx.ko] undefined! 
WARNING: "sys_open" [xxx.ko] undefined! 

顯然insmod無法加載模塊,因爲連接不正確地發生。

問題:

  • 如何閱讀2.6.22(其中不出口sys_read()/sys_open())後的內核中/寫?
  • 一般來說,如何在內核中使用包含在宏SYSCALL_DEFINEn()中的系統調用?

回答

94

你應該知道,你應該儘可能地避免文件I/O。其主要思路是走「更深層次」,並呼籲VFS level functions,而不是直接在系統調用處理程序:

包括:

#include <linux/fs.h> 
#include <asm/segment.h> 
#include <asm/uaccess.h> 
#include <linux/buffer_head.h> 

開幕(類似打開文件)的文件:

struct file *file_open(const char *path, int flags, int rights) 
{ 
    struct file *filp = NULL; 
    mm_segment_t oldfs; 
    int err = 0; 

    oldfs = get_fs(); 
    set_fs(get_ds()); 
    filp = filp_open(path, flags, rights); 
    set_fs(oldfs); 
    if (IS_ERR(filp)) { 
     err = PTR_ERR(filp); 
     return NULL; 
    } 
    return filp; 
} 

關閉文件(類似於關閉):

void file_close(struct file *file) 
{ 
    filp_close(file, NULL); 
} 

從文件中讀取數據(與prea類似d):

int file_read(struct file *file, unsigned long long offset, unsigned char *data, unsigned int size) 
{ 
    mm_segment_t oldfs; 
    int ret; 

    oldfs = get_fs(); 
    set_fs(get_ds()); 

    ret = vfs_read(file, data, size, &offset); 

    set_fs(oldfs); 
    return ret; 
} 

將數據寫入到文件中(類似於PWRITE):

int file_write(struct file *file, unsigned long long offset, unsigned char *data, unsigned int size) 
{ 
    mm_segment_t oldfs; 
    int ret; 

    oldfs = get_fs(); 
    set_fs(get_ds()); 

    ret = vfs_write(file, data, size, &offset); 

    set_fs(oldfs); 
    return ret; 
} 

同步功能變化(類似於FSYNC)的文件:

int file_sync(struct file *file) 
{ 
    vfs_fsync(file, 0); 
    return 0; 
} 

[編輯]最初,我建議使用file_fsync,它在更新的內核版本中消失了。感謝這位可憐的人提出改變,但他們的改變被拒絕了。編輯在我審查之前被拒絕。

+2

謝謝。我正在考慮通過複製sys_read/sys_open功能來做類似的事情。但這是很大的幫助。好奇心,有什麼方法可以使用SYSCALL_DEFINE聲明的系統調用嗎? – Methos 2009-07-26 12:48:32