Sie sind auf Seite 1von 11

A STUDY ON POSIX

REAL-TIME EXTENSION

Author: Thang Minh Le


thangmle@gmail.com
INTRODUCTION

REAL-TIME COMPUTING

Real-time computing is not a new topic in computer science. It originally emerged from the need
of building systems where timing constraint was critical. The concept of fast response time has
been around since 1940s. According to [1], Laptante believed that the first ‘real-time’ system
was built in project Whirlwind during Second World War. For decades, real-time computing has
drawn a lot of attentions from researchers. Substantial improvements have been introduced to the
field in order to achieve better results in term of efficiency and reliability. Despite all effort has
been made, the topic is still remained challenging to researchers at all time.

Real-time system is an interesting topic. A system claims to be real-time if it is designed to


operate within a real-time domain. This domain is constructed by cascading the real-time
requirement of one component to all of other components to which it interacts in the system. The
cascading process continues and applies to all related components including hardware devices.
Because of this unique restrict of real-time systems, in the 1960s, real-time computers were
considered the largest most complex technical systems ever conceived [1]. In contrast with real-
time systems, non-real-time systems do not require all of their components to operate in real-
time manner. In fact, it is preferred to have them operating in non-real-time for better
performance.

Real-time systems are used in most embedded devices which are designed for their own purpose.
Real-time software industry has moved to a better standardized way which adopts real-time
operating system (RTOS) as an operating system for real-time embedded devices. A RTOS is
designed to meet certain real-time requirements in order to provide a desired runtime
environment to its applications. Real-time applications are different in their own will. However,
real-time operating systems seem to share the same set of requirements with respect to real-time
computing. The most important contract of a RTOS to its applications is to provide a
deterministic or predictable response time per executing task. This is directly derived from the
POSIX definition of real-time in operating system: “the ability of the operating system to
provide a required level of service in a bounded response time” [2]. Accordingly, real-time
application designers must be able to determine the amount of the worst case execution time per
task. In hard real-time systems, this amount must be bounded for all time. In soft real-time
systems, this restriction is relaxed a bit to allow unbounded worst case execution time from time
to time. It must be clear that real-time should not be confused with getting immediate
results/responses. It is simply because a faster response time can be achieved by running an
application on a super-computer compared with a desktop computer. However, such
achievement does not mean the application is executing in real-time manner. Indeed, it is
suggested that response time must be bounded and the range is a function of the application the
computer is serving [1].

POSIX REAL-TIME EXTENSION

POSIX, as it stands for Portable Operating System Interface for UNIX, is an evolving set of
standard APIs. The main purpose of POSIX standards is to promote portability of applications
among operating systems. POSIX achieve its goal by standardizing operating system interface

2
and environment based on UNIX. POSIX adopts open software architecture to address issues of
interoperability and portability. It defines a standard way for an application to interface with the
operating system. Operating systems conforms to POSIX standards must implement their
services following the definition and interface defined in corresponding POSIX APIs. It is to
guarantee that the use of the same API in different POSIX compliant systems retrieves the same
result. The original POSIX standard was first published in 1990. It is now a family of over 30
specifications for everything ranging from basic operating system services to testing the
conformance to the standard.

Including in POSIX standards is POSIX real-time extension which takes an important role in
standardizing real-time operating systems. Finding a common interface suitable for real-time
applications is far more challenging. These applications usually demand low latency and
efficient execution. Meanwhile, the POSIX basic standard is too heavy causing compliant
systems to perform poorly in real-time requirement. As a result, real-time applications tend to
call internal interfaces provided by the RTOS to achieve efficiency. In addition, there exists a
large number of real-time operating systems with variations in their implementation makes a
portable task for real-time applications unforeseeable. Facing with these issues, a working group
was established in POSIX to “develop standards which are the minimum syntactic and semantics
changes or additions to POSIX standards to support portability of applications with real-time
requirements” [2]. A series of POSIX real-time standards were released including:

• IEEE Std 1003.1b-1993 Real-time Extension


• IEEE Std 1003.1c-1995 Threads
• IEEE Std 1003.1d-1999 Additional Real-time Extensions
• IEEE Std 1003.1j-2000 Advanced Real-time Extensions
• IEEE Std 1003.1q-2000 Tracing
• IEEE Std 1003.13-1998 Real-time Application Environment Profiles (AEPs)

