logo

gVisor - Abstractions

Because gVisor is essentially an entire operating system kernel written in Go (called the Sentry), it has to reimplement all standard Linux kernel concepts from scratch. To do this while adhering to container standards (like the OCI runtime spec), gVisor layers its abstractions into two categories: Workload Isolation Abstractions (managing containers/pods) and Kernel Execution Abstractions (managing processes/threads).

Workload Isolation Abstractions

These boundaries dictate how applications are containerized and walled off from the host operating system.

The Sandbox

  • What it is in gVisor: The outermost boundary of isolation. A Sandbox represents a single instance of the Sentry process running on the host machine. It encapsulates its own dedicated, sandboxed memory space, virtualized network stack (Netstack), and set of namespaces. Multiple containers (e.g., a Kubernetes Pod containing an application and a sidecar) run inside a single Sandbox, sharing this single Sentry instance.
  • Linux Kernel Equivalent: A Virtual Machine (VM) boundary / Hypervisor context. While gVisor is technically a process-level sandbox rather than a true hypervisor, conceptually it acts like a lightweight VM kernel boundary. In standard Linux container runtimes (runc), there is no "Sandbox" abstraction; instead, containers rely directly on a combination of host-level Namespaces and Cgroups to achieve isolation.

Code: runsc/sandbox/sandbox.go

Container

  • What it is in gVisor: A logical grouping of processes inside a Sandbox that shares a specific mount namespace and root filesystem config. A container inside gVisor is tied to a dedicated Gofer process on the host machine, which securely proxies file operations from that specific container's root filesystem.
  • Linux Kernel Equivalent: A set of Namespaces (specifically Mount, UTS, and IPC) constrained by a Cgroup. Just like in standard Linux, a container in gVisor isn't a single kernel object—it is a collection of tasks configured to view the same filesystem tree and system identifiers.

Code: runsc/container/container.go

Kernel Execution Abstractions

These are the internal Go structures inside the Sentry that emulate how Linux handles threads, processes, and resources.

  [ gVisor Sandbox (Sentry) ]
               │
     [ struct ThreadGroup ]  <───> (Equivalent to a Linux Process)
               │
 ┌─────────────┴─────────────┐
 ▼                           ▼
[ struct Task ]             [ struct Task ]  <───> (Equivalent to Linux Threads)

Task

  • What it is in gVisor: The foundational unit of execution within the Sentry. Represented in gVisor's internal Go code as kernel.Task, it tracks the execution state of a single execution context. It holds registers, CPU architecture states, signal masks, and memory mappings.
  • Linux Kernel Equivalent: struct task_struct. In Linux, everything that executes is a task_struct. Whether it is a single-threaded process or one of many threads inside a multi-threaded application, the Linux kernel scheduler treats each as an individual task_struct. gVisor's kernel.Task mirrors this exact design.

Code: pkg/sentry/kernel/task.go

ThreadGroup

  • What it is in gVisor: A collection of Task objects that share the same resources, such as memory space (virtual memory mappings), signal handlers, and a shared Thread Group ID (TGID).
  • Linux Kernel Equivalent: A Process. In Linux, a "process" is technically just a group of task_struct objects that share memory and signal tables, bound together under the same Thread Group Leader. When you issue a clone() syscall in Linux with flags like CLONE_VM and CLONE_SIGHAND, you add a thread to a process. In gVisor, this translates to adding a Task to a ThreadGroup.

Code: pkg/sentry/kernel/thread_group.go

MemoryManager (MM)

  • What it is in gVisor: The component inside the Sentry that emulates virtual memory allocation, page tables, memory mappings (mmap), and memory protections (mprotect) for a specific ThreadGroup.
  • Linux Kernel Equivalent: struct mm_struct. In the Linux kernel, the mm_struct inside task_struct defines the memory footprint of a process. When threads share memory, their task_struct->mm pointers point to the exact same mm_struct. gVisor mimics this by pointing multiple Task structures to a single MemoryManager.

FDTable (File Descriptor Table)

  • What it is in gVisor: An internal table mapped to a ThreadGroup that tracks integer values (file descriptors) and translates them into virtual file objects (vfs.FileDescription) managed inside the Sentry.
  • Linux Kernel Equivalent: struct files_struct / fdtable. In Linux, this is the table that maps your open files (like FD 0, 1, 2) to the kernel's underlying struct file objects.

Quick Reference Summary

To visualize how these concepts translate, use this mapping table:

gVisor Concept Linux Kernel Equivalent Scope / Responsibility
Sandbox No direct equivalent (Closest to a VM boundary) The boundary of the Sentry kernel instance.
Container Host Namespaces + Cgroups A filesystem and resource boundary inside the Sentry.
ThreadGroup Process (task_struct leader) A collection of threads sharing memory and signals.
Task Thread (struct task_struct) The atomic unit of execution and scheduling.
MemoryManager struct mm_struct Manages virtual memory mappings (mmap) for a process.
FDTable struct files_struct Tracks integer File Descriptors for a process.