webentwicklung-frage-antwort-db.com.de

Datei-E/A in einem Linux-Kernelmodul

Ich schreibe ein Linux-Kernelmodul, das Dateien öffnen und lesen muss. Was ist der beste Weg, um das zu erreichen?

19
mipadi

Kann ich fragen, warum Sie versuchen, eine Datei zu öffnen?

Ich verfolge gerne die Linux-Entwicklung (aus Neugier, ich bin kein Kernel-Entwickler, ich mache Java), und ich habe die Diskussion über diese Frage schon einmal gesehen. Ich konnte eine LKML-Nachricht darüber finden und erwähnte im Grunde genommen, dass es normalerweise eine schlechte Idee ist. Ich bin mir fast sicher, dass LWN im letzten Jahr darüber berichtet hat, aber ich habe Probleme, den Artikel zu finden.

Wenn es sich um ein privates Modul handelt (z. B. um eine benutzerdefinierte Hardware, die nicht verteilt wird), können Sie dies tun. Ich habe jedoch den Eindruck, dass Ihr Code möglicherweise nicht an die Hauptleitung gesendet wird akzeptiert sein.

Evan Teran erwähnte sysfs, was für mich eine gute Idee ist. Wenn Sie wirklich härtere benutzerdefinierte Aufgaben erledigen müssen, können Sie immer neue ioctrls erstellen.

BEARBEITEN:

OK, ich habe den Artikel gefunden, den ich gesucht habe. Er stammt aus Linux Journal . Es erklärt, warum es im Allgemeinen eine schlechte Idee ist, solche Dinge zu tun.

31
MBCook

angenommen, Sie können Zeiger auf die relaventen Funktionen abrufen, die auf die Systemaufrufe von open/read/close verweisen.

mm_segment_t fs = get_fs();
set_fs(KERNEL_DS);

fd = (*syscall_open)(file, flags, mode);
if(fd != -1) {
    (*syscall_read)(fd, buf, size);
    (*syscall_close)(fd);
}
set_fs(fs);

sie müssen jedoch die von mir gezeigten "syscall_*" -Funktionszeiger erstellen. Ich bin mir sicher, dass es einen besseren Weg gibt, aber ich glaube, dass dies funktionieren würde.

9
Evan Teran

Wenn Sie Dateien von einem Kernelmodul lesen/schreiben müssen, machen Sie im Allgemeinen architektonisch etwas falsch.

Es gibt Mechanismen (zum Beispiel netlink - oder registrieren Sie einfach ein Zeichengerät), mit denen ein Kernelmodul mit einem Userspace-Hilfsprozess kommunizieren kann. Dieser Userspace-Hilfsprozeß kann tun, was er will.

Sie können auch einen Systemaufruf (oder ähnliches) implementieren, um einen im Userspace geöffneten Dateideskriptor zu verwenden und vom Kernel aus zu lesen/schreiben.

Dies wäre wahrscheinlich sinnvoller, als zu versuchen, Dateien im Kernelspeicher zu öffnen.

Es gibt einige andere Dinge, die bereits Dateien aus dem Kernel-Space öffnen, man könnte sie sich anschauen (der Loop-Treiber kommt in den Sinn?).

2
MarkR

Informationen zu sys_call_open finden Sie auch in diesem Linux Kernel Module Programing Guide .

1
VonC

Das/proc-Dateisystem ist auch für den privaten Gebrauch geeignet und einfach.
http://www.linuxtopia.org/online_books/Linux_Kernel_Module_Programming_Guide/x773.html

1
Denes Tarjan

Alle Kernel-Entwickler sagen, dass die Datei-E/A aus dem Kernel-Speicher schlecht ist (insbesondere, wenn Sie über ihre Pfade auf diese Dateien verweisen), aber der Mainstream-Kernel tut dies, wenn Sie Firmware laden. Wenn Sie nur aus Dateien lesen müssen, verwenden Sie die

kernel_read_file_from_path(const char *path, void **buf, loff_t *size, loff_t max_size, enum kernel_read_file_id id)

funktion, die vom Firmware-Ladeprogrammcode verwendet wird und in include/linux/fs.h deklariert ist. Diese Funktion liefert im Fehlerfall einen negativen Wert.

Ich bin mir nicht wirklich sicher, was die Variable id am Ende angeht. Wenn Sie sich den Code ansehen, der nicht wirklich verwendet wird, setzen Sie einfach etwas wie READING_FIRMWARE dort ein (keine Anführungszeichen).

buf ist nicht nullterminiert, sondern bezieht sich auf die Größe in size. Wenn eine Nullterminierung erforderlich ist, erstellen Sie eine Zeichenfolge mit size + 1 Bytes Länge und kopieren Sie sie oder schreiben Sie die Funktion kernel_read_file() (verwendet von kernel_read_file_from_path(), definiert in fs/exec.c) neu und fügen Sie eine zu i_size hinzu, wo Speicher zugewiesen wird. (Wenn Sie dies tun möchten, können Sie die Funktion kernel_read_file() in Ihrem Modul mit einem anderen Funktionsnamen neu definieren, um zu vermeiden, dass der gesamte Kernel geändert wird.)

Wenn Sie in Dateien schreiben müssen, gibt es eine Funktion kernel_write() (analog zu kernel_read(), die von kernel_read_file() und damit auch von kernel_read_file_from_path() verwendet wird), aber es gibt keine Funktion kernel_write_file() oder kernel_write_file_from_path(). Sie können den Code in der fs/exec.c-Datei im Linux-Kernel-Quelltextbaum anzeigen, in dem kernel_read_file() und kernel_read_file_from_path() definiert sind, um Ihre eigenen kernel_write_file()- und kernel_write_file_from_path()-Funktionen zu schreiben, die Sie in Ihr Modul aufnehmen können.

Und wie immer können Sie mit dieser Funktion den Inhalt einer Datei in einem Zeichenzeiger anstelle eines leeren Zeigers speichern, indem Sie ihn umwandeln.

0
Billy