| # Zircon Kernel objects | |
| [TOC] | |
| Zircon is an object-based kernel. User mode code almost exclusively interacts | |
| with OS resources via object [handles]. A handle can be thought of as an active | |
| session with a specific OS subsystem scoped to a particular resource. | |
| Zircon actively manages the following resources: | |
| + processor time | |
| + memory and address spaces | |
| + device-io memory | |
| + interrupts | |
| + signaling and waiting | |
| + inter-process communication | |
| ## Kernel objects for applications | |
| ### General | |
| + [Clock](/docs/reference/kernel_objects/clock.md) | |
| ### IPC | |
| + [Channel](/docs/reference/kernel_objects/channel.md) | |
| + [Socket](/docs/reference/kernel_objects/socket.md) | |
| + [FIFO](/docs/reference/kernel_objects/fifo.md) | |
| + [Stream](/docs/reference/kernel_objects/stream.md) | |
| + [IOBuffer](/docs/reference/kernel_objects/io_buffer.md) | |
| ### Tasks | |
| + [Process](/docs/reference/kernel_objects/process.md) | |
| + [Thread](/docs/reference/kernel_objects/thread.md) | |
| + [Job](/docs/reference/kernel_objects/job.md) | |
| + [Task](/docs/reference/kernel_objects/task.md) | |
| ### Scheduling | |
| + [Profile](/docs/reference/kernel_objects/profile.md) | |
| ### Signaling | |
| + [Event](/docs/reference/kernel_objects/event.md) | |
| + [Event Pair](/docs/reference/kernel_objects/eventpair.md) | |
| + [Futex](/docs/reference/kernel_objects/futex.md) | |
| + [Counter](/docs/reference/kernel_objects/counter.md) | |
| ### Memory and address space | |
| + [Virtual Memory Object](/docs/reference/kernel_objects/vm_object.md) | |
| + [Virtual Memory Address Region](/docs/reference/kernel_objects/vm_address_region.md) | |
| + [Pager](/docs/reference/kernel_objects/pager.md) | |
| ### Waiting | |
| + [Port](/docs/reference/kernel_objects/port.md) | |
| + [Timer](/docs/reference/kernel_objects/timer.md) | |
| ## Kernel objects for drivers | |
| + [Interrupts](/docs/reference/kernel_objects/interrupts.md) | |
| + [Message Signaled Interrupts](/docs/reference/kernel_objects/msi.md) | |
| + [Resource](/docs/reference/kernel_objects/resource.md) | |
| + [Debuglog](/docs/reference/kernel_objects/debuglog.md) | |
| + [Bus Transaction Initiator](/docs/reference/kernel_objects/bus_transaction_initiator.md) | |
| + [Pinned Memory Token](/docs/reference/kernel_objects/pinned_memory_token.md) | |
| ## Kernel object lifetime | |
| Kernel objects are [reference-counted]. Most kernel objects are | |
| created during a 'create' syscall and are held alive by the first handle, | |
| given as the output of the create syscall. The caller gets the numeric id of | |
| the handle and the handle itself is placed in the handle table of the process. | |
| A handle is held alive as long it exists in the handle table. Handles are | |
| removed from the handle table by: | |
| + Closing them via [`zx_handle_close`] which decrements the reference | |
| count of the corresponding kernel object. Usually, when the last handle is | |
| closed the kernel object reference count will reach 0 which causes the kernel | |
| object to be destroyed. | |
| + When a channel endpoint holding an unread message containing a handle is | |
| destroyed, all of the pending messages will also be destroyed, closing any | |
| handles contained in the messages while doing so. | |
| + When the process that owns the handle table is destroyed. The kernel | |
| effectively iterates over the entire handle table closing each handle in turn. | |
| The reference count increases when new handles (referring to the same object) | |
| are created via [`zx_handle_duplicate`], but also when a direct pointer | |
| reference (by some kernel code) is acquired; therefore a kernel object lifetime | |
| might be longer than the lifetime of the code that created it. A separate count | |
| of active handles referencing an object is also maintained, allowing the kernel | |
| to trigger specific behaviors when the handle count of an object reaches zero, | |
| even if the kernel is keeping the object alive behind the scenes because of a | |
| direct pointer reference. | |
| There are three important cases in which kernel objects are kept alive | |
| when there are no outstanding handles to them: | |
| + The object is referenced by a handle in a message which has not been consumed. | |
| This can happen via the [channel APIs][channel-api]. While such handle is in | |
| the channel the kernel keeps the object alive, and with a non-zero active | |
| handle count. | |
| + The object is the parent of another object which is alive. This is the | |
| case of [VMOs] attached to live [VMARs], of processes with live [threads] and | |
| [jobs] with live processes or child jobs. | |
| + Threads are kept alive by the scheduler. A thread that is alive will continue | |
| to live until it voluntarily exits by calling [`zx_thread_exit`] or the process | |
| is terminated via [`zx_task_kill`]. | |
| The outcome of the last case is that a single thread can keep its process | |
| and the entire lineage of jobs up to the root job alive. | |
| ## Peered object and the peer-closed state | |
| Currently, the kernel defines the following object types as "peered" objects. | |
| Name | Peer-Closed Signal Name | |
| ----------------------------------------------------------+------------------------- | |
| [Channel](/docs/reference/kernel_objects/channel.md) | `ZX_CHANNEL_PEER_CLOSED` | |
| [Socket](/docs/reference/kernel_objects/socket.md) | `ZX_SOCKET_PEER_CLOSED` | |
| [FIFO](/docs/reference/kernel_objects/fifo.md) | `ZX_FIFO_PEER_CLOSED` | |
| [Event Pair](/docs/reference/kernel_objects/eventpair.md) | `ZX_EVENTPAIR_PEER_CLOSED` | |
| [IOBuffer](/docs/reference/kernel_objects/io_buffer.md) | `ZX_IOB_PEER_CLOSED` | |
| All peered objects are created in pairs, which are internally linked to each | |
| other in a peer relationship. When the active handle count of a peered object | |
| reaches 0, if that object still has a link to its peer, the peer object will be | |
| placed in the `PEER_CLOSED` state, causing the link to be destroyed, the | |
| specific `ZX_*_PEER_CLOSED` signal to become asserted on the peer, and for | |
| syscalls involving the object's peer (for example, `zx_channel_write`) to return | |
| the error `ZX_ERR_PEER_CLOSED`. | |
| When the final handle to an object is closed via a call to [`zx_handle_close`], | |
| or [`zx_handle_close_many`], it is guaranteed that the object's peer (if any) | |
| will be placed into the `PEER_CLOSED` state, asserting its associated signal in | |
| the process, before the `zx_handle_close` syscall returns from the kernel. | |
| Note that objects are placed into `PEER_CLOSED` when their peer's _active handle | |
| count_ has hit zero, even of the peer object continues to live because of a | |
| direct pointer reference held by the kernel. | |
| ## Kernel Object security | |
| Kernel objects do not have an intrinsic notion of security and do not do | |
| authorization checks; security rights are held by each handle. A single process | |
| can have two different handles to the same object with different rights. | |
| ## See Also | |
| [Handles][handles] | |
| [handles]: /docs/concepts/kernel/handles.md | |
| [reference-counted]: https://en.wikipedia.org/wiki/Reference_counting | |
| [`zx_handle_close`]: /reference/syscalls/handle_close.md | |
| [`zx_handle_close_many`]: /reference/syscalls/handle_close_many.md | |
| [`zx_handle_duplicate`]: /reference/syscalls/handle_duplicate.md | |
| [`zx_thread_exit`]:/reference/syscalls/thread_exit.md | |
| [`zx_task_kill`]: /reference/syscalls/task_kill.md | |
| [VMOs]: /docs/reference/kernel_objects/vm_object.md | |
| [VMARs]: /docs/reference/kernel_objects/vm_address_region.md | |
| [threads]: /docs/reference/kernel_objects/thread.md | |
| [jobs]: /docs/reference/kernel_objects/job.md | |
| [channel-api]: /docs/reference/kernel_objects/channel.md |