Linux-Zeichengeräte werden im Verzeichnis „/dev“ abgelegt. Zeichengeräte beziehen sich auf Geräte, die nur Byte für Byte gelesen und geschrieben werden können. Im Allgemeinen entspricht jedes Zeichengerät oder Blockgerät einer Gerätedatei im Verzeichnis „/dev“, und jede Gerätedatei muss über ein Haupt-/Geräteverzeichnis verfügen Gleiche Nebengerätenummer und Hauptgerätenummer sind ähnliche Geräte und verwenden denselben Treiber.
Die Betriebsumgebung dieses Tutorials: Linux7.3-System, Dell G3-Computer.
Das Linux-System unterteilt Geräte in drei Kategorien: Charaktergeräte, Blockgeräte und Netzwerkgeräte Unter diesen drei Kategorien sind Zeichengeräte relativ einfach und Anwendungszeichengeräte Der Zugriff erfolgt über Zeichengerätedateien. In dieser Vorlesung werden hauptsächlich Zeichengeräte und Netzwerkgeräte vorgestellt.
Zeichengerät bezieht sich auf ein Gerät, das nur Byte für Byte lesen und schreiben kann. Bestimmte Daten im Gerät können nicht zufällig gelesen werden und die Daten müssen der Reihe nach gelesen werden. Zeichengeräte sind Stream-orientierte Geräte, darunter Mäuse, Tastaturen, serielle Anschlüsse, Konsolen und LEDs.
Im Allgemeinen entspricht jedes Zeichengerät oder Blockgerät einer Gerätedatei im Verzeichnis /dev, und jede Gerätedatei muss eine Haupt-/Nebengerätenummer haben. Geräte mit derselben Hauptgerätenummer sind ähnliche Geräte . Verwenden Sie denselben Treiber.
Linux-Programme auf Benutzerebene verwenden Treiber, um Zeichengeräte zu bedienen oder Geräte über Gerätedateien zu blockieren.
Sie können den Befehl
cat /proc/devices
verwenden, um die Hauptgerätenummer des aktuell geladenen Gerätetreibers anzuzeigen.
Durch Ausführen des Befehls
ls -l
im Verzeichnis /dev können Sie die Haupt- und Nebengerätenummern aller Gerätedateien sehen:
Erklären Sie allgemeine Gerätedateien wie folgt:
/dev/hd[a-t]:IDE设备 /dev/sd[a-z]:SCSI设备 /dev/fd[0-7]:标准软驱 /dev/md[0-31]:软raid设备 /dev/loop[0-7]:本地回环设备 /dev/mem:内存 /dev/null:无限数据接收设备,相当于黑洞 /dev/zero:无限零资源 /dev/tty[0-63]:虚拟终端 /dev/ttyS[0-3]:串口 /dev/lp[0-3]:并口 /dev/console:控制台 /dev/fb[0-31]:framebuffer /dev/cdrom => /dev/hdc /dev/modem => /dev/ttyS[0-9] /dev/pilot => /dev/ttyS[0-9]
Es gibt zwei Möglichkeiten, eine Gerätedatei zu erstellen. Der erste Parameter des Befehls ist der Aufruf dieser Funktion in der Programmierung Der Name der Gerätedatei, der zweite Parameter ist der Gerätetyp, z. B. c steht für ein Zeichengerät, und der dritte und vierte Parameter sind die Hauptgerätenummer und die Nebengerätenummer der Gerätedatei, z. B. 231 und 0. Die Kombination aus Hauptgerätenummer und Nebengerätenummer bestimmt eindeutig ein Gerät. Die Hauptgerätenummern verschiedener Typen desselben Geräts sind gleich, aber die Nebengerätenummern sind unterschiedlich. Beispielsweise sind mehrere Partitionen einer Festplatte vorhanden verschiedene Nebengerätenummern Die Gerätenummer kann die Gerätedatei dem Treiber zuordnen.
mknod Dateiname Typ Major Minor
struct cdev { struct kobject kobj; // 内嵌内核对象 struct module *owner; //该字符设备所在的内核模块 const struct file_operations *ops; //文件操作结构体 struct list_head list; //已注册字符设备链表 dev_t dev; //由主、次设备号构成的设备号 unsigned int count;//同一主设备号的次设备号的个数 };
struct file_operations { struct module *owner; loff_t (*llseek) (struct file *, loff_t, int); ssize_t (*read) (struct file *, char *, size_t, loff_t *); ssize_t (*write) (struct file *, const char *, size_t, loff_t *); int (*readdir) (struct file *, void *, filldir_t); unsigned int (*poll) (struct file *, struct poll_table_struct *); int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long); int (*mmap) (struct file *, struct vm_area_struct *); int (*open) (struct inode *, struct file *); int (*flush) (struct file *); int (*release) (struct inode *, struct file *); int (*fsync) (struct file *, struct dentry *, int datasync); int (*fasync) (int, struct file *, int); int (*lock) (struct file *, int, struct file_lock *); ssize_t (*readv) (struct file *, const struct iovec *, unsigned long,loff_t *); ssize_t (*writev) (struct file *, const struct iovec *, unsigned long, loff_t *); };
Wie in der Abbildung gezeigt, wird im Linux-Kernel ganz links die cdev-Struktur zur Beschreibung des Zeichengeräts verwendet. Über ihr Mitglied dev_t wird die Gerätenummer (unterteilt in Haupt- und Nebengerätenummern) definiert, um das zu bestimmen Einzigartigkeit des Zeichengeräts; durch sein Mitglied file_operations Definieren Sie die Schnittstellenfunktionen, die der Zeichengerätetreiber dem virtuellen Dateisystem VFS bereitstellt, wie z. B. die allgemeinen Funktionen open(), read(), write() usw Betreiben Sie das Hardwaregerät.
Schauen wir uns dieses Bild basierend auf dem vorherigen Bild an. Der Zeichengerätetreiber wird in Form eines Kernelmoduls zunächst auf statische oder dynamische Weise in den Kernel geladen ; dann das Zeichen Die Initialisierungsfunktion stellt die Verbindung zwischen cdev und file_operations her und fügt dem System über die Registrierungsfunktion eine CDev hinzu, um die Registrierung abzuschließen, die dem Laden entspricht cdev muss abgemeldet und die Gerätenummer freigegeben werden. Im Benutzerprogramm können diese vom Treiber im Kernel implementierten Funktionen über Systemaufrufe wie open(), read(), write() usw. aufgerufen werden. Auf diese Weise wird der Pfad zwischen Benutzermodus und Kerneltreiber geöffnet.
Wie in der Abbildung gezeigt, ist das Schreiben eines Zeichengerätetreibers in drei Hauptschritte unterteilt:
Treiberinitialisierung, die in vier Schritte unterteilt ist, Die aufrufende Funktion wird erreicht.Die erste Funktion ist die Zuweisungsfunktion, die dynamisch für den Speicher von cdev gilt und der Struktur Speicherplatz zuweist.
Die zweite Funktion ist die Initialisierungsfunktion, die die Mitglieder von cdev initialisiert und die Zuordnung zwischen cdev und file_operations herstellt.
Die dritte Funktion registriert das cdev-Geräteobjekt, dh fügt einfach das Zeichengerät zur Zeichengerätetabelle hinzu Wie alle Die Anmeldung erfolgt wie bei der Immatrikulation.
Die vierte Funktion ist der Aufruf zum Aufheben der Registrierung des Treibers, um das CDev-Objekt aus dem System zu löschen.
Die fünfte Funktion gibt den von der CDev-Datenstruktur belegten Speicher frei.
6.1 Anwendung und Freigabe der GerätenummerEin Zeichengerät oder Blockgerät hat eine Hauptgerätenummer und eine Nebengerätenummer.
Die Hauptgerätenummer dient zur Identifizierung des mit der Gerätedatei verbundenen Treibers und spiegelt den Gerätetyp wider. Die sekundäre Gerätenummer wird vom Treiber verwendet, um zu identifizieren, welches Gerät er betreibt, und um Geräte desselben Typs zu unterscheiden. Beantragen Sie bei der Anmeldung eine Gerätenummer und geben Sie die Gerätenummer bei der Abmeldung frei. So wie jeder bei der Einschreibung einen Studierendenausweis hat und dieser Studierendenausweis beim Abschluss und beim Verlassen freigegeben wird.
6.2 Datentransfer zwischen Userspace und KernelspaceWenn wir die Funktion read() im Benutzerprogramm aufrufen, fallen wir in den Kernelspace. Tatsächlich müssen wir sie verwenden Die copy_to_user()-Funktion des Kernels kopiert die Daten im Kernel-Space-Puffer in den User-Space-Puffer. Wenn wir hingegen die Funktion write() aufrufen, kopiert der Kernel die User-Space-Daten in den Kernel-Puffer Aufruf der Funktion copy_from_user().
Verwandte Empfehlungen: „
Linux-Video-TutorialDas obige ist der detaillierte Inhalt vonWo ist das Linux-Zeichengerät platziert?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!