109 votes

Comment lire / écrire des fichiers dans un module de noyau Linux?

Je sais que de toutes les discussions au sujet de pourquoi il ne faut pas lire/écrire des fichiers à partir du noyau, au lieu de cela comment utiliser /proc ou netlink pour le faire. Je veux lire/écrire de toute façon. J'ai aussi lu Me rend fou - des Choses que Vous ne Devez Faire dans le Noyau.

Cependant, le problème est 2.6.30 ne pas exporter sys_read(). C'est plutôt enveloppé dans SYSCALL_DEFINE3. Donc, si je utiliser dans mon module, je reçois des avertissements suivants:

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

Évidemment insmod ne peut pas charger le module que la liaison ne se fait pas correctement.

Questions:

  • Comment lire/écrire dans le noyau après 2.6.22 (où sys_read()/sys_open() ne sont pas exportées)?
  • En général, comment utiliser les appels système enveloppé dans de la macro SYSCALL_DEFINEn() de dans le noyau?

132voto

dmeister Points 11529

Vous devez être conscient que vous devez éviter d'e/S de fichier lorsque cela est possible. L'idée principale est de "monter d'un niveau plus profond" et appelez VFS fonctions de niveau au lieu de le syscall gestionnaire directement:

Comprend:

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

L'ouverture d'un fichier (similaire à "ouvrir"):

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

La fermeture d'un fichier (similaire):

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

La lecture des données à partir d'un fichier (similaire à 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;
}   

L'écriture de données dans un fichier (similaire à 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 synchronisation des modifications d'un fichier (similaire à fsync):

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

[Modifier] à l'Origine, j'ai proposé à l'aide de file_fsync, qui est allé dans les nouvelles versions du noyau. Merci pour le pauvre gars qui suggère le changement, mais dont le changement a été rejetée. Le montage a été rejetée avant que je puisse l'examiner.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X