Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Couche 0 d’Air — introduction (développeurs)

Document de présentation, pour entrer vite dans la couche 0 et savoir où trouver la référence. Les ADR (docs/adrs/) sont des documents internes au projet ; ce document-ci s’adresse aux développeurs qui consomment ou étudient la couche 0.

Ce qu’est la couche 0

La couche 0 est le socle syscall d’Air : une API Rust typée et sûre au-dessus des appels système Linux, sans libc. Deux crates :

  • air-sys-types — les types purs (aucun syscall) : identifiants typés (Pid, Tid, Uid/Gid, WatchDescriptor…), Errno, drapeaux/bitflags, types miroirs #[repr(C)] des structures kernel.
  • air-sys-syscall — les wrappers qui appellent le kernel via core::arch::asm! et rendent des Result<T, Errno>.

Ce que tu y trouves :

  • 11 familles de syscalls : process, fs, mem, signal, time, net, ipc, security, system, device (uevent/evdev), ebpf (bpf() + perf_event_open) ;
  • le module io_uring complet (12 « Temps » : cœur, fichiers, réseau, async, uring_cmd, registration, buffers fournis, opérations liées, multishot, multi-thread, confinement, accès brut) — la fondation des I/O asynchrones d’Air ;
  • des extensions : fs::inotify, affinité CPU (sched_set/getaffinity), mem::MmapRegion, l’extension privsep de process (setgroups/setres*id).

Pourquoi cette architecture

  • Pas de libc, pas de rustix. La couche 0 parle au kernel directement en asm!. Objectif : maîtrise totale du comportement, aucune dépendance C, et un cap no_std-compatible. (ADR-004 : Linux tier-1.)
  • Sûreté par le typage. Option<T> au lieu des sentinelles kernel (-1/0), Result<T, Errno> au lieu d’errno global, OwnedFd/BorrowedFd (RAII, pas de fuite de FD), newtypes par identifiant. (Conventions gravées : ADR-021.)
  • io_uring comme socle async. Le runtime asynchrone d’Air (ADR-023) se bâtit sur io_uring (ADR-022/028), pas sur epoll ni Tokio. Modèle d’ownership « slab S1 » sûr, prouvé (Miri/loom).
  • Variantes modernes préférées : clone3 (pas clone), pidfd_* (pas le PID nu), waitid (pas wait/waitpid), signalfd (ADR-020), les register-ops *2 d’io_uring…
  • Rigueur de couche fondatrice : 100 % de couverture lignes + branches (hors exceptions documentées), property-testing, fuzzing sur tout parseur de données externes, Miri/loom sur l’unsafe/le concurrent. (Principe 1.)

Pourquoi un noyau 6.12 minimum

6.12 est un noyau LTS (support long, cohérent avec l’horizon de durabilité d’Air), et c’est la version où la surface io_uring dont Air dépend est disponible (jusqu’aux opérations et register-ops récents), aux côtés de Landlock, seccomp-bpf, eBPF, etc. Cibler une seule version stable évite l’enfer des #ifdef de compatibilité et garde la couche 0 simple et auditable. Les numéros de syscalls et dispositions sont vérifiés par architecture (x86_64 et aarch64) sur l’uapi 6.12.

Ce que tu n’y trouveras pas (et pourquoi)

  • Aucune libc, aucun rustix — par conception (cf. ci-dessus).
  • Les syscalls legacy délibérément écartés, listés et justifiés dans UNSUPPORTED.md : les variantes anciennes supplantées par une variante moderne (clone, wait/waitpid, PID nus…), et les mécanismes io_uring obsolètes (PROVIDE_BUFFERS/REMOVE_BUFFERS op-based, register-ops v1 non taguées…).
  • Différés par décision (présents nulle part, et c’est voulu) : epoll (le besoin de readiness est couvert par le poll/multishot d’io_uring ; seuls des types Epoll* spéculatifs existent), fanotify (primitif privilégié, pour un service de sécurité ultérieur), futex synchrone (viendra avec l’implémentation futex maison d’air-thread).

UNSUPPORTED.md est la liste de référence de ces choix.

Dépendances externes

Aucune en production. La couche 0 est du Rust pur + asm! — pas de C, pas de libc, pas de rustix. Les seules dépendances sont test-only (property-testing, loom, cargo-fuzz), isolées et soumises à deny.toml/cargo audit (carve-out ADR-030). C’est inhabituel et assumé : la fondation ne dépend de rien au-dessus du kernel.

Pour le développeur C/C++

La couche 0 n’expose pas d’ABI C, et c’est volontaire : toute sa valeur vit dans le système de types Rust (RAII, lifetimes, Option/Result, ownership io_uring) — qui ne traverse pas une frontière C. Si tu es en C/C++ :

  • syscalls bruts → utilise ta libc (glibc/musl) ; io_uring en Cliburing ;
  • fonctionnalités Air → la C ABI des couches 1+ (air-base-lib, puis air-runtime/air-aircom), là où Air est polyglotte par conception (ADR-027) ;
  • asseoir des outils C sur la stack Air est l’objet d’une piste libc-compat (exploration, docs/notes/), pas de la couche 0.

Référence — pour aller plus loin

  • Specs par famille : docs/specs/layer-0/family-*.md.
  • Module io_uring : inventaire maître io-uring-0-inventaire.md + un document par Temps (io-uring-1-core.mdio-uring-4-raw.md).
  • Décisions : ADR-021 (conventions couche 0), ADR-019 (erreurs), ADR-020 (signaux), ADR-022/028 (io_uring), ADR-029 (nommage), ADR-024/030/034 (dépendances), ADR-031/035 (couverture & taxonomie d’exceptions).
  • Listes de référence : UNSUPPORTED.md (legacy écartés), COVERAGE-EXCEPTIONS.md (exceptions de couverture justifiées).
  • API : la référence rustdoc générée (/api/).

Licence du document : MPL 2.0.