Gibt es unter Linux eine Systemebene/ein Skript, das das Öffnen von Dateien übernimmt?

Gibt es unter Linux eine Systemebene/ein Skript, das das Öffnen von Dateien übernimmt?

Gibt es unter Linux eine Ebene/ein Skript, das Programmanforderungen zum Öffnen von Dateien verarbeitet?

Wie wenn Sie einen Datei-Deskriptor in Bash öffnen: exec 3 <>/documents/foo.txtoder Ihr Texteditor öffnet/documents/foo.txt

Ich kann nicht glauben, dass ein Editor „einfach eine Datei öffnen“ kann, um selbstständig Lese-/Schreibzugriff zu haben.

Ich stelle mir das eher als eine Anfrage an eine „Schicht“ vor (init.d-Skript?), das zunächst nur eine bestimmte Anzahl von Dateien öffnen kann und das geöffnete Dateien mit ihren Zugriffsarten, den Prozessen, mit denen sie geöffnet werden usw. im Auge behält.

Antwort1

Diese Schicht befindet sich bei Linux und anderen Systemen, die nicht zu weit vom historischen Unix-Design abweichen (und auch bei den meisten Nicht-Unix-Betriebssystemen), innerhalb des Kernels.

Dieser Teil des Kernels heißtVFS-Schicht (virtuelles Dateisystem)Die Rolle des VFS besteht darin, Informationen über offene Dateien zu verwalten (die Korrespondenz zwischenDateideskriptoren,Offene Dateibeschreibungenund Verzeichniseinträge), um Dateipfade zu analysieren (Interpretieren von /, .und ..) und um Operationen an Verzeichniseinträgen an den richtigen Dateisystemtreiber zu verteilen.

Die meisten Dateisystemtreiber sind ebenfalls im Kernel enthalten, aber dieSICHERUNGDer Dateisystemtreiber ermöglicht die Delegierung dieser Funktionalität außerhalb des Kernels. Dateisystemoperationen können auch Benutzerlandcode beinhalten, wenn ein Speicher auf niedrigerer Ebene dies tut, beispielsweise wenn sich ein Festplattendateisystem auf einemLoop-Gerät.

Antwort2

Das Öffnen von Dateien unter Linux wird direkt vom Kernel übernommenSie können jedoch verschiedene Dinge tun, um den Prozess zu beeinflussen und zu untersuchen.


Linux-Speicherstapeldiagramm


Systemaufrufe

Von oben beginnend können Sie sehen, dass die Schnittstelle, die Anwendungen zur Interaktion mit Dateien verwenden,Systemaufrufe.

Offen,lesenUndschreibentun, was Sie erwarten, währendStatistikGibt Informationen zu einer Datei zurück, ohne sie zu öffnen.

Sie können die Verwendung dateibezogener Systemaufrufe durch ein Programm mit strace untersuchen:

$ strace -e trace=%file /bin/ls /etc
[...]
stat("/etc", {st_mode=S_IFDIR|0755,  ...}) = 0
openat(AT_FDCWD, "/etc", O_RDONLY...) = 3

Dadurch werden die durch verursachten Systemaufrufe analysiert ls /etcund angezeigt, dass statund openatfür das Verzeichnis aufgerufen werden /etc.

Sie fragen sich vielleicht, warum wir Dateioperationen für ein Verzeichnis aufrufen. Unter UNIX sind Verzeichnisse auch Dateien.alles ist eine Datei!


Dateideskriptoren

Sie fragen sich vielleicht, was openat() = 3in der obigen Ausgabe steht.

Unter UNIX werden geöffnete Dateien durch einDateideskriptor, eine eindeutige Darstellung der geöffneten Datei durch einen bestimmten Prozess. Die Dateideskriptoren 0, 1 und 2 sind normalerweise reserviert fürStandard-Streams(Benutzereingabe/-ausgabe), daher ist die erste geöffnete Datei 3.

Sie können eine Liste der offenen Dateideskriptoren für einen bestimmten Prozess abrufen, indem Sie Folgendes verwenden:lsof(michSTÖStiftFDateien):

