import std.io_uring;
io_uring ist der moderne Linux-Mechanismus für asynchrones I/O (Kernel 5.1+). SQEs (Submission Queue Entries) werden in einen Ring-Puffer geschrieben, den Kernel dann unabhängig abarbeitet. Abschlüsse erscheinen als CQEs (Completion Queue Entries) im CQ-Ring. Syscall-Overhead wird durch den gemeinsamen mmap-Speicher minimiert.
→ std.net.epoll · std.fs · Rohspeicher
| Konstante | Wert | Beschreibung |
|---|---|---|
IORING_OP_NOP | 0 | No-Op (Test) |
IORING_OP_READV | 1 | Scatter-Read (iovec) |
IORING_OP_WRITEV | 2 | Gather-Write (iovec) |
IORING_OP_TIMEOUT | 11 | Timeout |
IORING_OP_ACCEPT | 13 | accept4 |
IORING_OP_CONNECT | 16 | connect |
IORING_OP_READ | 22 | Einfacher Read |
IORING_OP_WRITE | 23 | Einfacher Write |
IORING_OP_SEND | 26 | send |
IORING_OP_RECV | 27 | recv |
| Konstante | Offset | Typ | Bedeutung |
|---|---|---|---|
SQE_OPCODE | 0 | uint8 | Opcode (IORING_OP_*) |
SQE_FLAGS | 1 | uint8 | SQE-Flags |
SQE_FD | 4 | int32 | Dateideskriptor |
SQE_OFF | 8 | uint64 | Datei-Offset |
SQE_ADDR | 16 | uint64 | Puffer-Zeiger |
SQE_LEN | 24 | uint32 | Pufferlänge |
SQE_USER_DATA | 32 | uint64 | Frei wählbare Kennung |
| Konstante | Offset | Typ | Bedeutung |
|---|---|---|---|
CQE_USER_DATA | 0 | uint64 | Wie in der SQE gesetzt |
CQE_RES | 8 | int32 | Ergebnis (negativ = Fehler-errno) |
| Funktion | Signatur | Beschreibung |
|---|---|---|
IoUringCreate | (entries: int64): int64 | Initialisiert Ring mit mind. entries Slots; gibt Ring-Handle oder 0 zurück |
IoUringFree | (ring: int64): int64 | Gibt alle Ring-Ressourcen frei (munmap + close) |
IoUringFd | (ring: int64): int64 | Liefert den io_uring-Dateideskriptor |
IoUringEnter | (fd: int64, toSubmit: int64, minComplete: int64, flags: int64): int64 | Direkter sys_io_uring_enter-Aufruf |
| Funktion | Signatur | Beschreibung |
|---|---|---|
IoUringGetSQE | (ring: int64): int64 | Nächste freie SQE (auf Null gesetzt); 0 wenn Ring voll |
IoUringSubmit | (ring: int64): int64 | Veröffentlicht alle vorbereiteten SQEs |
IoUringSubmitAndWait | (ring: int64, minComplete: int64): int64 | Submit + blockiert bis minComplete CQEs fertig |
| Funktion | Signatur | Beschreibung |
|---|---|---|
IoUringPeekCQE | (ring: int64): int64 | Nächste fertige CQE oder 0 wenn keine vorhanden |
IoUringWaitCQE | (ring: int64): int64 | Blockiert bis eine CQE verfügbar ist |
IoUringCQESeen | (ring: int64, cqe: int64): int64 | Markiert CQE als verarbeitet (Head +1) |
IoUringCQEResult | (cqe: int64): int64 | Liest Ergebnis aus CQE (negativ = Fehler-errno) |
IoUringCQEUserData | (cqe: int64): int64 | Liest user_data-Feld der CQE |
| Funktion | Beschreibung |
|---|---|
IoUringSQESetNop(sqe, userData) | No-Op konfigurieren (für Tests) |
IoUringSQESetRead(sqe, fd, buf, len, offset, userData) | Asynchronen Read konfigurieren |
IoUringSQESetWrite(sqe, fd, buf, len, offset, userData) | Asynchronen Write konfigurieren |
import std.io_uring;
fn main(): int64 {
var ring: int64 := IoUringCreate(8);
if (ring = 0) { return -1; }
var sqe: int64 := IoUringGetSQE(ring);
if (sqe = 0) { IoUringFree(ring); return -1; }
IoUringSQESetNop(sqe, 42);
IoUringSubmit(ring);
var cqe: int64 := IoUringWaitCQE(ring);
var res: int64 := IoUringCQEResult(cqe);
var ud: int64 := IoUringCQEUserData(cqe);
IoUringCQESeen(ring, cqe);
IoUringFree(ring);
return 0;
}
import std.io_uring;
import std.alloc;
import std.fs;
fn AsyncRead(path: pchar, outBuf: int64, bufLen: int64): int64 {
var fd: int64 := OpenFile(path, 0);
if (fd < 0) { return fd; }
var ring: int64 := IoUringCreate(4);
if (ring = 0) { CloseFile(fd); return -12; }
var sqe: int64 := IoUringGetSQE(ring);
IoUringSQESetRead(sqe, fd, outBuf, bufLen, 0, 1);
IoUringSubmit(ring);
var cqe: int64 := IoUringWaitCQE(ring);
var res: int64 := IoUringCQEResult(cqe);
IoUringCQESeen(ring, cqe);
IoUringFree(ring);
CloseFile(fd);
return res; // Anzahl gelesener Bytes oder negatives errno
}
import std.io_uring;
import std.alloc;
fn MultiWrite(fd: int64, buf1: int64, len1: int64,
buf2: int64, len2: int64): int64 {
var ring: int64 := IoUringCreate(8);
if (ring = 0) { return -12; }
// Zwei Writes in den Ring stellen
var sqe1: int64 := IoUringGetSQE(ring);
IoUringSQESetWrite(sqe1, fd, buf1, len1, 0, 100);
var sqe2: int64 := IoUringGetSQE(ring);
IoUringSQESetWrite(sqe2, fd, buf2, len2, len1, 200);
// Beide abschicken, auf beide warten
IoUringSubmitAndWait(ring, 2);
var result: int64 := 0;
var i: int64 := 0;
while (i < 2) {
var cqe: int64 := IoUringPeekCQE(ring);
if (cqe != 0) {
var res: int64 := IoUringCQEResult(cqe);
if (res < 0) { result := res; }
IoUringCQESeen(ring, cqe);
}
i := i + 1;
}
IoUringFree(ring);
return result;
}
IoUringCreate gibt 0 zurück wenn sys_io_uring_setup fehlschlägt.entries auf die nächste Zweierpotenz. Für einzelne Operationen reicht IoUringCreate(4).IoUringCQESeen aufgerufen werden, sonst bleibt der Ring blockiert.IOSQE_IO_LINK-Flag setzen (nicht in diesem Wrapper implementiert).IORING_FEAT_SINGLE_MMAP). Der Wrapper erkennt und handhabt das automatisch.offset auf -1 gesetzt werden (aktuelle Position, kein seekbares Medium).Letzte Aktualisierung: 2026-06-05