3
POSIX real-time extension 1003.1b and 1003.1c are most commonly implemented in real-time
operating systems. They were approved by IEEE and ISO/IEC and have been integrated into
POSIX 1003.1 base standard.

POSIX 1003.1b covers the most important part of real-time operating system. For this reason,
this study mainly focuses on POSIX real-time extension 1003.1b which includes:

 Real-time signals: additional signals with multiple levels of priority.


 Clock and Timer: periodic timer delivery with the help of POSIX signals.
 Shared Memory and Memory Locking: sharing memory and prevent virtual memory
swapping in/out.
 Priority Scheduling: fixed priority pre-emptive scheduling with a minimum of 32
priority levels.

POSIX 1003.13 is another important standard which is also briefly discussed in this study.

4
POSIX 1003.1b

Real-time Signal

Signal in POSIX standard is a notifying mechanism used in inter-process communication. A


signal is generated as a result of the event that causes the signal first occurs. Events can be either
internal or external. Such these events can be anything from detection of hardware faults to timer
expiration. An operating system sends a notification message to a process under the format of
POSIX signal based upon a particular event. When the process accepts the signal and handles it,
the signal handler associated with this signal is entered. This progress is similar to the system
entering an interrupt handler as the result of receiving an interrupt. Signal is an important
concept in operating system design. POSIX defined a list of standard signals which represented a
set of common events and recommended POSIX compliant operating systems should at least
support these.

Many signals defined in POSIX 1003.1 are primarily


reserved for operating system. SIGURS1 and SIGUSR2
signals are the two used by applications. Signals can be
generated in synchronous manner, asynchronous
manner or explicitly by a process or a thread.
Traditional signals presents “some drawbacks to be
used in real-time application: too few number of
signals for application use, no priority on signal
delivery, limited information content associated to
signal, signal lost due to not queuing, among other
problems” [3].

POSIX 1003.1b extended the standard signal structure


by adding more signals for application use. The
macros SIGRTMIN and SIGRTMAX specify a range of
signal numbers that are reserved for application use.
RTOS must support at least RTSIG_MAX signal
numbers.

Another important feature introduced signal real-time


extension is the ability to queue real-time signals.
“Historical implementations of signals, using the
signal() function, have shortcomings that make them
unreliable for many application uses” [2]. To address
this reliable issue, real-time signals are now queued in
the system. When a process is blocked and unable to
handle generated signals designated to it, these signals
will be queued by the operating system. Once the
process is able to handle signals, these signals will be
de-queued and are delivered to the process without any
lost. The delivery of queued signals follows the

5
lowest-numbered signal first mechanism. This feature allows applications to use number to be a
signal priority. Signals might be failed to be queued in cases when there is no free space in the
queue. SIGQUEUE_MAX is used to define maximum size of the queue.

Union sigval was introduced in real-time signal extension. The union is used to pass a value
along with a signal. As a result, signals now can have extra information associated with them.
This information then can be used to help applications to identify the source of the signal.
Sigwaitinfo() and sigtimedwait() were added to support real-time signals. Sigwaitinfo() is similar
to the existing sigwait() but it is more dedicated to handle real-time signal which has the ability
to return additional information. Sigtimedwait() is the same as sigwaitinfo() with additional
feature which allows process/thread to wait within timeout unit.

In brief, introducing queuing feature for real-time signals is a big improvement. However, it also
creates some disadvantages:
 In term of performance, “queuing a signal implies reduced performance in a security-
conscious implementation as the access permissions between the sender and receiver
have to be checked on each send when the pid is resolved into a target process” [2].
 Another aspect is the size of the queue is fixed. Without setting correct value for the
queue’s size, signal might get lost. However, running into this situation might be rare
thanks to only signals with sa_flags field set to SA_SIGINFO are queued.
 Queuing duplicated signal is another problem. Duplicated signals existing in the queue
are considered wasted and might cause some overhead due to the same signal handler
being executed many times. In most cases, these re-executions are unnecessary and
should be avoided.

