Overview
The Portable Operating System Interface (POSIX) is a family of standards specified by the IEEE Computer Society for maintaining compatibility between operating systems. Zephyr implements a subset of the standard POSIX API specified by IEEE 1003.1-2017 (also known as POSIX-1.2017).
POSIX support in Zephyr
Note
This page does not document Zephyr’s POSIX architecture, which is used to run Zephyr as a native application under the host operating system for prototyping, test, and diagnostic purposes.
With the POSIX support available in Zephyr, an existing POSIX conformant application can be ported to run on the Zephyr kernel, and therefore leverage Zephyr features and functionality. Additionally, a library designed to be POSIX conformant can be ported to Zephyr kernel based applications with no changes.
The POSIX API is an increasingly popular OSAL (operating system abstraction layer) for IoT and embedded applications, as can be seen in Zephyr, AWS:FreeRTOS, TI-RTOS, and NuttX.
Benefits of POSIX support in Zephyr include:
Offering a familiar API to non-embedded programmers, especially from Linux
Enabling reuse (portability) of existing libraries based on POSIX APIs
Providing an efficient API subset appropriate for small (MCU) embedded systems
POSIX Subprofiles
While Zephyr supports running multiple threads (possibly in an SMP configuration), as well as Virtual Memory and MMUs, Zephyr code and data normally share a common address space that is partitioned into separate Memory Domains. The Zephyr kernel executable code and the application executable code are typically compiled into the same binary artifact. From that perspective, Zephyr apps can be seen as running in the context of a single process by default; the optional POSIX_MULTI_PROCESS Option Group adds processes as kernel thread groups (see Multi-Process Design).
While multi-purpose operating systems (OS) offer full POSIX conformance, Real-Time Operating Systems (RTOS) such as Zephyr typically serve a fixed-purpose, have limited hardware resources, and experience limited user interaction. In such systems, full POSIX conformance can be impractical and unnecessary.
For that reason, POSIX defined the following Application Environment Profiles (AEP) as part of IEEE 1003.13-2003 (also known as POSIX.13-2003). Each AEP adds incrementally more features over the required POSIX System Interfaces.
POSIX Application Environment Profiles (AEP)
Minimal Realtime System Profile (PSE51)
Realtime Controller System Profile (PSE52)
Dedicated Realtime System Profile (PSE53)
Multi-Purpose Realtime System (PSE54)
POSIX.13-2003 AEP were formalized in 2003 via “Units of Functionality” but the specification is now inactive (for reference only). Nevertheless, the intent is still captured as part of POSIX-1.2017 via Options and Option Groups.
For more information, please see IEEE 1003.1-2017, Section E, Subprofiling Considerations.
POSIX Applications in Zephyr
A POSIX app in Zephyr is built like any other app and therefore requires the
usual prj.conf, CMakeLists.txt, and source code. For example, the app below
leverages the nanosleep() and perror() POSIX functions.
CONFIG_POSIX_AEP_CHOICE_PSE51=y
#include <stddef.h>
#include <stdio.h>
#include <time.h>
void megasleep(size_t megaseconds)
{
struct timespec ts = {
.tv_sec = megaseconds * 1000000,
.tv_nsec = 0,
};
printf("See you in a while!\n");
if (nanosleep(&ts, NULL) == -1) {
perror("nanosleep");
}
}
int main()
{
megasleep(42);
return 0;
}
For more examples of POSIX applications, please see the POSIX sample applications.
Configuration
Like most features in Zephyr, POSIX features are highly configurable but disabled by default. Users must explicitly choose to enable POSIX options via Kconfig selection.
Subprofiles
Applications should enable one of the Kconfig options below to quickly configure a pre-defined POSIX subprofile.
A subprofile enables its Option Groups and Options by default rather than forcing them on: each may be disabled individually, and further Option Groups may be enabled on top. A network appliance without processes, for example, is PSE52 plus networking:
CONFIG_POSIX_AEP_CHOICE_PSE52=y
CONFIG_POSIX_NETWORKING=y
The conformance macros (_POSIX_AEP_REALTIME_MINIMAL, _XOPEN_REALTIME and so on) are
defined only when every constituent of the corresponding profile or Option Group is actually
enabled, so a subtracted profile is reported honestly by <unistd.h> and sysconf().
Libraries should depend on CONFIG_POSIX_SYSTEM_INTERFACES and other
POSIX Option Groups, as needed.
Further fine-tuning may be accomplished via additional POSIX-related Kconfig options.
Application conformance macros
IEEE 1003.1 reserves _POSIX_C_SOURCE and _XOPEN_SOURCE for the application: a source
file states the version of the standard it is written to by defining one of them before it
includes any header, and the headers then expose the matching set of declarations. The
implementation never defines them. Zephyr and posix-next therefore set neither macro globally,
and a library must not either; the global _POSIX_C_SOURCE=200809 of earlier releases was both
the wrong value (the standard’s is 200809L) and a conflict for every application that
defined the right one.
An application chooses its conformance level in its own build files or sources, for example
target_compile_options(app PRIVATE -U_POSIX_C_SOURCE -D_POSIX_C_SOURCE=200809L)
#include #define _POSIX_C_SOURCE 200809L
#include <time.h>
The -U first undefines the value some toolchains predefine, so the application’s definition
is not reported as a redefinition. Defining neither macro is also a valid choice: each C library
then applies its own default namespace. A library that needs a particular level defines it
locally, on its own sources, with target_compile_definitions or zephyr_library_compile_definitions.
There is deliberately no Kconfig choice for the application conformance level: the macro
belongs to a translation unit, not to the system configuration, and a Kconfig symbol would turn
it back into a global definition for every library in the image. The implementation
conformance macros that answer it (_POSIX_VERSION, _POSIX_THREADS, _POSIX_TIMERS
and the other constants of <unistd.h>) are what Kconfig controls, and they report exactly
the Option Groups that are enabled.
Legacy
Historically, Zephyr used CONFIG_POSIX_API to configure a set of POSIX features
that was overloaded and always increasing in size.
The CONFIG_POSIX_API should be considered deprecated and will be removed. It
shall not be used for new applications.
Applications should choose a POSIX subprofile mentioned above.