$ cat /dev/urandom > /dev/null &
[1] 3242
$ lsof -p 3242
COMMAND  PID      USER   FD   TYPE DEVICE SIZE/OFF   NODE NAME
...
cat     3242 user         0u   CHR  136,0      0t0      3 /dev/pts/0
cat     3242 user         1w   CHR    1,3      0t0   1028 /dev/null
cat     3242 user         2u   CHR  136,0      0t0      3 /dev/pts/0
cat     3242 user         3r   CHR    1,9      0t0   1033 /dev/urandom

Die FDSpalte zeigt Ihnen die Dateideskriptornummer zusammen mit dem Zugriff.

Sie können auchfuserum nach Prozessen zu suchen, die bestimmte Dateien enthalten:

$ fuser /dev/urandom
/dev/urandom:         ...  3242  ...

Prozessinformationen zum Pseudodateisystem – /proc

Jetzt fragen Sie sich vielleicht:aber woher lsofweiß ich überhaupt, welche Dateien geöffnet sind??

Na, dann schauen wir doch mal!

$ strace -e trace=%file lsof -p 3242
...
stat("/proc/3242/", {st_mode=S_IFDIR|0555, st_size=0, ...}) = 0
openat(AT_FDCWD, "/proc/3242/stat", O_RDONLY) = 4
...
openat(AT_FDCWD, "/proc/3242/fd", O_RDONLY|O_NONBLOCK|O_CLOEXEC|O_DIRECTORY) = 4
readlink("/proc/3242/fd/0", "/dev/pts/0", 4096) = 10
lstat("/proc/3242/fd/0", {st_mode=S_IFLNK|0700, st_size=64, ...}) = 0
stat("/proc/3242/fd/0", {st_mode=S_IFCHR|0620, st_rdev=makedev(0x88, 0), ...}) = 0
openat(AT_FDCWD, "/proc/3242/fdinfo/0", O_RDONLY) = 7
...

So lsofweiß er, welche Dateien geöffnet sind, indem er weitere Dateien liest! Insbesondere das Verzeichnis /proc/3242/fd. Alles darunter /procist ein „falsches“ Dateisystem, das vom Kernel verwaltet wird. Sie können ls -les verwenden, um seine Struktur anzuzeigen.


Beeinflussung des Dateiöffnens

Es gibt verschiedene Methoden, mit denen Sie das Öffnen von Dateien beeinflussen können. Allerdings ist es nicht so einfach, wie einfach ein Skript zu ersetzen.

Wenn Sie die Art und Weise ändern möchten, wie Dateien gespeichert oder abgerufen werden, z. B. durch Verschlüsselung, Zwischenspeicherung, Verteilung auf mehrere Festplatten oder ähnliches, besteht eine gute Chance, dass bereits eine vorhandeneGerätemapperdas Ihren Bedürfnissen entspricht.

Wenn Sie eine feinere Kontrolle über das Öffnen von Dateien in einem bestimmten Verzeichnis / Mount wünschen, können Sie einen einfachenSICHERUNGDateisystem und mounten Sie es.

Auf Programm-/Prozessebene können SieLD_PRELOADum die Aufrufe der C-Bibliothek zu ändern und zu verhindern, dass sie die normalen Systemaufrufe durchführen.

Der schwierigste, aber flexibelste Weg wäre, einen eigenen Dateisystemtreiber zu schreiben.

Antwort3

Die Verwaltung des Dateizugriffs ist die erste und wichtigste Funktion eines Betriebssystems. DOS, eines der ältesten Betriebssysteme auf PCs, steht für Disk Operating System. Es ermöglichte Programmen größtenteils den direkten Zugriff auf die Hardware, jedoch nicht den Zugriff auf Dateien. Programme mussten DOS-Aufrufe verwenden und DOS verwaltete das Einfügen und Auslesen von Daten in Dateien für das Programm. Nur Festplattendienstprogramme konnten unter DOS direkt auf die Festplatte und Dateien zugreifen.

