Spleiß (Systemaufruf) - splice (system call)

splice () ist ein Linux- spezifischer Systemaufruf , der Daten zwischen einem Dateideskriptor und einer Pipe ohne Roundtrip in den Benutzerbereich verschiebt. Der zugehörige Systemaufruf vmsplice () verschiebt oder kopiert Daten zwischen einer Pipe und dem Benutzerbereich. Im Idealfall arbeiten Splice und VMMSPLICE, indem sie Seiten neu zuordnen und keine Daten kopieren, was die E / A- Leistungverbessern kann. Da lineare Adressen nicht unbedingt zusammenhängenden physischen Adressen entsprechen, ist dies möglicherweise nicht in allen Fällen und auf allen Hardwarekombinationen möglich.

Arbeiten

Mit splice () können Daten von einem Dateideskriptor in einen anderen verschoben werden, ohne dass Kopien aus dem Benutzerbereich in den Kernelbereich gelangen. Dies ist normalerweise erforderlich, um die Systemsicherheit zu gewährleisten und um eine einfache Schnittstelle für Prozesse zum Lesen und Schreiben in Dateien zu erhalten. splice () arbeitet mit dem Pipe-Puffer . Ein Pipe-Puffer ist ein kerninterner Speicherpuffer, der für den User-Space-Prozess undurchsichtig ist. Ein Benutzerprozess kann den Inhalt einer Quelldatei in diesen Pipe-Puffer und dann den Pipe-Puffer in die Zieldatei spleißen, ohne Daten durch den Benutzerbereich zu verschieben.

Linus Torvalds beschrieb splice () in einer E-Mail von 2006, die in einem KernelTrap- Artikel enthalten war.

Ursprünge

Die Linux- Splice-Implementierung basiert auf einem ursprünglichen Vorschlag von Larry McVoy aus dem Jahr 1998. Die Splice-Systemaufrufe wurden erstmals in der Linux- Kernel-Version 2.6.17 veröffentlicht und von Jens Axboe geschrieben .

Prototyp

 ssize_t splice(int fd_in, loff_t *off_in, int fd_out, loff_t *off_out, size_t len, unsigned int flags);

Einige Konstanten, die von Interesse sind, sind:

/* Splice flags (not laid down in stone yet). */
#ifndef SPLICE_F_MOVE
#define SPLICE_F_MOVE           0x01
#endif
#ifndef SPLICE_F_NONBLOCK
#define SPLICE_F_NONBLOCK       0x02
#endif
#ifndef SPLICE_F_MORE
#define SPLICE_F_MORE           0x04
#endif
#ifndef SPLICE_F_GIFT
#define SPLICE_F_GIFT           0x08
#endif

Beispiel

Dies ist ein Beispiel für Spleiß in Aktion:

/* Transfer from disk to a log. */
int log_blocks (struct log_handle * handle, int fd, loff_t offset, size_t size)
{
    int filedes [2];
    int ret;
    size_t to_write = size;
    ret = pipe (filedes);
    if (ret < 0)
        goto out;
    /* splice the file into the pipe (data in kernel memory). */
    while (to_write > 0) {
        ret = splice (fd, &offset, filedes [1], NULL, to_write,
                SPLICE_F_MORE | SPLICE_F_MOVE);
        if (ret < 0)
            goto pipe;
        else
            to_write -= ret;
    }
    to_write = size;
    /* splice the data in the pipe (in kernel memory) into the file. */
    while (to_write > 0) {
        ret = splice (filedes [0], NULL, handle->fd,
                &(handle->fd_offset), to_write,
                SPLICE_F_MORE | SPLICE_F_MOVE);
        if (ret < 0)
            goto pipe;
        else
            to_write -= ret;
    }

pipe:
    close (filedes [0]);
    close (filedes [1]);
out:
    if (ret < 0)
        return -errno;
    return 0;
}

Ergänzende Systemaufrufe

splice () ist einer von drei Systemaufrufen, die die splice () -Architektur vervollständigen . vmsplice () kann einen Anwendungsdatenbereich einer Pipe zuordnen ( oder umgekehrt) und so Übertragungen zwischen Pipes und Benutzerspeicher ermöglichen, wobei sys_splice () zwischen einem Dateideskriptor und einer Pipe überträgt. tee () ist der letzte Teil der Trilogie. Es dupliziert ein Rohr in ein anderes und ermöglicht Gabeln bei der Verbindung von Anwendungen mit Rohren.

Bedarf

Bei Verwendung von splice () mit Sockets sollte der Netzwerkcontroller (NIC) DMA unterstützen, da sonst splice () keine große Leistungsverbesserung liefert. Der Grund dafür ist, dass jede Seite der Pipe nur bis zur Rahmengröße gefüllt wird (1460 Bytes der verfügbaren 4096 Bytes pro Seite).

Nicht alle Dateisystemtypen unterstützen splice () . Auch AF_UNIX Steckdosen nicht unterstützen splice () .

Siehe auch

Verweise

Externe Links