Open Source im professionellen Einsatz

Newsletter abonnieren
Seite durchsuchen

HEFTARCHIV | NEWS | E-BIBLIOTHEK | VIDEO | BLOGS | WHITEPAPER | EVENTS | ACADEMY | ABO | SHOP

user friendly

  Home  »  Heft & Abo  »  Heftarchiv  »  2007  »  09  »  Kern-Technik  

RSS-Feed der aktuellen News von Linux-Magazin Online Folgen Sie Linux-Magazin Online auf Twitter
Diesen Artikel druckenDiesen Artikel weiterempfehlen Diesen Artikel kommentieren Newsletter abonnieren
Share/Bookmark

Kernel- und Treiberprogrammierung mit dem Kernel 2.6 - Folge 35 Folge 35

Kern-Technik

von Eva-Katharina Kunst, Jürgen Quade
Erschienen im Linux-Magazin 2007/09

Kopieren, ohne die CPU damit zu belasten? Linux kann's. Fehlen nur noch Applikationen, die das neue Feature nutzen. Die Kern-Technik verschafft Anwendungsprogrammierern das Know-how.

Die Datenmengen bei Multimedia & Co. sind für jedes Betriebssystem eine mächtige Herausforderung. Oft müssen mal eben ein paar GByte von der Festplatte gelesen, in die Grafikkarte transportiert oder über das Netzwerkinterface versandt werden. Typischerweise kopiert das OS die Daten dazu gleich mehrfach hin und her (Abbildung 1), was den ganzen Vorgang selbstverständlich verlangsamt.


Abbildung 1: Beim traditionellen Kopieren wird eine Datei bis zu viermal im Speicher kopiert. Unter günstigen Umständen kommt zweimal direkter Speicherzugriff (DMA) zum Einsatz, aber mindestens zweimal durchlaufen die Daten die CPU.

Zum Beispiel bei einem Server, der eine Filmdatei an einen über TCP/IP angebundenen Client sendet: Zuerst wandern die Daten (also der Film) von der Festplatte in den Speicher des Betriebssystemkerns, den Kernelspace. Dann sind die Daten ein zweites Mal unterwegs, um in den Speicherbereich der Server-Applikation zu wandern, den Userspace.

Zum Glück erfolgen zumindest zwei der Kopieraktionen häufig per DMA, nämlich das Lesen von der Platte und die Übergabe an den Ethernet-Controller. Das lindert das Problem aber nur zum Teil. Mindestens zweimal fasst die CPU die Daten an - das können sich auch moderne (HPC, High Performance Computing) Systeme nicht leisten.

Schon seit Längerem verwenden pfiffige Programmierer daher den Systemcall »sendfile()« [1]. Dieser Systemaufruf kopiert Daten von einem Stream in den nächsten, ohne sie dabei im Userspace zwischenzuparken. Leider ist »sendfile()« nicht universell verwendbar. Es lässt nämlich - vereinfacht gesagt - nur das Kopieren von einer auf der Platte liegenden Datei auf einen Socket (Netzwerk) zu. Datei auf Datei, Socket auf Socket oder Socket auf Datei - für »sendfile()« ist das alles unmöglich.

Turbolader

Seit Kernel 2.6.17 tragen die Entwickler den steten Nachfragen nach optimierten Datenkopierfunktionen mit den neuen Systemcalls »splice()«, »tee()« und »vmsplice()« Rechnung. Sie implementieren so genanntes Zero-Copying, was bedeutet, dass die CPU beim Kopieren von Daten nicht mehr beteiligt ist, eine CPU-Last also durch das Kopieren nicht anfällt (Abbildung 2).


Abbildung 2: Disk-to-Disk-Copy: Der erste Aufruf von »splice()« füllt den Kernel-Buffer, der zweite Aufruf überführt die Daten in die neue Datei.

Der Trick besteht darin, die Daten - meist per DMA - von der Quelle (etwa der Festplatte) in einen Kernel-Buffer zu transportieren. Statt die Daten danach weiter in den Userspace und von dort zurück an eine andere Stelle im Kernel zu kopieren, entnimmt der Kernel (etwa der Netzwerktreiber) die Daten direkt dem Kernel-Buffer. Gesteuert wird dieser Vorgang, bei dem die CPU kein einziges Datenbyte anfasst, durch die User-Applikation (siehe Abbildung 2).