Using signal number to be the priority level when delivering the signal to a process from the
queue is misleading. In software design, the same field serving two different purposes is ‘double
duties’ which is not recommended. A better way is to use ‘signal owner’ concept to obtain signal
priority value. “The signal owner is defined as the thread that installed the signal handler last,
or that made a call to any of sigwait() functions last” [3]. Signal when it stands alone outside of
its creation context has no meaning of priority level. In this case, it is reasonable to use its signal
number as its priority level. However, when considering its creation context, the use of signal
number for its priority level is inappropriate. The context in which a signal is generated is very
important. A signal generated during performing a high priority task must have higher priority
than the same signal (same signal number) generated during performing a lower priority task. In
this case, the two signals have the same signal number but they must have different priority
levels. It is important that signal structure should have an extra field to store its priority value
which must be different from its signal number. The priority level of a signal can be obtained by
using ‘signal owner’ concept or inheriting from its creation process by default or being explicitly
set to a correct value at runtime by applications.

Also, real-time signal should have a field to indicate ‘deadline’ value which should be relative to
its creation time. It is not necessary that two signals which are created at the same time and have
the same signal number must have the same deadline. Again, the context when a signal is created
might affect its deadline value. Real-time tasks thrive to finish within their deadline. So do real-
time signals. The interval of time when a real-time signal is created till it is accepted is
undetermined in most POSIX compliant real-time systems. During this time, the signal is in
pending state. The pending period is longer or shorter depends on the implementation and the
workload of the system at that time. POSIX standard does not clearly mention when a signal
6
must be delivered to its targeted process. Hence, ‘deadline’ field is necessary since real-time
applications can depend on this value to determine whether a signal is already expired when it is
accepted and perform necessary logic accordingly.

Priority scheduling

Scheduling is the heart of real-time operating systems. Because of its importance, it has been the
most discussed topic since the beginning of real-time computing. Scheduling research has been
split into two categories: runtime scheduling and pre-runtime scheduling. In term of runtime
scheduling approach, priority based scheduling is the most widely adopted in many RTOSs.
POSIX real-time extension used priority scheduling as the standard scheduling for its compliant
systems. Real-time specification for Java (RTSJ) also adopted priority based scheduling as its
standard scheduling.

Priority based scheduling is proven to be a good candidate for runtime scheduling in RTOS. The
most importance of priority scheduling supporting real-time requirements is that “it is
deterministic: the highest-priority process is always run and, among processes of equal priority,
the process that has been runnable for the longest time is executed first” [2]. In priority
scheduling, a real-time application is responsible for controlling the execution sequence of its
processes to meet the correctness and response time requirements. The real-time application
gains this control through the value it set to processes’ priority. It is the responsibility of
application logic to make rational priority assignments. RTOS, in return, must respect process
priority value and perform scheduling processes:
 System scheduler always dispatches a process that has the highest (generally the most
time-critical) priority among all runnable processes in the system.
 In fixed priority scheduling system, process priority must not be altered.

By default, SCHED_FIFO is used to resolve the case of processes having the same priority
value. Besides, POSIX 1003.1b requires these basic scheduling polices supported in its
compliant RTOS:
 SCHED_RR: Round robin scheduling policy.
 SCHED_SPORADIC: Sporadic server scheduling policy.
 SCHED_OTHER: Another scheduling policy.

While POSIX 1003.1 provided details of process preemption behavior, it did not mention the
expectation for resource preemption. Preempting a process without handling its holding
resources leads to the well-known priority inversion problem. The problem relates to resource
contention where a low priority process whose holds a lock on a resource is preempted by a
higher priority task which, in turn, is locked by the lower priority process during acquiring lock
on the same resource.

Two scenarios can happen in priority inversion. They were defined in [4] as follow:
 Bounded priority inversion, shown in Figure 1, occurs when low-priority Task L acquires
a lock on a shared resource, but before releasing the resource is preempted by high-
priority Task H. Task H attempts to acquire the resource but is forced to wait for Task L
to finish its critical section. Task L continues running until it releases the resource, at
which point Task H acquires the resource and resumes executing. The worst-case wait
time for Task H is equal to the length of the critical section of Task L.

7
 Unbounded priority inversion, shown in Figure 2, occurs when an intervening task
