본문으로 건너뛰기
cccskills
무료GitHub에 공개

io-uring

Use when building Linux servers with liburing, batching SQEs, multi-shot operations, provided buffer rings, registered files and buffers, or zero-copy send. Not for packet I/O: use af-xdp.

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

설치 방법 보기

포함된 파일(2)

  • SKILL.md7.5 KB
  • agents/openai.yaml218 B

SKILL.md(원문)

설치하기 전에 에이전트에게 전달되는 지시 내용을 확인할 수 있습니다.

io_uring

Contract

FieldBound contract
TriggerBuilding or tuning Linux async I/O with io_uring: the SQE/CQE model, liburing usage, multi-shot accept or recv, provided buffer rings, fixed files and buffers, zero-copy send, tokio-uring, or the io_uring versus epoll decision.
AuthorityRead-only. Writes nothing. Chat output only. No remote mutation.
Side effectReturns setup code, ring lifecycle rules, and a comparison verdict. No source files are modified.
DoneThe liburing example, the multi-shot and buffer-ring patterns, the zero-copy rule, and the epoll comparison verdict are delivered.

Inputs

  1. Workload shape (required): network or disk, operation mix, and connection count.
  2. Kernel (required): the running version, because io_uring features vary by version; base support starts at 5.1.
  3. Language (optional): C with liburing, or Rust with tokio-uring.

Procedure

  1. State the queue model. Each SQE describes one operation. Each CQE reports a result and the user_data cookie that identifies the operation. io_uring_submit() pushes SQEs to the kernel; io_uring_wait_cqe() blocks for a completion. Done when: the SQE-to-CQE flow with the cookie rule is stated in the delivered guidance.

  2. Show the minimal liburing loop as the reference shape.

    #include <liburing.h>
    
    struct io_uring ring;
    io_uring_queue_init(32, &ring, 0);
    
    struct io_uring_sqe *sqe = io_uring_get_sqe(&ring);
    io_uring_prep_read(sqe, fd, buf, sizeof(buf), 0);
    io_uring_sqe_set_data(sqe, (void *)1);
    io_uring_submit(&ring);
    
    struct io_uring_cqe *cqe;
    io_uring_wait_cqe(&ring, &cqe);
    if (cqe->res >= 0)
        handle(cqe->res);
    io_uring_cqe_seen(&ring, cqe);
    io_uring_queue_exit(&ring);
    

    Build with -luring. Done when: the example compiles against liburing and each CQE is consumed with cqe_seen.

  3. Map the request to its prep function: io_uring_prep_read, prep_write, prep_recv, prep_send, prep_accept, prep_connect, prep_poll_add, prep_timeout. Batch many SQEs between submits; one submit amortizes the syscall cost over the batch. Done when: every operation in the workload has a prep function and a batching point.

  4. Use multi-shot operations for connection-heavy paths. One io_uring_prep_multishot_accept SQE keeps producing completions until it reports completion of its own life.

    io_uring_prep_multishot_accept(sqe, listen_fd, NULL, NULL, 0);
    io_uring_sqe_set_data(sqe, (void *)ACCEPT_COOKIE);
    
    io_uring_wait_cqe(&ring, &cqe);
    if (cqe->user_data == ACCEPT_COOKIE && cqe->res >= 0)
        handle_client(cqe->res);
    int more = cqe->flags & IORING_CQE_F_MORE;
    io_uring_cqe_seen(&ring, cqe);
    if (!more)
        rearm_accept(); /* the multishot SQE ended; submit a new one */
    

    Done when: the loop re-arms exactly when IORING_CQE_F_MORE is clear.

  5. Use provided buffer rings for recv paths. The kernel picks a buffer from the ring, which removes the per-recv allocation.

    #define BUF_SIZE  4096
    #define BUF_COUNT 64
    
    int ret;
    struct io_uring_buf_ring *buf_ring =
        io_uring_setup_buf_ring(&ring, BUF_COUNT, BUF_GROUP, 0, &ret);
    for (int i = 0; i < BUF_COUNT; i++)
        /* mask is ring size - 1; offset walks the slots */
        io_uring_buf_ring_add(buf_ring, bufs[i], BUF_SIZE, i, BUF_COUNT - 1, i);
    io_uring_buf_ring_advance(buf_ring, BUF_COUNT);
    
    sqe = io_uring_get_sqe(&ring);
    io_uring_prep_recv_multishot(sqe, sock_fd, NULL, 0, 0);
    sqe->buf_group = BUF_GROUP;
    

    Return each consumed buffer with io_uring_buf_ring_add before the next advance. Done when: every consumed buffer is re-added, and the recv carries the buffer group.

  6. Register files and buffers on hot paths. Registered files avoid the per-operation fd table lookup; registered buffers are pinned and suited to *_fixed operations.

    io_uring_register_files(&ring, fds, 64);
    io_uring_prep_read(sqe, 0, buf, size, offset); /* index into the table, not the fd */
    struct iovec iov = { .iov_base = buf, .iov_len = size };
    io_uring_register_buffers(&ring, &iov, 1);
    io_uring_prep_read_fixed(sqe, fd, buf, size, offset, 0);
    

    Done when: hot-path operations use fixed variants and the registered tables are updated on fd churn.

  7. Use zero-copy send where available. io_uring_prep_send_zc needs kernel 6.0 or later and falls back to a normal send when the protocol or device does not support it. A zero-copy send posts a second notification CQE; treat IORING_CQE_F_MORE on the first CQE as the signal to wait for it. Done when: the send path handles the notification CQE and the fallback.

  8. For Rust, show the tokio-uring shape: the runtime owns the ring and returns buffer ownership with the result.

    use tokio_uring::fs::File;
    
    #[tokio_uring::main]
    async fn main() -> std::io::Result<()> {
        let file = File::open("test.txt").await?;
        let buf = vec![0u8; 4096];
        let (res, buf) = file.read_at(buf, 0).await;
        println!("read {} bytes", res?);
        Ok(())
    }
    

    Done when: the Rust example compiles with the tokio-uring crate and buffer ownership flow is stated.

  9. Deliver the epoll comparison as a verdict, not a table of absolutes.

    Aspectepollio_uring
    SyscallsOne per operation plus epoll_waitBatched SQEs, one submit
    BuffersApplication allocates per opProvided buffer rings
    Zero-copy sendManualSEND_ZC built in
    PortabilityEverywhere5.1+, feature-dependent

    Choose io_uring when syscall overhead is measured, not assumed, and the kernel has the needed operations. Stay on epoll for simple services and portability. Probe support at runtime with io_uring_get_probe(). Done when: the verdict cites a measured syscall or batching cost.

  10. State the security posture. Some distributions restrict io_uring by default because it has been an attack surface.