Alles, was »splice()« & Co. also brauchen, ist - neben der Eingangsdatenquelle und der Ausgangsdatensenke - ein Kernel-Buffer. Den stellt eine klassische Unix-Pipe zur Verfügung, weshalb sie auch der Dreh- und Angelpunkt der Kernel-Implementierung ist. Der Systemcall »splice()« verbindet einen Filedeskriptor mit dem Anfang (oder Ende) einer solchen Pipe und füllt respektive entleert den zugehörigen Kernel-Buffer. Insgesamt sind bei einer derartigen Kopieraktion also vier Deskriptoren beteiligt (Abbildung 3).

Pipes und Puffer

Wer beispielsweise mit Hilfe von Zero-Copying eine Datei in eine andere kopieren möchte, verbindet mit »splice()« den File-Deskriptor der Quelldatei mit dem einen Ende der Pipe und füllt den Pipe-Buffer. Ein zweiter Aufruf von »splice()« verbindet das andere Ende der Pipe mit der Ausgabedatei und transferiert dadurch den Inhalt des Pipe-Buffers zurück auf die Festplatte. Diese Sequenz wiederholt sich so lange, bis alle Daten kopiert sind. Abbildung 3 verdeutlicht den Unterschied zur traditionellen Kopierfunktion: An die Stelle des Puffers im Userspace tritt der per Aufruf »pipe()« reservierte Kernel-Buffer. Und statt »read()« und »write()« transferiert der neue Systemcall »splice()« die Daten.


Abbildung 3: Statt des Puffers im Userspace legt der Kernel beim Zero-Copying per »pipe()«-Aufruf einen eigenen Puffer an. Der Syscall »splice()« stößt aus dem Userspace das Lesen von Platte in den Kernel-Buffer und das Schreiben aus dem Kernel-Buffer auf die Platte an.

Um mehreren Programmen parallel Zugriff auf die im Kernel-Buffer befindlichen Daten zu ermöglichen, bietet Linux den Systemcall »tee()« an. In seiner Funktion ähnelt er dem von der Shell bekannten Tee-Kommando. Er erlaubt es, Daten aus dem Pipe-Buffer auszulesen und an eine (andere) Pipe weiterzureichen (siehe Abbildung 4). Damit lassen sich beispielsweise die von einem DVB-T-Gerät empfangenen Daten per »tee« gleichzeitig mit einen Videoplayer anschauen und auf Festplatte speichern. »tee()« kopiert die Daten dabei nicht, sondern arbeitet allein mit Referenzen. Häufig ist die Pipe, an die »tee()« die Daten weiterreicht, die Standardausgabe Stdout (»STDOUT_FILENO«).

Auf der Kommandozeile sieht eine solche Befehls-Pipeline so aus:

splice-in /dev/dvbt | splice-tee film.mpeg | splice-out /dev/tvout

Doch sollten Programmierer aufpassen: Wer von einer Quelle zwei Kopien ziehen möchte - wobei keine der Kopien nach Stdout geht -, braucht auch zwei Pipes! Der Pseudo-Code in Abbildung 5 gibt die Struktur einer solchen Kopierapplikation wieder.

Die Applikation schließlich übergibt die Daten wieder dem Kernel, damit er sie über das Netzwerkinterface an den Client-Rechner schickt. Dazu kopiert der Netzwerktreiber die im Kernel deponierten Daten in den Speicher des Ethernet-Controllers.


Abbildung 4: Der Systemcall »tee()« bindet noch einen zweiten Kernel-Buffer zwischen die Eingabequelle und den duplizierten Ausgabekanal. Doch keine Angst vor unnötigen Datenduplikaten: Der Kernel arbeitet intern nicht mit einer Kopie, sondern nur mit einer Referenz.


Abbildung 5: Der vorgestellte Pseudo-Code legt zwei Kopien einer Datei an.

Der dritte hier vorgestellte Systemcall »vmsplice()« macht die im Userspace bereits vorhandenen Speicherbereiche dem Kernel zugänglich. Ohne Kopieraktion der Daten vom User- in den Kernelspace überträgt der Kernel die ihm anvertrauten Daten zur Peripherie per DMA und umgekehrt. Es handelt sich damit - abgesehen von der mit dem Systemcall verbundenen Kopieraktion - gewissermaßen um ein Gegenstück zu »mmap()« [3], das Speicherbereiche im Kernelspace einer Applikation zugänglich macht. Der zugehörige Filedeskriptor ist wieder einmal eine Pipe. Die genaue Aufrufsyntax der Systemcalls und der zugehörigen Parameter beschreibt der Kasten "Neue Systemcalls im Überblick".