extends a bounded priority inversion, possibly forever. In the previous example, suppose
medium-priority Task M preempts Task L during the execution of Task L's critical
section. Task M runs until it relinquishes control of the processor. Only when Task M
turns over control can Task L finish executing its critical section and release the shared
resource. This extension of the critical region leads to unbounded priority inversion.
When Task L releases the resource, Task H can finally acquire the resource and resume
execution. The worst-case wait time for Task H is now equal to the sum of the worst-case
execution times of Task M and the critical section of Task L.

Priority ceiling protocol and priority inheritance protocol are the two most known solutions to
priority inversion problem. The two protocols work by temporarily changing process priority at
runtime. This effectively violates the requirement of fixed priority scheduling as applications
should control process priority not RTOSs. Changing priority of a process without thoroughly
testing it might cause unexpected behaviors. Although priority ceiling and priority inheritance
both prevent unbounded priority inversion, neither protocol prevents bounded priority inversion.
It's generally simpler to avoid priority inversion than to solve it in software [4]. If priority
inversion is impossible to avoid, it is sufficient that the two processes involved in the problem
perform some agreement upon executing either priority ceiling protocol or priority inheritance
protocol. This way forces real-time application implementations to be well-prepared in handling
this problem if it ever occurs.

Despite all of the advantages when using priority based scheduling in RTOS, there are some
concerns regarding this scheduling. Using priority based scheduling might not suitable for hard
real-time system. Priority is somewhat unrelated to real-time. Using priority based scheduling as
a solution to meet real-time requirements is unclear. The correctness of this approach has not
been proved in any papers. Real-time by its definition is the ability of determining the worst case
execution time of a task. However, using priority alone can only satisfy the real-time requirement
of the highest priority task in a system. Once the highest task is available, it is executed
immediately and hence the waiting time factor can be eliminated. In contrast, a real-time task
which has lower priority has its execution time unbounded since there is no way to know when
this task will be executed.

In priority based scheduling, a real-time application is responsible for determining when its
processes will run in relation to each other. This task is not trivial. In hard real-time systems with
high computational complexity, finding an off-line feasible schedule for a set of processes which
must satisfy all of their constraints and deadlines is easily proved to be NP-hard matter [5].
Given this, finding a proper priority scheme for a real-time application in hard real-time
requirement at runtime is even harder leading to impossible. It is because there is no guarantee
that using priority based scheduling at runtime satisfies all timing constraints [6]. In soft real-
time requirement, priority based scheduling is sufficient. Nevertheless, one can take advantage of
pre-run-time scheduling algorithm to help in finding priority scheme for a set of processes of a

8
given real-time application. Such an example of pre-run-time scheduling algorithm was
described in [5].

Shared Memory & Memory Locking

Memory management is another important aspect of real-time application. POSIX real-time


extension introduced some great features including memory locking, memory mapped file and
memory protection to manage memory more efficiently. In-used memory of a process might be
paged out in the case of shortage of physical memory. Paging in/out memory produces
unpredictable latency which is not acceptable in real-time systems. To prevent this happens,
POSIX real-time extension defined memory locking using mlock(), munlock(), mlockall() and
munlockall(). Upon successful return from mlock(), pages in the specified range shall be locked
and memory-resident. In munlock(), pages in the specified range shall be unlocked with respect
to the address space of the process. Using mlockall() function with MCL_CURRENT set, all
currently mapped pages of the process' address space shall be memory-resident and locked.
When munlockall() function returns, all currently mapped pages of the process' address space
shall be unlocked with respect to the process' address space.

Real-time processes usually work together, hence, they need to access each other resource. Inter-
process communication must be done in efficient manner satisfying real-time requirements.
Real-time signals can be used for this purpose. However, using this approach introduces
unnecessary overhead. For more efficient communication among real-time processes, POSIX
real-time extension defined shared memory feature which allow multiple processes access the
shared data. The shared memory can be done through mmap() which maps a regular file/shared
memory objects or typed memory objects to memory.

Clock and Timer

Time is the essence of real-time systems. Expressing absolute time in sub-millisecond precision
is an absolute minimum requirement. Many advanced techniques have been introduced to
improve hardware speed. Nowadays, processors can easily reach GHz in speed. Difference by
nanoseconds can be computed on such environment. Nanosecond precision has precedent and
allows the implementation to provide time-based services, such as timers, using whatever
precision it is capable of while the application requirements are expressed to an arbitrary level of
precision. For this purpose, POSIX defines structure timespec as follow:
 time_t tv_sec – Seconds
 long tv_nsec – Nanoseconds

