¿Cómo leer / escribir archivos dentro de un módulo kernel de Linux?

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: Cosas que nunca debes hacer en el Kernel .

Sin embargo, el problema es 2.6.30 no exporta sys_read() . Más bien está envuelto en SYSCALL_DEFINE3 . Entonces, si uso eso en mi módulo, recibo las siguientes advertencias:

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

Obviamente, insmod no puede cargar el módulo porque la vinculación no ocurre correctamente.

Preguntas:

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

Debe tener en cuenta que debe evitar E / S de archivos cuando sea posible. La idea principal es ir “un nivel más profundo” y llamar directamente a las funciones de nivel de VFS en lugar del manejador de syscall:

Incluye:

 #include  #include  #include  #include  

Abrir 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 a cerrar):

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

Lectura de datos de un archivo (similar a pread):

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

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

La 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 se ha ido 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.