sysctl kernel.io_uring_disabled
# 0: all processes may create instances
# 1: CAP_SYS_ADMIN or members of kernel.io_uring_group only
# 2: creation off for everyone
sysctl kernel.io_uring_group   # the gid allowed at level 1

Existing instances keep working after a policy change. Keep the kernel patched and sandbox untrusted code. Done when: the deployment documents its io_uring policy and kernel version.

Failure and recovery

SymptomCauseRecovery
-EINVAL on prepOperation unsupported on this kernelCheck io_uring_get_probe(); gate the code path on it.
Hang on wait_cqeSQEs never submittedCall io_uring_submit after preparing.
Buffer never returnedConsumed buffer not re-addedRe-add with buf_ring_add after consuming.
SEND_ZC result unclearNotification CQE pendingWait for the second CQE; IORING_CQE_F_MORE marks the pair.
Slower than epollTiny batchesBatch more SQEs per submit; consider SQPOLL.
-EPERM on setupio_uring restricted by sysctlAlign with the kernel.io_uring_disabled policy.

Output

The queue-model statement; the minimal liburing example; the prep-function mapping and batching plan; the multi-shot and buffer-ring code; the registration rules; the zero-copy send rule; the tokio-uring example; the epoll verdict with its measured basis; the security posture.

리뷰

아직 리뷰가 없습니다. 사용해 본 소감을 남겨 주세요.

댓글

로그인 없이 쓸 수 있습니다. 사용 후기, 질문, 작동하지 않은 환경 등을 편하게 남겨 주세요.

아직 댓글이 없습니다. 첫 댓글을 남겨 보세요.

보내면 바로 공개됩니다. 이메일 주소나 전화번호 같은 개인 정보는 쓰지 마세요. URL은 2개까지입니다.

0 / 1,000자

이 양식은 reCAPTCHA로 보호되며 Google 개인정보처리방침 및 서비스 약관이 적용됩니다.

같은 저장소의 스킬

Use when explaining System V AMD64, ARM AAPCS, RISC-V psABI, stack frames, variadic calls, or FFI register rules. Not for the Rust FFI binding layer: use rust-ffi.

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

OutlineDriven/odin-claude-plugin372026년 9월 29일 업데이트

Use when configuring ADC sampling time, DMA-driven ADC, calibration, or DAC channel setup on bare-metal MCUs. Not for the DMA stream itself: use dma-baremetal.

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

OutlineDriven/odin-claude-plugin372026년 9월 29일 업데이트

af-xdp

무료

Use when creating AF_XDP sockets, configuring UMEM and XSK rings, writing an XDP redirect program, or choosing copy versus zero-copy mode. Not for full kernel bypass: use dpdk.

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

OutlineDriven/odin-claude-plugin372026년 9월 29일 업데이트

Use when a completed session needs an agent-environment retrospective. Not for an engineering retrospective from telemetry: use engineering-retrospective.

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

OutlineDriven/odin-claude-plugin372026년 9월 29일 업데이트

Use when a redacted, trimmed agent transcript must be appended to a GitHub PR or issue body, with human approval and preview. Not for automated or model-initiated insertion.

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

OutlineDriven/odin-claude-plugin372026년 9월 29일 업데이트

agents-md

무료

Use when a repo needs agent setup, AGENTS.md added or made lean, CLAUDE.md audited, or agent instructions scored or pruned. Not for remote, credential, publish, deploy, or irreversible changes.

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

OutlineDriven/odin-claude-plugin372026년 9월 29일 업데이트

OutlineDriven의 스킬 모두 보기

이 스킬의 문제 신고