Moderne Betriebssysteme im geschützten Modus wie Linux handhaben den Dateizugriff wie DOS, erfordern aber auch, dass jeder Zugriff auf irgendetwas außerhalb des Programms selbst (oder jedes anderen Programms, mit dem es laut Konfiguration den Speicher teilt) über den Kernel erfolgt (Linux ist ein Kernel).

Ihr Programm unter Linux kann eine Funktion in der C-Bibliothek aufrufen, um Daten in eine Datei zu lesen oder darin zu schreiben. Die C-Bibliothek übernimmt dann ihren Teil der Organisation des Zugriffs auf die Daten in der Datei, während sie weiterhin im selben Kontext wie Ihr Programm ausgeführt wird. Anschließend ruft die C-Bibliothek den Kernel (Linux) mit der richtigen Funktion auf, um auf eine Datei zuzugreifen, wodurch die CPU in Ring 0 oder den privilegierten Modus versetzt wird. Die CPU führt jetzt den Linux-Dateisystemtreiber und die Festplattentreibersoftware im privilegierten Modus aus, der direkt auf die Hardware zugreift, um auf die Datei zuzugreifen. Die Daten werden in den Speicherbereich kopiert, in dem die C-Bibliothek Linux angewiesen hat, die Daten abzulegen. Die CPU wird wieder in den Benutzermodus mit dem Sicherheitskontext Ihres Programms geschaltet. Die C-Bibliothek wird fortgesetzt und führt alle erforderlichen Verarbeitungsvorgänge an diesen Daten aus und kehrt dann zur Ausführung Ihres Programms zurück.

Antwort4

Kurz gesagt, das passiert, wenn ein Programm in eine Datei schreibt

  1. Das Programm fordert den Kernel openzum Schreiben in eine durch einen Pfad angegebene Datei auf.
  2. Der Kernel richtet einige interne Strukturen ein und delegiert einen Teil der Aufgabe des Öffnens der Datei an einen für den Dateisystemtyp spezifischen Treiber. Der Kernel gibt dann einen Dateideskriptor, der nur eine Ganzzahl (z. B. 3) ist, an das Programm zurück.
  3. Das Programm fordert den Kernel auf, writeeine Bytefolge (z. B. einen String) an die durch den Dateideskriptor referenzierte Datei weiterzugeben.
  4. Der Kernel delegiert die Arbeit erneut an den Treiber.
  5. Die Schritte 3 und 4 werden wahrscheinlich mehrmals wiederholt.
  6. Das Programm fordert den Kernel zur closeDatei auf, auf die der Dateideskriptor verweist.
  7. Der Kernel delegiert erneut Arbeit an den Treiber und zerstört anschließend die internen Strukturen.

Hier ist ein recht minimalistisches Assemblerprogramm, das "Hallo Welt!" in die Datei greeting.txt schreibt:

.text
.globl _start

_start:
    # Open and possible create file
    mov $2,             %rax        # syscall 'open'
    mov $path_start,    %rdi        # path
    mov $0101,          %rsi        # create + write
    mov $400,           %edx        # only user gets read permissions
    syscall

    mov %rax,           %r10        # file descriptor

    # Write string to file
    mov $1,             %rax        # syscall 'write'
    mov %r10,           %rdi        # file descriptor
    mov $msg_start,     %rsi        # start of data
    mov $msg_length,    %edx        # length of data
    syscall                         # perform syscall

    # Close file
    mov $3,             %rax        # syscall 'close'
    mov %r10,           %rdi        # file descriptor
    syscall

    # Exit program
    mov $60,            %rax        # syscall 'exit'
    syscall                         # perform syscall


.section .rodata

path_start:
    .string "greeting.txt\0"
path_end:
path_length = path_end - path_start


msg_start:
    .string "Hello World!\n"
msg_end:
msg_length = msg_end - msg_start

Speichern Sie den Code in write.s und erstellen Sie ihn mit

as -o write.o write.s
ld -o write   write.o

und dann laufen mit

./write

Hoffentlich klappt alles.

(Hinweis: Ich führe keine Fehlerbehandlung durch. Dies ist nur Spielzeugcode.)

verwandte Informationen