Neue Systemcalls im
Überblick

Drei Systemaufrufe geben dem Anwendungsprogrammierer eine Eintrittskarte zu den neuen Kernelfunktionen.

Der erste Systemcall verbindet den über die Pipe repräsentierten Kernel-Buffer mit einem File-, Pipe- oder Socket-Deskriptor:

int splice(int fdin, loff_t *off_in, int fdout, loff_t *off_out, size_t len,unsigned int flags)

Er überträgt von »fdin« ab dem »off_in«-Byte maximal »len« Bytes Daten nach »fdout«. Über das Bitfeld »flags« lässt sich der Transfer parametrisieren. Die Bedeutung der Flags sieht folgendermaßen aus:

»SPLICE_F_MOVE«: Ist dieses Flag gesetzt, versucht der Kernel anstelle einer Kopie den Pipe-Buffer in den Page-Cache zu verschieben, falls er die Daten auf die Festplatte transferieren soll.

»SPLICE_F_MORE«: Ist dieses Flag gesetzt, weiß den Kernel, dass nach dem Aufruf von »splice()« weitere Daten folgen.

»SPLICE_F_NONBLOCK«: Dieses Flag verhindert, dass die Applikation am »splice()«-Aufruf schlafen gelegt wird. Achtung: Ein (interner) Zugriff auf die File-Deskriptoren kann dennoch blockieren.

»SPLICE_F_GIFT«: Das Flag ist nur im Kontext von »vmsplice« interessant. Damit überlässt eine Applikation dem Kernel die Kontrolle über die übergebenen Speicherbereiche, die Applikation darf den Speicher nicht weiter verwenden. Der übergebene Speicher muss einer Seitenlänge (typisch 4 KByte) entsprechen und auf eine Seitenadresse ausgerichtet sein.

Der zweite Systemcall dupliziert mindestens »len« Bytes von »pipe_in« nach »pipe_out«:

int tee(int pipe_in, int pipe_out, size_t len, unsigned int flags)

Der dritte Systemcall schließlich blendet »nr_segs« Speicherbereiche (referenziert über »iov«) in den durch »fd« repräsentierten Pipe-Buffer ein:

int vmsplice(int fd, const struct iovec *iov, unsigned long nr_segs, unsigned int flags)

Die Struktur »struct iovec *« ist in der Headerdatei »sys/uio.h« deklariert.

Sie können diesen Artikel als PDF für 99 Cent kaufen. Klicken Sie dazu einfach auf eine der beiden Bezahloptionen Paypal oder ClickandBuy.


Diesen Artikel druckenDiesen Artikel weiterempfehlen Diesen Artikel kommentieren Newsletter abonnieren
Share/Bookmark
Ähnliche Artikel
Dateien im Kosmos Das verteilte Dateisystem Kosmos-FS
Handliche Bibliotheken Optimale C-Bibliotheken für Embedded Linux
Keine Magie Open VPN mit Aladdins E-Tokens in großen Umgebungen
LAMP mal ohne AMP Performante Webapplikationen in C++ entwickeln
Dateisystem im Server LPIC-1-Vorbereitung - Teil 23: Network File System (NFS)
Große Kiste, kleine Kosten Der Mainframe-Emulator Hercules
Whitepaper
Usage Landscape Enterprise Open Source Data Integration

Die Nachfrage nach Datenintegrationslösungen für Unternehmen ist zunehmend gestiegen und vor allem das Interesse an Open Source Technologien wird immer größer. Doch wie und von wem werden Open Source Datenintegrationslösungen genutzt und welches Nutzungsverhalten lässt sich daraus ableiten? Das vorliegende White Paper präsentiert die Erfahrungswerte von über 1000 Open Source Nutzern und liefert fundierte Antworten auf diese Fragen.

Download PDF (Registrierung erforderlich)
Daten Migration - Eine Publikation von Bloor Research

Datenmigrationsprojekte überschreiten häufig das Budget, neigen zu Verzögerung und werden unter Umständen komplett abgebrochen. Bloor Research ist eines der weltweit führenden IT-Forschungs-, Analyse- und Beratungsunternehmen und wird in dem vorliegenden White Paper die wichtigsten Aspekte dieser Problematik näher beleuchten. Ferner werden praktische Empfehlungen für erfolgreiche Migrationsprojekte gegeben, die Sie auf Ihr nächstes Projekt übertragen können.

Download PDF (Registrierung erforderlich)
Kommentare (0)