Es gibt spezielle Dateien in Linux, die nicht wirklich Dateien sind.
Die bemerkenswertesten und klarsten Beispiele dafür sind im dev
Ordner "files":
/dev/null
- Ignoriert alles, was Sie in die Datei schreiben/dev/random
- Gibt zufällige Daten anstelle des Inhalts einer Datei aus/dev/tcp
- Sendet alle Daten, die Sie in diese Datei schreiben, über das Netzwerk
Was ist der Name dieser Art von "Dateien", die wirklich eine Art Skript oder Binärdatei sind?
Zweitens, wie entstehen sie? Sind diese Dateien auf Kernel-Ebene in das System integriert, oder gibt es eine Möglichkeit, eine "magische Datei" selbst zu erstellen (wie wäre es mit einer /dev/rickroll
)?
man 2 mknod
open()
,read()
,close()
usw. Danach ist es bis zur SoftwareAntworten:
/dev/zero
ist ein Beispiel für eine "spezielle Datei" - insbesondere ein "Geräteknoten". Normalerweise werden diese bei der Installation der Distribution erstellt, aber Sie können sie ganz selbst erstellen, wenn Sie möchten.Wenn Sie fragen
ls
nach/dev/zero
:Das "c" am Anfang zeigt an, dass es sich um ein "Zeichengerät" handelt. Der andere Typ ist "Block Device" (gedruckt mit
ls
"b"). Ganz grob gesagt sind Direktzugriffsgeräte wie Festplatten Blockgeräte, während sequenzielle Geräte wie Bandlaufwerke oder Ihre Soundkarte Zeichengeräte sind.Der Teil "1, 5" ist die "Hauptgerätenummer" und die "Nebengerätenummer".
Mit diesen Informationen können wir den
mknod
Befehl verwenden, um unseren eigenen Geräteknoten zu erstellen:Dadurch wird
foobar
im aktuellen Ordner eine neue Datei mit dem Namen erstellt , die genau dasselbe tut wie/dev/zero
. (Sie können natürlich verschiedene Berechtigungen festlegen, wenn Sie möchten.) Diese "Datei" enthält nur die drei oben genannten Elemente - Gerätetyp, Hauptnummer, Nebennummer. Sie könnenls
die Codes für andere Geräte nachschlagen und diese auch neu erstellen. Wenn Sie sich langweilen,rm
entfernen Sie einfach die Geräteknoten, die Sie gerade erstellt haben.Grundsätzlich teilt die Hauptnummer dem Linux-Kernel mit, mit welchem Gerätetreiber gesprochen werden soll, und die Nebennummer teilt dem Gerätetreiber mit, über welches Gerät Sie sprechen. (ZB haben Sie wahrscheinlich einen SATA-Controller, aber möglicherweise sind mehrere Festplatten angeschlossen.)
Wenn Sie neue Geräte erfinden möchten , die etwas Neues bewirken, müssen Sie den Quellcode für den Linux-Kernel bearbeiten und Ihren eigenen Kernel kompilieren. Also lass uns das nicht tun! :-) Sie können jedoch Gerätedateien hinzufügen, die die bereits vorhandenen duplizieren. Ein automatisiertes System wie udev wartet im Grunde nur auf Geräteereignisse und ruft automatisch
mknod
/rm
für Sie an. Nichts magischeres als das.Es gibt noch andere Arten von Spezialdateien:
Linux betrachtet ein Verzeichnis als eine spezielle Art von Datei. (Normalerweise können Sie ein Verzeichnis nicht direkt öffnen, aber wenn Sie könnten, würden Sie feststellen, dass es sich um eine normale Datei handelt, die Daten in einem speziellen Format enthält und dem Kernel mitteilt, wo alle Dateien in diesem Verzeichnis zu finden sind.)
Ein Symlink ist eine spezielle Datei. (Ein fester Link ist es nicht.) Mit dem
ln -s
Befehl können Sie Symlinks erstellen . (Schlagen Sie die Manpage nach.)Es gibt auch eine sogenannte "Named Pipe" oder "FIFO" (First-In, First-Out Queue). Sie können eine mit erstellen
mkfifo
. Ein FIFO ist eine magische Datei, die von zwei Programmen gleichzeitig geöffnet werden kann - ein Lesen, ein Schreiben. In diesem Fall funktioniert es wie ein normales Mantelrohr. Sie können aber jedes Programm einzeln starten ...Eine Datei, die in keiner Weise "speziell" ist, wird als "reguläre Datei" bezeichnet. Gelegentlich wird dies in der Unix-Dokumentation erwähnt. Das ist was es bedeutet; Eine Datei, die kein Geräteknoten oder Symlink oder was auch immer ist. Nur eine normale, alltägliche Datei ohne magische Eigenschaften.
quelle
mknod
, rufencat /proc/devices
Sie die Hauptnummern aller Treiber auf. Das bringt uns zu einer weiteren Art von Spezialdatei, dem/proc
Dateisystem ( diese Antwort spricht darüber).Die meisten
/dev
Einträge sind Blockgeräte-Inodes oder Zeichengeräte-Inodes. Wikipedia hat viele Details darüber, die ich nicht wiederholen werde.Aber
/dev/tcp
was in Ihrer Frage erwähnt wird, wird durch keine der vorhandenen Antworten erklärt./dev/tcp
und/dev/udp
unterscheiden sich von den meisten anderen/dev
Einträgen. Die Block- und Zeichengeräte werden vom Kernel implementiert, aber/dev/tcp
und/dev/udp
werden im Benutzermodus implementiert.Die Bash-Shell ist ein Programm, das eine Implementierung von
/dev/tcp
und/dev/udp
(kopiert vonksh93
) hat. Wenn Sie versuchen, einen Pfad unter denen mit Bash-Umleitungsoperatoren zu öffnen, wird kein gewöhnlicheropen
Systemaufruf ausgeführt. Stattdessen erstellt bash einen TCP-Socket und verbindet ihn mit dem angegebenen Port.Dies ist im Benutzermodus und nur in einigen Programmen implementiert, wie im folgenden Beispiel zu sehen ist, das den Unterschied zwischen dem Lassen
bash
und demcat
Versuch des Öffnens demonstriert/dev/tcp/::1/22
Ein Unterschied zu
ksh93
ist, dassbash
nur diese TCP-Verbindungen mit Umleitungsoperatoren ausgeführt werden, nicht an den anderen Stellen, an denen Dateien wie diesource
oder die.
eingebauten geöffnet werden können.quelle
gawk
ähnliche Sonderfälle/inet{,4,6}/{tcp,udp}/$port/$remote/$rport
, seit ungefähr 2010 (ich erinnere mich nicht genau und kann keine Versionshinweise finden)./dev/tcp
ist, dass es KEINE Datei ist. Es gibt niemals eine Datei mit diesem Namen. Bashs Syntax zum Öffnen von Sockets verwendet die Zeichenfolge/dev/tcp/address
wie einen Dateinamen, aber die Bezeichnung "Datei im Benutzerbereich implementiert" klingt nur seltsam. Interessant, dassksh
diese Dateinamen für alles verwendet werden, nicht nur für Weiterleitungen. Das ist näher an "Implementieren einer Datei".bash
nur dieses Verhalten kopiert, aber es hat einen anderen Ursprung.Neben dem Geräteknoten in anderen Antworten erklärt (erstellt mit mknod (2) oder von einigen geliefert devfs ), hat Linux andere „magische“ Dateien durch spezielle bereitgestellt virtuelle Dateisysteme , insbesondere in
/proc/
(siehe proc (5) , lesen Sie über procfs ) und in/sys/
(lies über sysfs ).Diese Pseudodateien (die stat (2) als normale Dateien und nicht als Geräte erscheinen) sind eine vom Kernel bereitgestellte virtuelle Ansicht. insbesondere das Lesen von
/proc/
(zB mitcat /proc/$$/maps
oder durch Öffnen (2) -ing/proc/self/status
in Ihrem Programm) beinhalten im Allgemeinen keine physikalische I / O von der Festplatte oder im Netzwerk, so ziemlich schnell.Um eine zusätzliche Pseudodatei zu erstellen,
/proc/
sollten Sie in der Regel Ihr eigenes Kernelmodul schreiben und laden (siehe z . B. dieses ).quelle
Sie werden Geräteknoten genannt und entweder manuell mit
mknod
oder automatisch von erstelltudev
. Sie sind typischerweise dateiähnliche Schnittstellen zu Zeichen- oder Blockgeräten mit Treibern im Kernel - z. B. sind Festplatten Blockgeräte, ttys und serielle Ports usw. sind Zeichengeräte.Es gibt auch andere "spezielle" Dateitypen, einschließlich Named Pipes und Fifos und Sockets.
quelle
Wie andere Benutzer bereits ausführlich erklärt haben, benötigen spezielle Dateien Code, um sie zu sichern. Es scheint jedoch niemand erwähnt zu haben, dass Linux verschiedene Möglichkeiten bietet, diesen Code im Userspace zu schreiben:
A. Mit FUSE (Dateisystem in USErspace) können Sie so etwas wie schreiben,
/proc
ohne dass das Risiko eines Absturzes des Kernels besteht, und dies in einer Sprache / Laufzeit Ihrer Wahl, wie z. B. Go , Node.js , Perl , PHP , Python , Ruby , Rust . usw. .Dies hat auch den Vorteil, dass FUSE-Dateisysteme bereitgestellt werden können, ohne
sudo
dass sie ausgeführt werden, während der Benutzer die Bereitstellung vornimmt.Hier sind einige Beispiele von Dingen, die Leute mit FUSE geschrieben haben:
B. Wenn Sie ein virtuelles Eingabegerät wie eine Tastatur, eine Maus, einen Joystick usw. erstellen möchten (z. B. um einen Userspace-Treiber für ein USB-Gerät zu schreiben, mit dem Sie sprechen
libusb
), gibt es eine Eingabe .Bindungen dafür sind schwerer zu finden, aber ich weiß, dass sie für Go (nur Tastatur), Python und Ruby (2) existieren .
Beispiele für die Verwendung von Eingaben in der Praxis sind:
C. Für generische Zeichengeräte gibt es CUSE (Zeichengeräte in USErspace). Es ist jedoch viel weniger beliebt.
Der einzige Benutzer des CUSE API , die ich persönlich bewusst bin , ist das gleiche Programm , das seine Schöpfung aufgefordert: osspd , die implementiert
/dev/dsp
,/dev/adsp
und/dev/mixer
(das OSS Audio-API) in User - Space , damit sie mit Pulseaudio oder dmix geleitet werden.Die einzige CUSE-Bindung, die ich finden konnte, ist cusepy , die seit 2010 nicht mehr aktualisiert wurde.
D. Möglicherweise benötigen Sie überhaupt keine neue Spezialdatei.
Sie können beispielsweise mit libusb (Liste der Bindungen auf der Seite) eine unformatierte Kommunikation mit einem beliebigen USB-Gerät herstellen und dann über einen anderen Mechanismus (TCP / UDP-Sockets, Lesen / Schreiben von stdin / stdout- oder normalen Dateien auf der Festplatte) mit anderen Programmen kommunizieren , usw.).
quelle
poll
, aber da cusepy ctypes verwendet und die Bindungen auf der Grundlage von C-Header-Dateien automatisch generiert werden, müssen Sie der Liste der exportierten Funktionen in nur den gewünschten Funktionsnamen hinzufügen, um fehlende Funktionen zu behebensetup.py
.In dem Buch Linux Device Drivers (dringend empfohlen) wird dies ausführlich erläutert, und Sie haben sogar ein Kernelmodul erstellt, das dies als Beispiel dient. Kurz gesagt, jeder Gerätetreiber verfügt über spezifische Funktionen, die aufgerufen werden, wenn eine Datei geöffnet oder geschlossen wird , lesen, schreiben, etc. Die "speziellen" Dateien machen einfach etwas Besonderes in diesen Funktionen, anstatt auf die Speicherhardware auf einer Festplatte zuzugreifen.
Zum Beispiel
/dev/null
tut die Schreibfunktion für einfach nichts und ignoriert die Bytes. Die Lesefunktion für/dev/random
gibt eine Zufallszahl zurück.quelle
mount -t devtmpfs
Es ist auch interessant zu sehen, dass es sich bei modernen Systemen
/dev
normalerweise um einen Dateisystemtyp handelt, der beliebig eingehängt werden kann. Ubuntu 16.04:Dies wird von aktiviert
CONFIG_DEVTMPFS=y
und ermöglicht es dem Kernel selbst, nach Bedarf Gerätedateien zu erstellen und zu zerstören.CONFIG_DEVTMPFS_MOUNT=y
Durch diese Option wird der Kernel automatisch zum Einhängen von devtmpfs veranlasst
/dev
.drivers/base/Kconfig
Unterlagen:file_operations
Schließlich sollten Sie Ihr eigenes Character Device-Kernel-Modul erstellen, um genau zu sehen, was los ist.
Hier ist ein minimal ausführbares Beispiel: Grundlegendes zu Gerätedateien (oder speziellen Zeichendateien)
Der wichtigste Schritt ist das Einrichten der
file_operations
Struktur, zB:enthält Funktionszeiger, die bei jedem dateibezogenen Systemaufruf aufgerufen werden.
Es wird dann offensichtlich, dass Sie diese dateibezogenen Systemaufrufe überschreiben, um zu tun, was Sie wollen, und so implementiert der Kernel Geräte wie
/dev/zero
./dev
Einträge erstellen um automatisch ohnemknod
Das letzte Rätsel ist, wie der Kernel automatisch
/dev
Einträge erstellt .Der Mechanismus kann durch eine Kernel - Modul beobachtet werden, dass sich tut , wie bei: https://stackoverflow.com/questions/5970595/how-to-create-a-device-node-from-the-init-module- Code-of-a-Linux-Kernel-Modul / 45531867 # 45531867 und kommt auf einen
device_create
Anruf.quelle