Time in POSIX has nanosecond resolution, which satisfies most real-time application
requirements. POSIX real-time extension also defined a set of new functions to take the
advantage of high resolution timer. These new functions allow timer events can be created that
notify a process of timer expirations. Such these functions are timer_settime(), timer_gettime(),
timer_getoverrun(). The advantage of nanosecond resolution and the ability of creating real-time
signals for timer expiration ease the task of implementing periodic events in real-time
applications. However, it is a bit overhead the way POSIX using 64-bit long for nanoseconds. It
would be better to revise a bit by using 64-bit for milliseconds and 32-bit for nanoseconds. On
fast processors, timing difference in real-time computing is usually from milliseconds to
nanoseconds. Hence, expressing time in milliseconds and nanoseconds is more suitable than in
seconds and nanoseconds. RTSJ is currently using 64-bit milliseconds and 32-bit nanoseconds.

9
Bollella, in [7], observed that 64-bit real-time clock based in nanoseconds had insufficient range
in some situations.

POSIX 1003.13

Besides POSIX 1003.1b, POSIX real-time Application Environment Profiles (AEPs) defined in
POSIX 1003.13 is another important feature. It was introduced to compromise the heavyweight
of POSIX 1003.1 standard. Some embedded systems have very limited hardware components
and hence, it is not feasible for these systems implementing all of POSIX basic standard 1003.1.
To address this issue, AEPs define different profiles based on hardware constraints of devices.
Within a certain profile, RTOS is only required to implement a subset of POSIX 1003.1
standards to be compliant. Four real-time AEPs are being defined in POSIX 1003.13:
 Minimum System: systems with no memory management unit (MMU), no file system, no
I/O terminal. Only one process is allowed, but multi-threads can run concurrently.
 Real-time controller: it is similar to minimum system profile but adding file system and
I/O terminal. Only one process but multiple threads are allowed.
 Dedicated system: representing large embedded systems with no file system. These
systems have multiple processes and threads running concurrently.
 Multi-purpose system: it is for large real-time systems with all features supported

10
CONCLUSION
POSIX 1003.1b covered many important aspects of real-time computing. The standard was
created based on open architecture design with no explicit or implicit references to how the
standard should be implemented. Adding real-time signal features into traditional signal without
breaking the existing standard was a big achievement. It is shown that the standards defined in
POSIX have been taken carefully so that they are flexible to further required works.

POSIX standards have a large impact on industrial software standard. However, history shows
that the process of POSIX is a bit slow to keep pace with technical trends. Nowadays, it is crucial
for industrial vendors to quickly react to new innovations and launch products to the market
sooner better than later. POSIX standards provide little help in this type of business.
Nevertheless, the work in POSIX standards is a great success.

REFERNCES
[1] Phillip A. Laplante, Eileen P. Rose and Maria Gracia-Watson - An historical survey of early real-
time computing developments in the U.S. – Real-time Systems, vol.8, 199-213, 1995.

[2] IEEE Std 1003.1 – 2008, The Open Group Base Specifications, Issue 7

[3] Arnoldo Diaz, Ismael Ripoll and Alfons Crespo – On Integrating POSIX Signals into a Real-time
operating system.

[4] Kyle Renwick and Bill Renwick - How to use priority inheritance, Embedded System Design
(http://www.embedded.com/columns/technicalinsights/20600062?_requestid=846574)

[5] Jia Xu, David Lorge Parnas – Scheduling Processes with Release Times, Deadlines, Precedence,
and Exclusion Relations – IEEE Transactions on Software Engineering, vol.16, no.3, 1990

[6] Jia Xu, David Lorge Parnas – On Satisfying Timing Constraints in Hard-Real-Time Systems,
IEEE Transactions on Software Engineering, vol.19, no.1, 1993

[7] Greg Bollella – Real-time Specification for Java version 1.0, 2000

[8] Michael Gonzalez Harbour – Real-time POSIX: An Overview

11

Das könnte Ihnen auch gefallen