Kernel API

Generally, userspace applications will not have the capability to message the kernel. Those that can, such as the app store, have full control over starting and stopping all userspace processes.

The kernel runtime task accepts one kind of Request:

#![allow(unused)]
fn main() {
/// IPC format for requests sent to kernel runtime module
#[derive(Debug, Serialize, Deserialize)]
pub enum KernelCommand {
    /// RUNTIME ONLY: used to notify the kernel that booting is complete and
    /// all processes have been loaded in from their persisted or bootstrapped state.
    Booted,
    /// Tell the kernel to install and prepare a new process for execution.
    /// The process will not begin execution until the kernel receives a
    /// `RunProcess` command with the same `id`.
    ///
    /// The process that sends this command will be given messaging capabilities
    /// for the new process if `public` is false.
    ///
    /// All capabilities passed into initial_capabilities must be held by the source
    /// of this message, or the kernel will discard them (silently for now).
    InitializeProcess {
        id: ProcessId,
        wasm_bytes_handle: String,
        wit_version: Option<u32>,
        on_exit: OnExit,
        initial_capabilities: HashSet<Capability>,
        public: bool,
    },
    /// Create an arbitrary capability and grant it to a process.
    GrantCapabilities {
        target: ProcessId,
        capabilities: Vec<Capability>,
    },
    /// Drop capabilities. Does nothing if process doesn't have these caps
    DropCapabilities {
        target: ProcessId,
        capabilities: Vec<Capability>,
    },
    /// Tell the kernel to run a process that has already been installed.
    /// TODO: in the future, this command could be extended to allow for
    /// resource provision.
    RunProcess(ProcessId),
    /// Kill a running process immediately. This may result in the dropping / mishandling of messages!
    KillProcess(ProcessId),
    /// RUNTIME ONLY: notify the kernel that the runtime is shutting down and it
    /// should gracefully stop and persist the running processes.
    Shutdown,
    /// Ask kernel to produce debugging information
    Debug(KernelPrint),
}
}

All KernelCommands are sent in the body field of a Request, serialized to JSON. Only InitializeProcess, RunProcess, and KillProcess will give back a Response, also serialized to JSON text bytes using serde_json:

#![allow(unused)]
fn main() {
pub enum KernelResponse {
    InitializedProcess,       // given back after a successful InitializeProcess
    InitializeProcessError,   // given back after a failed InitializeProcess
    StartedProcess,           // given back after a successful RunProcess
    RunProcessError,          // given back after a failed RunProcess
    KilledProcess(ProcessId), // given back after a KillProcess request
}
}

Booted

Purely for internal use within the kernel. Sent by the kernel, to the kernel, to indicate that all persisted processes have been initialized and are ready to run.

InitializeProcess

The first command used to start a new process. Generally available to apps via the spawn() function in the WIT interface. The wasm_bytes_handle is a pointer generated by the filesystem API — it should be a valid .wasm file compiled using the Kinode tooling. The on_panic field is an enum that specifies what to do if the process panics. The initial_capabilities field is a set of capabilities that the process will have access to — note that the capabilities are signed by this kernel. The public field specifies whether the process should be visible to other processes without needing to grant a messaging capability.

InitializeProcess must be sent with a lazy_load_blob. The blob must be the same .wasm file, in raw bytes, that the wasm_bytes_handle points to.

This will not cause the process to begin running. To do that, send a RunProcess command after a successful InitializeProcess command.

GrantCapabilities

This command directly inserts a list of capabilities into another process' state. While you generally don't want to do this for security reasons, it helps you clean up the "handshake" process by which capabilities must be handed off between two processes before engaging in the business logic. For instance, if you want a kernel module like http_server to be able to message a process back, you do this by directly inserting that "messaging" cap into http_server's store. Only the app_store, terminal, and tester make use of this.

DropCapabilities

This command removes a list of capabilities from another process' state. Currently, no app makes use of this, as it is very powerful.

RunProcess

Takes a process ID and tells kernel to call the init function. The process must have first been initialized with a successful InitializeProcess.

KillProcess

Takes a process ID and kills it. This is a dangerous operation as messages queued for the process will be lost. The process will be removed from the kernel's process table and will no longer be able to receive messages.

Shutdown

Send to the kernel in order to gracefully shut down the system. The runtime must perform this request before exiting in order to see that all processes are properly cleaned up.

Get Help: