LinuxCore 0.4.10
dotnet add package LinuxCore --version 0.4.10
NuGet\Install-Package LinuxCore -Version 0.4.10
<PackageReference Include="LinuxCore" Version="0.4.10" />
<PackageVersion Include="LinuxCore" Version="0.4.10" />
<PackageReference Include="LinuxCore" />
paket add LinuxCore --version 0.4.10
#r "nuget: LinuxCore, 0.4.10"
#:package LinuxCore@0.4.10
#addin nuget:?package=LinuxCore&version=0.4.10
#tool nuget:?package=LinuxCore&version=0.4.10
LinuxCore
A thin, AOT-compatible .NET wrapper around Linux libc APIs and raw kernel interfaces. Provides ergonomic, low-allocation C# abstractions for files, sockets, events, polling, scheduling, and more.
Features
- File I/O —
LinuxFileforopen/read/write/seek/statxwithSpan<byte>support - Memory Files —
LinuxMemoryFileformemfd_createand memfd seals viafcntl - Memory Maps —
LinuxMemoryMap/LinuxReadOnlyMemoryMapformmap/munmapwithSpan<byte>/Memory<byte>access - Events & Semaphores —
LinuxEventandLinuxSemaphorebacked byeventfd - Polling —
LinuxPollforpoll()-based readiness notification - Clocks —
LinuxClockfor nanosecond-precision monotonic, boottime, CPU-time, and wall-clock (CLOCK_REALTIME) timestamps and high-precision sleeps - Scheduling —
LinuxSchedulerforsched_setscheduler/sched_getscheduler(FIFO, RR, etc.) - Resource Limits —
LinuxResourceLimitforgetrlimit/setrlimit - Cancellation —
LinuxCancellationTokenbridgesCancellationTokento native poll - Sockets —
UnixSocketfor AF_UNIX sockets andLinuxSocketBasefor shared raw socket operations - System Configuration —
SystemConfigurationforsysconf()queries (page size, max open files, etc.) - Users & Groups —
LinuxUserandLinuxGroupfor passwd/group lookups by name or ID - Processes —
LinuxProcessforposix_spawnp, environment and standard-stream redirection, and cancellable pidfd waiting
Requirements
- Linux (the library is annotated with
[SupportedOSPlatform("linux")]) - .NET 10+
- Linux 4.11+ for
LinuxFilemetadata viastatx - glibc 2.28+ (2.34+ on 32-bit architectures) or musl 1.2.5+ for the remaining libc and time64 entry points
- Linux 5.3+ for
LinuxProcesspidfd waiting
Architecture
The library has two layers:
LinuxCore.Interop— internal native bindings. Most files map to libc subsystems through source-generated[LibraryImport]; file operations, memory-map operations,memfd_create, andeventfd2use libcsyscall()with numbers fromSystemCallTable. Numbers that are stable across supported architectures are exposed as static members. Numbers that vary but are available everywhere are abstract members implemented by each architecture table; calls available only on an architecture subset may use virtual members that throw elsewhere. Callers should useSystemCallTable.Current.LinuxCore— public API types wrapping the interop layer with safe-ish, idiomatic C# APIs.
File-descriptor-owning types follow this hierarchy:
NativeObject (IDisposable + Finalizer)
└─ FileObject (FileDescriptor, shared I/O and descriptor-control helpers)
├─ LinuxEventBase → LinuxEvent, LinuxSemaphore
├─ LinuxSocketBase → UnixSocket
└─ LinuxFile → LinuxMemoryFile
LinuxSecurityObject (Id + Name)
├─ LinuxUser
└─ LinuxGroup
Operational notes
LinuxScheduler.Set(...)and someLinuxResourceLimit.Set(...)calls may require root privileges or Linux capabilities such asCAP_SYS_NICE/CAP_SYS_RESOURCE.- AF_UNIX pathname sockets are subject to the kernel
sockaddr_un.sun_pathlimit (108 bytes on Linux). FileDescriptoris an allocation-free, non-owning value. Copying it or readingFileObject.Descriptordoes not duplicate the descriptor or retain its lifetime; useClone()for an independent descriptor.FileObjectintentionally avoids per-operation lifetime leasing, so callers must keep the owner strongly reachable and prevent concurrent disposal or external closure while operations or raw descriptors are in use. Closed or stale descriptor values may refer to unrelated resources after Linux recycles the number.- File operations, memory-map operations,
memfd_create, andeventfd2dispatch through libcsyscall()rather than dedicated libc symbols. They therefore use raw kernel semantics without libc cancellation points, musl close/AIO or virtual-memory synchronization, old-kernelO_CLOEXEC/fcntlfallbacks, specialfcntlemulation, or 32-bit time64 ioctl translation. Dedicated-symbol interposition such asLD_PRELOADhooks foropen,read,write,mmap,munmap,msync,memfd_create, oreventfdis bypassed. Seccomp profiles must allow the architecture-specific calls, includingopenat,mmapon 64-bit architectures,mmap2on 32-bit x86 and Arm,munmap,msync,memfd_create, andeventfd2, plusfcntl64/_llseekon 32-bit x86 and Arm. On s390x, the kernelmmapABI accepts one packed argument block; glibc callers must pack it, while musl's publicsyscall()wrapper packs six scalar arguments internally.FileDescriptor.Close()ignores close errors and must not be retried afterEINTR. - Generic
ReceiveMessagemethods return only the requested control-message type and do not close resources from nonmatching messages. On Unix sockets, useReceiveFileDescriptorswhen anSCM_RIGHTSmessage may be present. - On QEMU linux-user,
ReceiveFileDescriptorsrequiresSO_PASSPIDFDandSO_PASSSECto be disabled. Either option can cause host-side descriptors to be omitted during ancillary conversion and remain open. LinuxCore does not enable either option. LinuxFileFlagsandLinuxMemoryMapFlagsvalues are stable managed tokens. LinuxCore translates architecture-dependent file flags on Arm and PowerPC, and mapping flags on PowerPC, before calling libc.- CI runs the full test suite on every target. Alpine x64 and arm64 plus Arm32 glibc and musl build and test inside native SDK containers; ppc64le, s390x, RISC-V64, and LoongArch64 run host-built portable test output under QEMU. All targets gate publishing. The RISC-V64 and LoongArch64 matrix entries use community runtimes because Microsoft does not publish supported .NET 10 runtimes for those architectures or support QEMU execution.
- NativeAOT compatibility is exercised in CI on both glibc (Ubuntu) and musl (Alpine) runners via a small smoke app.
LinuxProcesscancellation stops only the wait; it does not terminate the child. Callers must successfully wait and reap the child before disposal. Process waits, disposal, supplied-descriptor mutation, native-environment mutation, and external child reaping must not race. A replacement child environment does not controlposix_spawnpexecutable lookup on supported glibc and musl versions; pass a path containing/when lookup must not use the native parentPATH.
Contributing
Every new or changed constant that represents a libc or Linux kernel value must include a CScript assertion against the current platform's native headers in the corresponding subsystem test file. Include explicit mappings for enum aliases and composite values. For architecture-dependent managed tokens such as LinuxFileFlags and LinuxMemoryMapFlags, assert the translated native value instead of the managed numeric token. Use optional-symbol assertions only when supported header versions genuinely omit the symbol.
License
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- No dependencies.
| Version | Downloads | Last Updated |
|---|---|---|
| 0.4.10 | 71 | 8/19/2026 |
| 0.4.9 | 66 | 8/18/2026 |
| 0.4.8 | 78 | 8/18/2026 |
| 0.4.7 | 68 | 8/17/2026 |
| 0.4.6 | 76 | 8/14/2026 |
| 0.4.5 | 71 | 8/14/2026 |
| 0.4.4 | 72 | 8/13/2026 |
| 0.4.3 | 71 | 8/11/2026 |
| 0.4.2 | 65 | 8/5/2026 |
| 0.4.1 | 73 | 8/4/2026 |
| 0.4.0 | 70 | 8/4/2026 |
| 0.3.12 | 76 | 7/16/2026 |
| 0.3.11 | 74 | 7/15/2026 |
| 0.3.10 | 143 | 6/26/2026 |
| 0.3.9 | 83 | 6/26/2026 |
| 0.3.8 | 78 | 6/26/2026 |
| 0.3.7 | 95 | 6/26/2026 |
| 0.3.6 | 102 | 6/22/2026 |
| 0.3.5 | 100 | 6/11/2026 |
| 0.3.4 | 85 | 5/25/2026 |