If POSIX
is mentioned as one of the requirements for a
software projects this does not really tell much. POSIX is large
and no project needs everything. The POSIX standard itself is
structured. A base set of interfaces and functionality is
required for all POSIX systems. The size of this base set has
been significantly increased in the 2008 revision. Other parts of
specification
are optional. The system signals the availability of the
functionality in the C programming environment by certain macros
which are defined after <unistd.h> is included.
Based on these options and option groups one can define profiles which further group some options which are needed for a certain purpose. An effort is currently underway to define a hierachy of profiles for embedded systems. For a user/programmer to see whether her program works with a system she first would have to desribe the minimal profile. This minimal profile includes all the options and option groups which absolutely have to be available. Given this profile it then is possible to look at the profiles a system provides (there can be more than one profile). If at least one profile is a superset of the requirement profile the application should work.
Some of the option groups contain a lot of functionality. The POSIX developers considered the functionality of the option group (at least until today) as atomic but in reality there might be room for more differentiation. The following document will refine option groups to provide more information about those option groups which are not completely implemented.
All the system-specific information is for Linux only. I could not care less about the status for other OSes.
What I listed here are the option groups from IEEE 1003.1-2001/XPG 6 or whatever you want to call it. The list of options in IEEE 1003.1-2008 is significantly shorted. For documentation purposes the now mandatory options are still listed below. The <unistd.h> contains the complete list.
The value of the macros is normally -1, 0, or a specific number indicating year and month of the POSIX.1 revision which introduced the option. The Linux headers follow the rules for the symbol and define them to -1 if the functionality is never available, to 0 if the program has to check at runtime (using fpathconf(), pathconf(), sysconf()) whether the functionality is available, or to the constant greater than zero to indicate the option is always available. The definition do vary between different architectures.
The definition related to what used to be POSIX.2 are left out.
The following is the list of macros as required in the 2008 revision.
The Unix standard groups certain options together and so forming option groups.
The Realtime option group consists of the following options:
All options except _POSIX_PRIORITIZED_IO are mandatory if this option group is claimed to be supported.
The Advanced Realtime option group consists of the following options:
If support for this option group is claimed all options must be defined.
The Realtime Threads option group consists of the following options:
If support for this option group is claimed all options must be defined.
The Advanced Realtime Threads option group consists of the following options:
If support for this option group is claimed all options must be defined.
The Tracing option group consists of the following options:
If support for this option group is claimed all options must be defined.
This is a bunch of more or less (un)related functions. posix_fadvise() and posix_madvise() help the OS to optimize access to files and memory mapped using mmap(). posix_fallocate() allows to pre-allocate disk space which can be a performance optimization (since the storage can be allocate sequentially. It is also a method to ensure that enough memory is available right away. Normally files, set to a certain size using ftruncate(), are allocate sparsely, i.e., without actually allocating disk space for all the blocks. The last function, posix_memalign(), allows allocating memory with a given alignment. A function with this semantics was widely available as memalign(). Its functionality can be implemented by the user with only malloc() but this can waste resources.
posix_fadvise() is implemented in the 2.5 kernel and used in recent glibc versions. posix_madvise() is mostly implemented but the implementation is based on the older BSD madvise() interface. posix_fallocate() is implemented entirely at user level by writing blocks of zeros. According to Stephen Tweedie it makes not much sense to move this functionality into the kernel. I don't know whether this is true. posix_memalign() is completely implemented.
Asynchronous I/O serves two purposes: first it allows the program to continue doing what is has to do without waiting for I/O to complete. If it is determined that the I/O results are not anymore needed the I/O request can be canceled. Second, it provides the OS the opportunity to optimize the I/O processing multiple requests at once.
Linux has for some time an almost 100% compliant implementation of AIO. The implementation is entirely at user-level. This means it is not taking advantage of all the possibilities the use of AIO provide.
For the 2.5 kernel Ben LaHaise implemented a kernel implementation. The kernel interface does not correspond to the POSIX AIO interface so there is significant effort at the user-level necessary. The result is very much better since the kernel gets complete control over the I/O.
Red Hat Enterprise Linux comes with a kernel-supported AIO implementation which is based on the functionality in the 2.5 kernel. RHEL3 even supports AIO on pipes and sockets. Due to changes in the 2.6 kernel the support in RHEL4 is reduced to file descriptors which bypass filesystem caching.
This option is mandatory in IEEE 1003.1-2008.
Barriers are one of the most recent extensions to the thread functionality. Rendezvous are of part of algorithms performing calculations in multiple threads.
The thread library on Linux implements these functions completely since version 2.2. There is as of this writing no other non-embedded OS with support for these interfaces.
This option is mandatory in IEEE 1003.1-2008.
If this option is defined changing the owner of filesystem objects is restricted. Normally only the super user is allowed to do this.
Linux defined this option since day one.
This option is mandatory in IEEE 1003.1-2001 and later.
This options lumps together three different groups of functions. Basically, they all add support for clocks other than the normal realtime clock. The latter is what is used implicitly everywhere time is measured unless explicitly stated otherwise. But this clock might have limitations such as precision.
The pthread_condattr_getclock() and pthread_condattr_setclock() allow to specify the clock which is used in pthread_cond_timedwait(). clock_nanosleep() is a superset of nanosleep(). It allows using alternative clocks but it also allows to specify absolute timeouts. clock_settime() is the interface to set any of the clocks which can be set.
Update: The Linux kernel version 2.5.64 and later provide the necessary support. glibc 2.3.3 with NPTL supports this option.
This option is mandatory in IEEE 1003.1-2008.
Some architectures provide user-level access to a very high-resolution clock the processor implements. Normally this simply a counter of cycles the chip is driven by. To be useful for this option the clock must not turn around often. For this reason Alpha does not have this option available although the architecture has a CPU cycle counter available. But its 32-bit size limit the usefulness.
Other processors, IA-32, IA-64 and perhaps more in future, do have a cycle counter register. The interfaces of this option provide support to use these registers without resorting to architecture specific code. The information is provided in nanoseconds and not in cycle counts.
Warning: Before the 2.6.10 kernel the CPU clock implementation we use might not be what other people want. The clocks basically measured wallclock time using CPU registers. This changed in 2.6.10 when new system calls were added and now scheduling can be taken into account. Now the clocks show the time which the system actually spent on the process/thread. Just like ru_utime/ru_stime info in struct rusage but available at all times.
Before the 2.6.10 kernel some support was available for processors with easy access to CPU cycle counters. For some architectures, like PPC, the great variety of CPU implementations based on the architecture complicate things and nothing has be done to solve the issue.
Update: After 2.6.10 support for all architectures and the correct semantics is available. The precision might vary between the architectures.
This option marks the fsync() interface which might not be useful or implementable on some system but Linux had it forever.
Is implemented since the very early days.
This option is signals support for the IPv6 protocol in addition to IPv4. To support IPv6 a number of new interfaces were introduced and some existing interfaces extended. It also means that a number of interfaces which were used with IPv4 cannot be used anymore in protocol-independent code.
IPv6 is usable in Linux since at least the Linux 2.4 days.
This option is mandatory in IEEE 1003.1-2008.
This option is another remembrance of the old days of very simple system. Job control was always available on Linux. Processes could always be sent to the background etc.
Is implemented since the very early days.
This option is mandatory in IEEE 1003.1-2001 and later.
Support for mapping files into the address space is one of the main requirements of shared library implementations. Otherwise the "shared" part couldn't be implemented. Linux got support for this very early on and all kernel versions the current ABI support have this features.
The only possible reason this feature is missing could be if it is deliberately left out which could make sense to strip a kernel down a bit more for the use in embedded systems where shared libraries are often not a requirement.
Is implemented since the very early days.
This option is mandatory in IEEE 1003.1-2008.
Mapping file contents in the address space allows the OS to optimize the handling of the needed memory by loading the data only when really needed and evacuate portions of already loaded data when the memory is needed otherwise. If delay associated with the overhead to load the data on demand is not acceptable the data can be forced to stay in memory. This feature is also available for all currently support kernel versions.
Is implemented since the very early days.
A bit more flexible than the functionality of _POSIX_MEMLOCK this options allows to lock parts of a file in memory. This feature is also available in all supported Linux kernel versions.
Is implemented since the very early days.
Changing the access protection of mapped memory regions is useful for many purposes. A reliable implementation of shared libraries requires it and therefore this feature is available in all support kernel versions.
Is implemented since the very early days.
This option is mandatory in IEEE 1003.1-2008.
POSIX message queues are used, similar to the SysV message queues, to pass information between different threads and/or processes. It is often faster to use than pipes and more flexible since multiple producers and consumers can use the same message queue. Plus, using SIGEV_THREAD it is possible to implement a kind of remote procedure call.
The implementation of POSIX message queues requires kernel support which got added after 2.6.5 (i.e., 2.6.6 will be the first official kernel with the support). The librt in glibc 2.3.4 after 2004-4-12 includes the necessary userlevel support.
The monotonic clock was introduced to allow the user to implement relative timeouts. The problem with the realtime clock which normally is used is that it can be reset with the consequence that timeouts maybe be lengthened or shortened depending on the direction of the clock adjustment. But the availability of this option also means that all interface which normally would use the realtime clock by default now use the monotonic clock which can lead to problem since this is not expected by most of the code written up to this day.
Update: glibc 2.3.3 has support for the functions governed by this option based on support in the 2.5 kernel. Older glibc versions had a userlevel implementation of limited quality and only for CLOCK_REALTIME..
This feature was a bad compromise for some broken systems. Long filenames were silently truncated generating surprising effects and security holes. Fortunately support for this option is now required.
Linux always supported this option.
This option is mandatory in IEEE 1003.1-2001 and later.
Asynchronous I/O provides the possibility to queue many I/O requests and have them worked on while the program can concentrate on other code. How and when the requests are worked on is up to the implementation to decide. This is sometimes not enough. Important data might have to be preferred. The AIO interface provides a mean to define priorities for I/O requests if this feature is available.
This is a matter-of-quality item on the checklist for the AIO implementation. The current user-level implementation has the necessary support available. The new kernel-level implementation will hopefully also have the needed support.
In situations where certain actions have to be performed as fast as possible the scheduling and priority of threads and processes can be changed. This will allow preferring certain threads and processes over others. In embedded systems which react on outside an stimulus and have to perform an action promptly this is important. But also desktop systems benefit, for instance, for video and audio recording and display.
If the _POSIX_SPAWN option is defined the following interfaces are available as well:
The Linux kernel supports realtime scheduling for many years now.
Raw sockets were a disputed socket type when the discussion was made about including them in the POSIX standard. The problem is that not much can be specified generally without consideration of the kind of socket which is manipulated.
The Linux kernel implements raw sockets for all kinds of socket types. The standard behavior is implemented as are many more features.
Reader-writer locks are a special kind of mutex which allows multiple readers at any one time but only one writer. In situations where the protected data is more often read than written using these mutexes is of benefit.
Reader-writer locks are implemented in the thread library for many years, even before they were added to the POSIX standard. The implementation provides two versions: a version which prefers readers and one which prefers writers.
This option is mandatory in IEEE 1003.1-2008. Even in IEEE 1003.1-2001 the functions must always be available if threads are supported.
Standard Unix signals have several drawbacks. First, they do not queue. If one signal of a kind is pending new ones are simply discarded. Second, the signal cannot carry any information which requires either the use of several different signals to transmit information or some mechanism outside the signal handler has be used (e.g., global variables) which has its own set of problems.
Realtime signals do queue and can transmit information. They also solve problems related to existing signals. E.g., the SIGSEGV can now transmit all the information to locate the reason of the segmentation fault.
Realtime signals are implement for many years and are in wide use.
This option is mandatory in IEEE 1003.1-2008.
Regular expressions were one of the big inventions of the original POSIX standard and although some people prefer other regular expression implementations the POSIX version prevailed in most situations. It provides all the necessary features and is widely available.
Regular expressions were always available in glibc. The quality of the implementation is another issues. Until glibc 2.3 there were issues with some border cases but internationalization features were available (unlike in most other implementations). Starting with glibc 2.3 a new implementation is available and it should fix the remaining problems with compliance to the standard. Full internationalization support is included as well.
This option is mandatory in IEEE 1003.1-2001 and later.
A process having effective and normal user and group IDs are a mean to increase security. Early POSIX standards didn't require support because some systems at that time didn't provide the feature. The alignment of the latest POSIX standard with FIPS makes this feature mandatory.
Linux always support saved IDs. The kernel even provides finer-grained IDs which functions which determine the access rights to files.
This option is mandatory in IEEE 1003.1-2001 and later.
Semaphores were added to POSIX not as part of the thread package but as a separate set of interfaces. The interface allows easy use of semaphores in different processes by creating named semaphore objects. At the same time anonymous semaphores are available for the use in multi-threaded applications.
glibc 2.3 with NPTL has full support for semaphores, including named semaphores and inter-process semaphores. Earlier glibc versions have only support for anonymous semaphores.
This option is mandatory in IEEE 1003.1-2008.
POSIX shared memory could theoretically be implemented without special kernel support but the implementation wouldn't be optimized and it would, depending on the setup, be a security problem. The 2.2 series of the kernel introduced a special filesystem type to support shared memory (refined in the 2.4 series) which allowed creating files without backing them with space on a device.
Starting with glibc 2.1 support for POSIX shared memory was available. But each system must be configured to provide the necessary filesystem.
This option was introduced to allow creating profiles for embedded systems which don't need shells and command lines. Non-embedded systems always have a shell.
The POSIX standard requires that system() is usable in multi-threaded applications but this is hardly ever implemented correctly since the implementation has to change global state.
Normal Linux setups always have a shell and this option defined. glibc 2.3.2 with NPTL support should even implement the multi-threaded application requirement correctly.
This option is mandatory in IEEE 1003.1-2001 and later.
To support multiple processes on systems without MMU support something other than the fork() and exec POSIX model is needed. The solution is the spawn family of functions. The functions can be implemented in the kernel. This way the kernel can avoid the fork() step. For systems which do support fork() the functions can be implemented at user-level.
Starting with version 2.2 glibc has a user-level implementation of these interfaces.
Spinlocks are a form of synchronization primitive which can be used only in carefully chosen situation. If programs which use threads with different priorities every use of a spinlock in a thread which does not have the highest priority is a gamble. But if spinlocks are usable they provide significant speed advantages.
Spinlocks are implemented since glibc 2.2. Even the inter-process variant is available since it does not require kernel support.
This option is mandatory in IEEE 1003.1-2008.
This option introduces a special scheduling variant for certain situations which seem important enough. The specification is very vague and such an option is of questionable usefulness since not very generic.
The Linux kernel does not implement this scheduling option. No effort to add such support is known.
To create a consistent state when it comes to disk I/O it is necessary to force all output from the buffers the kernel uses to the underlying device. With this option the POSIX standard provide a number of different ways to make this possible.
At least with the 2.4 kernels all the necessary support is in place. All the interfaces and functionality required by POSIX are available.
Each new thread has to have its own stack and all the stacks of the different threads in a process are in the same address space. Where the stacks are allocated is by default the thread libraries issue. If the use of the address space is an issue, as it sometimes is on 32-bit machine, the application can make the decision by determining the stack address explicitly. The stack is in this case allocated by the user.
This option is implemented since glibc 2.1 for those architectures which provide a thread register. Since a thread register is a prerequisite for NPTL these functions are always supported for this thread library.
Each new thread has to have its own stack and all the stacks of the different threads in a process are in the same address space. This can create two kinds of problems:
This option is implemented since glibc 2.1 for those architectures which provide a thread register. Since a thread register is a prerequisite for NPTL these functions are always supported for this thread library.
This option is similar to the _POSIX_CPUTIME option only that the time starts at zero for each individual thread.
This option is implemented in glibc 2.2. The system must fulfill the same requirements as for the _POSIX_CPUTIME option, namely that the CPU must support a cycle counter register.
This option can lead to better handling of threads with different priorities. If a high-priority thread is waiting on a mutex which is held by a lower-priority thread the latter is continuing to use its own priority although it blocks a thread with a higher priority. If this option is defined the user can define a mutex which automatically adjusts the priority of the thread holding the mutex based on the priority of the waiters.
The 2.6.18 kernel has the necessary support to implement this option. PI futexes are enabled in (almost?) all configurations. The thread library changes are in version 2.5 which starts to be available in Fedora Core 6 and RHEL5.
This option can lead to better handling of threads with different priorities. If a high-priority thread is waiting on a mutex which is held by a lower-priority thread the latter is continuing to use its own priority although it blocks a thread with a higher priority. If this option is defined the user can define a mutex which always increases the priority to a given level regardless of whether there are waiters or not.
This option is implemented for NPTL since August 2006. FC6 and RHEL5 will have this option. It is a userlevel implemention but it is believed to be compliant. The implementation does not support priority protection for robust mutexes. But since robust mutexes are not (yet) part of POSIX this has no effect on this option.
If this option is defined the different threads inside a process can run with different priorities and/or different schedulers.
This option is implemented in the LinuxThread library since glibc 2.1. NPTL does not support this option so far since there the priority protection support is not yet present.
The synchronization primitives provided by the thread library can normally only be used among threads in the same process. They are also useful to synchronize between different processes or threads therein but this support requires help from the kernel.
Not part of this option (since derived not from the thread extensions to POSIX) are the POSIX semaphore functions. The sem_init() interface's second parameter allows controlling inter-process sharing. An implementation is usually linked with the implementation of this option.
The kernel support for this option wasn't available until 2.5.7. Future versions of the thread library will support this option.
Update: The Native POSIX Thread Library has support for all the functions governed by this option, including sem_init().
Some of the interfaces in the POSIX standard are not thread-safe and some are changed noticeably in complexity and performance. For some but not all not thread-safe functions the POSIX standard defines variants if this option is present. The functions which were changed greatly speed-wise by the introduction of threads include the standard I/O function for which POSIX defines variants which can be implemented just like the functions in pre-thread times.
All the mentioned functions (and more) are implemented in glibc.
This option is mandatory in IEEE 1003.1-2008.
Just like the _POSIX_SPORADIC_SERVER option this option provides support for one more scheduler.
This option cannot be implemented if _POSIX_SPORADIC_SERVER cannot be implemented.
If this option is defined the functions to provide basic support for POSIX threads are available.
All the mentioned functions are available. The current implentation (NPTL) is, as far as it is known today, fully POSIX compliant. The same cannot be said for the now obsolete LinuxThreads implementations.
This option is mandatory in IEEE 1003.1-2008.
Initially only the conditional variable API had the functionality of a timeout for the operations which might block. But this is a generally needed functionality.
The last interfaces to be added were the POSIX message queue functions which are available in the 2.6.6 kernel and 2.3.4 glibc.
This option is mandatory in IEEE 1003.1-2008.
The asynchronous creation of timeouts (one-time and interval) in early Unix version was limited to the setitimer() function which sends a signals. Users demanded more flexibility and the result was the introduction of POSIX timers which not only allow sending arbitrary signals. The full functionality of realtime signals is available and instead of sending signals the functions could also create threads.
A user-level implementation of the interfaces is available in glibc 2.2. The overall performance is not the best, the clocks to use are restricted to only the realtime clock, and because of that the resolution is limited. With a 2.5 kernel and glibc 2.3.3 or up kernel support is available which also includes support for CLOCK_MONOTONIC.
This option is mandatory in IEEE 1003.1-2008.
POSIX tracing is a mechanism to collect information about a running process and eventually all the children. Events are generated by the user-program itself, the system, or other processes.
The functionality of this option isn't implemented as of glibc 2.3. Any implementation requires kernel support which is unlikely to be added.
This option has been obsoleted in IEEE 1003.1-2008.
This option is defined on top of _POSIX_TRACE. If set the user can register functions which discard some of the information which normally would be written into the trace file.
The functionality of this option isn't implemented as of glibc 2.3. Any implementation requires kernel support which is unlikely to be added.
This option has been obsoleted in IEEE 1003.1-2008.
This option is defined on top of _POSIX_TRACE. It allows to define how programs started from a traced program behave.
The functionality of this option isn't implemented as of glibc 2.3. Any implementation requires kernel support which is unlikely to be added.
This option has been obsoleted in IEEE 1003.1-2008.
This option is defined on top of _POSIX_TRACE. It allows to log to trace output.
The functionality of this option isn't implemented as of glibc 2.3. Any implementation requires kernel support which is unlikely to be added.
This option has been obsoleted in IEEE 1003.1-2008.
Typed memory objects are similar to shared memory but there is no requirement that they are backed by a device. Instead typed memory objects are identified by names which can mean everything. It would for instance useful to provide the video memory of a system a symbolic name and then access it with this name.
The functionality of this option isn't implemented as of glibc 2.3.
If this option is available the crypt() function family is available. Even though the standard implementation is based on DES; a real encryption mechanism, the functions cannot be used for this purpose. They are only useful for password verification.
These functions are available and since the lifting of the export restrictions they are available in the default package. The functions implement the DES encryption method as well as a non-standard implementation based on MD5.
This option was introduced in XPG4.2 to enable various variants of functions which were improved for use in internationalized applications. Since then this option was folded into XSI.
All the functions which were defined by this option are available in glibc.
If it is decided to discontinue an interface in Unix/POSIX the interface first has to be declared as legacy. Only after being legacy for at least one release can the interface be removed. The set of legacy interfaces therefore changes with every release. None of the interfaces in this category should be used in newly written code.
All these interfaces are and will be available in glibc.
The System V network code used the more structured STREAMS support instead of the more basic use of socket. Due to misdesign of the STREAMS interfaces (not the basic concept) STREAMS become more and more impractical. In addition do many OSes not provide a STREAMS implementation.
The standard Linux kernel does not provide support for STREAMS. But there are third-party kernel modules which implement the behavior. glibc is prepared to take advantage of the eventually available kernel module. If the module is not present the functions defined in glibc always fail..
This option has been obsoleted in IEEE 1003.1-2008.