2009-07-26 19 views
73

Conozco todas las discusiones sobre por qué uno no debe leer/escribir archivos desde kernel, sino cómo usar/proc o netlink para hacerlo. Quiero leer/escribir de todos modos. También he leído Driving Me Nuts - Things You Never Should Do in the Kernel.¿Cómo leer/escribir archivos dentro de un módulo kernel de Linux?

Sin embargo, el problema es 2.6.30 no exporta sys_read(). Más bien está envuelto en SYSCALL_DEFINE3. Así que si uso que en mi módulo, consigo siguientes advertencias:

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

Obviamente insmod no se puede cargar el módulo de enlace porque no se produce correctamente.

Preguntas:

  • Cómo leer/escribir dentro del núcleo después de 2.6.22 (donde sys_read()/sys_open() no se exportan)?
  • En general, ¿cómo utilizar las llamadas al sistema incluidas en macro SYSCALL_DEFINEn() desde dentro del kernel?

Respuesta

94

Debe tener en cuenta que debe evitar las E/S de archivos cuando sea posible. La idea principal es ir "un nivel más profundo" y llamar VFS level functions en lugar del controlador de llamada al sistema directamente:

Incluye:

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

apertura de un archivo (similar a abrir):

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

Cierre un archivo (similar al cierre):

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

Lectura de datos de un archivo (similar a 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; 
} 

escritura de datos en un archivo (similar a 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; 
} 

sincronización cambia un archivo (similar a fsync):

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

[Editar] Originalmente, Propuse usar file_fsync, que ya no está en versiones de kernel más nuevas. Gracias al pobre chico que sugiere el cambio, pero cuyo cambio fue rechazado. La edición fue rechazada antes de poder revisarla.

+2

Gracias. Estaba pensando en hacer algo similar al replicar la funcionalidad sys_read/sys_open. Pero esto es de gran ayuda. Una curiosidad, ¿hay alguna manera de usar las llamadas al sistema declaradas usando SYSCALL_DEFINE? – Methos

+5

Probé este código en kernel 2.6.30 (Ubuntu 9.04) y al leer el archivo falla el sistema. ¿Alguien experimentó el mismo problema? –

+0

@Enrico Detoma? Oh wow. ¿Hay alguna forma de que me puedas dar el módulo que usaste? Nunca he visto eso antes? – dmeister

Cuestiones relacionadas