2009-07-26 19 views
73

Kernel'den dosyaları neden okuması/yazmaması gerektiği ile ilgili tüm tartışmaları biliyorum, bunun yerine nasıl/proc veya netlink kullanacağımı. Yine de okumak/yazmak istiyorum. Ayrıca Driving Me Nuts - Things You Never Should Do in the Kernel'u da okudum.Linux çekirdek modülündeki dosyalar nasıl okunur/yazılır?

Ancak, sorun 2.6.23 sys_read() dışa aktarmıyor. Onun yerine SYSCALL_DEFINE3. Benim modülünde olduğu kullanırsanız Yani, şu uyarıları alıyorum: bağlama doğru olmaz çünkü

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

Açıkçası insmod modülü yüklemek mümkün değil.

Sorular:

  • Nasıl (sys_read()/sys_open() ihraç edilmemektedir) 2.6.22 sonra çekirdek içindeki okuma/yazma için?
  • Genelde, makro içinde SYSCALL_DEFINEn() içine sistem çağrıları nasıl çekilir?

cevap

94

Mümkün olduğunda dosya G/Ç'lerinden kaçınmanız gerektiğini unutmayın.

içerir:

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

(açmak benzer) bir dosya açma:

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; 
} 

ana fikir "bir seviye aşağıya" gidip doğrudan syscall işleyici yerine VFS level functions çağırmaktır Bir dosyayı kapatın (close to close):

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

Dosyadan veri okuma (prea'ya benzer) d) pwrite benzer bir dosyaya

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; 
} 

veri yazma():

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; 
} 

Eşzamanlama) fsync (benzer bir dosya değiştirir:

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

[Düzenleme] Başlangıçta, Daha yeni çekirdek sürümlerinde bulunan file_fsync'i kullanmayı önerdim. Değişimi öneren, ama değişimleri reddedilen zavallı adama teşekkürler. Düzenleme yapmadan önce düzenleme reddedildi.

+2

Teşekkür ederiz. Sys_read/sys_open işlevlerini çoğaltarak benzer bir şey yapmayı düşünüyordum. Ama bu harika bir yardım. Bir merak, SYSCALL_DEFINE kullanarak bildirilen sistem çağrılarını kullanmak için herhangi bir yolu var mı? – Methos

+5

Bu kodu çekirdek 2.6.30'da (Ubuntu 9.04) denedim ve dosyayı okumak sistem çöküyor. Aynı sorunu yaşayan var mı? –

+0

@Enrico Detoma? Vay canına. Bu bana kullandığınız modülü verebilmenin herhangi bir yolu var mı? Bunu daha önce hiç görmedin mi? – dmeister