You are on page 1of 12

QNX Software Systems Ltd.

175 Terence Matthews Crescent


Ottawa, Ontario, Canada, K2M 1W8
Voice: +1 613 591-0931 1 800 676-0566
Fax: +1 613 591-3579
Email: info@qnx.com
Web: www.qnx.com

Real Time or Real Linux?


A Realistic Alternative

Paul N. Leroux
Technology Analyst
QNX Software Systems Ltd.
paull@qnx.com

Abstract
Designers of embedded systems have become increasingly interested in the Linux operating
system, largely because of its open source model. But, as it turns out, the standard Linux kernel
can’t deliver the hard realtime capabilities  such as predictable response times and microsecond
latencies — that a large number of embedded systems demand. Several products have emerged to
fill the Linux realtime gap, with mixed success. For instance, some vendors have taken a dual-
kernel approach that provides a fragile runtime environment for realtime tasks, while forcing
developers to write new drivers and system services — even when equivalent services already
exist for Linux. Meanwhile, others have proposed a “pure” Linux solution that, to be effective,
would require a rewrite of the Linux driver and virtual file system frameworks. In this paper, we
look at an alternate approach — using a POSIX-based RTOS designed specifically for embedded
systems — that not only allows Linux developers to keep their programming model, but also
maintains the key advantages of Linux’s open source model. As an added benefit, this approach
allows embedded developers to enjoy OS services unavailable with either standard Linux or
realtime Linux extensions. To illustrate the viability of this approach, the paper ends with
examples of various Linux applications already ported QNX Neutrino, the POSIX-based RTOS
from QNX Software Systems.
Real Time or Real Linux? A Realistic Alternative

Filling the Realtime Gap however, has emerged as the “standard.” In fact,
some approaches even deviate from the standard
For the embedded systems designer, Linux poses a
Linux/POSIX programming model.
dilemma. On the one hand, Linux lets the designer
leverage a large pool of developers, a rich legacy
of source code, and industry-standard POSIX APIs. Real Time Implemented
At the same time, the standard Linux kernel can’t Outside of Linux
deliver the “hard” realtime capabilities  such as
For instance, most vendors provide “realtime Linux”
guaranteed response times and microsecond
— note the quotation marks — by running Linux as
latencies — that many embedded devices require.
a task on top of a realtime kernel (see Figure 1). Any
The reasons for this are rooted in Linux’s general- tasks that require deterministic scheduling also run in
purpose architecture. Take process scheduling, for this preemptible kernel, but at a higher priority than
instance. Rather than use a preemptive priority- Linux. These tasks can thus preempt Linux whenever
based scheduler, as an RTOS would, Linux they need to execute and will yield the CPU to Linux
implements a “fairness” policy so that every process only when their work is done.
gets a reasonable opportunity to execute. As a result,
high-priority, time-critical processes can’t always
gain immediate access to the CPU. In fact, the OS Dual-Kernel Model
will sometimes interrupt a high-priority process to
give a lower-priority process a share of CPU time.
User Applications
Also, the standard Linux kernel isn’t preemptible.
IPC
A high-priority process can never preempt a kernel
call, but must instead wait for the entire call to Linux Kernel
complete — even if the call was invoked by the Realtime Tasks
lowest-priority process in the system. This makes it
Realtime Kernel
difficult, if not impossible, to create a design where
critical events are consistently handled within short Hardware
(and predictable) timeframes.
Mind you, it’s wrong to think that this scheduling Figure 1 — In the dual-kernel model, Linux runs as the
model constitutes a deficiency in Linux. The model lowest-priority task in a separate realtime kernel.

does very well, for instance, at achieving the high


overall throughput required by desktop and server In this dual-kernel model, the realtime kernel
applications. It only falls short when forced into always gets first dibs on hardware interrupts. If an
deterministic environments that it wasn’t designed interrupt is flagged for a realtime task, the kernel
for, such as network routers, factory robots, medical will schedule that task to run. Otherwise, the kernel
instruments, and continuous media applications. will pass the interrupt to Linux for processing. The
nice thing here is that all this work is invisible to
Be that as it may, several products have emerged
applications running in the Linux environment —
with the aim of filling in Linux’s realtime gap.
except, of course, for the CPU cycles lost to the
Some of these represent the work of commercial
realtime kernel and its tasks. Still, the approach has
vendors. Others are open-source research projects.
several shortcomings:
Some are a combination of both. No approach,

Page 2 Real Time or Real Linux? A Realistic Alternative


Real Time or Real Linux? A Realistic Alternative

Duplicated coding efforts leverage Linux’s widely supported APIs must


Tasks running in the realtime kernel can’t make instead choose between competing "standards."
full use of existing Linux system services — file
No determinism for existing Linux
systems, networking, and so on. In fact, if a
applications and drivers
realtime task calls out to Linux for any service,
Because Linux processes don’t run in the real-
it will be subject to the same preemption
time kernel, they don’t gain any deterministic
problems that prohibit Linux processes from
behavior. Instead, they continue to be scheduled
behaving deterministically.
according to Linux’s fairness algorithm.
As a result, new drivers and system services
must be created specifically for the realtime Limited design options
kernel — even when equivalent services already
As mentioned, the APIs supported by the
exist for Linux. Since few such drivers are
realtime kernel provide only a subset of the
available off the shelf, Linux developers must
services provided by standard POSIX and Linux
typically write them from scratch, using an
APIs. Hence, developers have fewer design
unfamiliar API.
options than they would with either Linux or a
mature RTOS.
Fragile execution environment
Tasks running in the realtime kernel don’t “Pure” Realtime Linux?
benefit from the robust MMU-protected
environment that Linux provides for regular, Given the shortcomings of the dual-kernel approach,
non-realtime processes. Instead, they run wouldn’t it be better to make Linux itself realtime?
unprotected in kernel space. Consequently, any Apparently, this can’t be too hard to do, since at
realtime task that contains a common coding least one vendor has claimed they have a pure Linux
error, such as a corrupt C pointer, can easily kernel capable of supporting applications with
cause a fatal kernel fault. That’s a problem, since “realtime requirements.” In a nutshell, they made
most systems that need real time also demand a the kernel preemptible by enabling Linux’s SMP
very high degree of reliability. locking mechanisms to work on a single processor.
This approach has merit, since it allows developers
Limited portability to use a standard Linux kernel and programming
With the dual-kernel approach, realtime tasks model. And, like other common approaches to
aren’t Linux processes at all, but threads and making Linux more deterministic, such as adding
signal handlers written to a small subset of the high-resolution timers, it helps address the low-
POSIX API or, in some cases, a non-standard latency requirements of reactive, event-driven
API. Moving existing Linux code and systems. Unfortunately, such low-latency patches
applications to the realtime environment don’t address the complexity of most realtime
becomes difficult. environments, where realtime tasks span larger time
To complicate matters, different implementa- intervals and have more dependencies on system
tions of the dual-kernel approach use different services and other processes than do tasks in a
APIs. Realtime tasks written for one vendor’s simple event-driven system.
realtime extensions may not run on another’s. For instance, in systems where realtime tasks
Embedded device manufacturers hoping to depend on services such as device drivers or file
systems, the problem of priority inversion would

Real Time or Real Linux? A Realistic Alternative Page 3


Real Time or Real Linux? A Realistic Alternative

have to be addressed within the Linux driver and Compatible to the core
virtual file system (VFS) models. This would How well does QNX Neutrino support the Linux
effectively require a rewrite of those frameworks — programming model? The answer lies, to a great
and of all device drivers and file systems employing degree, in the POSIX APIs adopted by Linux.
them. Without these modifications, realtime tasks Though rooted in Unix practice, these APIs were
could experience unpredictable delays when defined by the POSIX working groups purely in
blocked on a service. As a further problem, most terms of “interface,” not “implementation.” Simply
existing Linux drivers aren’t preemptible. Thus, to put, the APIs aren’t tied to any OS or OS architec-
ensure predictability, programmers would also have ture. As a result, an RTOS can support the same
to insert preemption points into every driver in the POSIX APIs as Linux (along with various subtleties
system — something that few Linux developers of Linux compatibility) without adopting Linux’s
have experience doing. non-deterministic kernel.
In any case, it’s unclear which realtime modifica- The QNX Neutrino RTOS supplies proof for this
tions, if any, will eventually be integrated into the implementation-independent approach: It offers
standard Linux kernel. After all, most Linux-based POSIX-compliant APIs, but implemented on a
systems rely on the kernel’s current approach, which realtime, microkernel architecture (see Figure 2).
sacrifices predictability to achieve higher overall Importantly, QNX doesn’t implement POSIX as an
throughput. A more deterministic kernel — with its add-on layer. Rather, the very core of the QNX
attendant reduction in average response times — Neutrino RTOS — the QNX microkernel — was
may simply be out of step with what most Linux designed from the beginning to support POSIX
developers want. realtime facilities, including threads. POSIX, and
hence Linux, compatibility runs deep.
The Best of Both Worlds Embedded Linux: a new definition
® ®
The QNX Neutrino represents an entirely different This issue of API compatibility is taking on surpris-
and altogether more viable approach to the problems ing importance as OEMs attempt to use Linux in
we’ve been discussing. Instead of trying to make
developers squeeze predictable response times out
of Linux, QNX Neutrino offers a proven realtime QNX Microkernel Model
operating environment that:
HA File Device
• allows Linux developers to keep their existing Manager System Driver
APIs and programming model
Message Passing
• addresses the shortcomings of realtime Linux
Microkernel
extensions through a much tougher runtime
POSIX TCP/IP Java
model, greater design options, and a unified App Manager VM
environment for realtime and non-realtime
applications
Figure 2 — In QNX Neutrino, the microkernel contains
• maintains key benefits associated with Linux’s only the most fundamental OS services. All other
open source model, such as easier trouble- services are provided through optional, memory-
shooting and OS customization — in fact, protected processes that can be stopped and started
dynamically. To achieve this modularity, QNX Neutrino
QNX Neutrino’s architecture offers distinct
uses message passing as the fundamental means of
advantages on both counts IPC for the entire system.

Page 4 Real Time or Real Linux? A Realistic Alternative


Real Time or Real Linux? A Realistic Alternative

their embedded products. Until recently Linux was, helped save the Unix world from fragmentation. In
more than anything else, a unified community of fact, the ELC specification will be based on existing
developers creating software for a relatively narrow POSIX standards, such as the POSIX 1003.1, which
range of environments  mostly web servers and the QNX Neutrino RTOS supports today. As a result,
workstations based on x86 hardware. This common the QNX Neutrino RTOS will inherently support
focus meant that Linux developers could count on a embedded Linux applications, while simultaneously
variety of benefits: binary compatibility, a consistent providing all of the benefits of a true RTOS designed
OS kernel, a pool of readily adaptable source code, from the ground up for embedded systems (more on
and so on. these benefits later).

Unfortunately, no such common focus is possible


Inherently Open
in the embedded market, for the simple reason that
embedded systems are so incredibly diverse. Most Still, Linux compatibility is a red herring if an
are purpose-specific, requiring custom applications, RTOS doesn’t also address why most developers
custom drivers, custom OS services, custom board consider Linux in the first place: the benefits of its
designs, and so on. In fact, the consequences of open source model. With open source, developers
adapting Linux to this diversity are fast becoming can analyze the architecture of the OS to better
obvious. Scores of embedded OEMs and developers integrate their own code, adapt OS components to
are now independently rolling their own Linux application-specific demands, and save considerable
kernels with the result that, instead of one Linux, time troubleshooting — not only when problems
many non-standard and incompatible versions exist. occur in their own programs, but when a problem
Fragmentation isn't a distant threat; it’s happening involves unexpected results from underlying OS
today.1 code. In short, developers gain a level of vendor
independence and self-sufficiency not possible with
There is, then, a need for a new lingua franca
the “black box” model of many commercial OSs.
among embedded Linux developers  a way to
define “embedded Linux” that accommodates the The QNX Neutrino RTOS offers these benefits
teeming diversity of the embedded market, while in two ways: 1) by using a highly extensible
providing a critical mass of portability and microkernel architecture; and 2) by providing
interoperability. That’s exactly what the Embedded customers with source code for drivers, libraries,
Linux Consortium (ELC), a vendor-neutral trade and BSPs, including well-documented driver
association dedicated to advancing Linux in development kits for a variety of standard devices.
embedded markets, is now doing with its soon-to- As a microkernel OS, QNX Neutrino is fundamen-
be-proposed ELC Platform Specification. This tally open to customization. Except for a few core
specification will define embedded Linux in a new services (e.g. scheduling, timers, interrupt handling)
way: as a set of APIs, along with a test suite to that reside in kernel space, most OS-level services —
measure conformance. drivers, file systems, protocol stacks, and so on —
Truth is, this approach isn’t really new. The POSIX exist as user-space applications outside the kernel. As
specification did much the same thing when it a result, developing custom drivers and application-
specific OS extensions doesn’t require specialized
1
kernel debuggers or kernel gurus. In fact, as user-
Fragmentation raises another issue: lower reliability. A key reason
why standard x86 Linux performs so reliably is that a large com- space programs, OS extensions become as easy to
munity of developers is continually locating and fixing problems in develop as standard applications, since they can be
the code. That benefit no longer applies when you deploy a custom
Linux kernel supported by only a few developers.

Real Time or Real Linux? A Realistic Alternative Page 5


Real Time or Real Linux? A Realistic Alternative

debugged with standard, source-level tools familiar issuing calls such as open(), read(), write(), or lseek()
to every Linux developer. on the pathname. For instance, the QNX serial-port
Better yet, QNX Neutrino allows applications to driver typically registers the pathname /dev/ser1 to
access all drivers and OS services via a single, represent the first serial port. Any application that
consistent form of IPC: synchronous message needs to access that port simply issues an open() on
passing. This approach offers several advantages. /dev/ser1.
For instance, because QNX message passing is So where does the message passing come in? Well,
synchronous, it automatically coordinates the from the application’s perspective, the open() looks
execution of communicating programs, thereby and behaves like a standard POSIX call; there’s
eliminating the need to handcode — and debug — nothing special about it. But, underneath the hood,
complex synchronization services in every process the QNX Neutrino C library converts the call into an
(see Figure 2). Moreover, message passing inherently io_open message and forwards the message to the
simplifies the task of partitioning a complex system serial driver. If the application subsequently wished to
into well-defined building blocks that can be write a character to the serial port, a similar sequence
developed, tested, and maintained individually. would occur: the client would issue a write(), the C
Troubleshooting becomes much easier as a result. library would construct an io_write message, and the
Does this mean, however, that developers must use message would be sent to the driver.
proprietary message-passing functions? Not at all. There’s an interesting and highly beneficial side-
QNX messaging is implemented so seamlessly that effect here: the exact same message can be sent
applications and OS services don’t have to invoke from any client application to any service, provided
special functions to exchange messages — the the service supports that particular function. For
messages can be sent and received transparently, instance, to write a character to a serial port or to put
using standard POSIX calls. Now, that may sound a a character into a disk file, an application would issue
bit like magic, so let’s look at how it works. the same write() function in either case; the only
In QNX Neutrino, any service-providing program difference would be where the message was sent.
(e.g. a driver) can “advertise” its services to other In other words, the application is cleanly decoupled
programs by registering a pathname in the pathname from the services it relies on. This decoupling
space. Programs can then access those services by simplifies development since all interactions between
applications and system services can be implemented
MsgReply() or SEND
using a simple, POSIX-based programming model. It
MsgError() blocked also eases migration to new designs since applications
MsgReceive()
don't have to include hardware- or protocol-specific
MsgSend() code.
MsgSend()
RECEIVE
READY Two more (short) points about QNX message
blocked
MsgReceive() passing before we move on. First, developers can
MsgReply() or
REPLY access the QNX messaging framework directly, using
MsgError() blocked
three simple calls: MsgSend(), MsgReceive(), and
This thread
Other thread MsgReply(). Second, message passing isn’t the only
form of IPC that QNX Neutrino supports. Developers
Figure 3 — QNX message passing simplifies the
can, in fact, work with several standard forms of IPC,
synchronization of processes and threads. For instance,
the act of sending a message automatically causes the including signals, POSIX message queues, shared
sending thread to be blocked and the receiving thread memory, pipes, and FIFOs.
to be scheduled for execution.

Page 6 Real Time or Real Linux? A Realistic Alternative


Real Time or Real Linux? A Realistic Alternative

Available source unprotected realtime kernels used in the dual-


kernel approach.
QNX Neutrino further simplifies troubleshooting
and OS customization by providing customers with A unified environment
full source code for libraries, drivers, and board-
In QNX, the realtime and non-realtime
support packages. Developers can also freely down-
environments are one and the same. Realtime
load device driver kits (DDKs) for a variety of device
applications can take advantage of the full
types, including networking, graphics, input, audio,
POSIX API and enjoy full access to system
and USB. Besides providing source code, the DDKs
services — GUIs, file systems, and so on.
include clear, concise documentation and a software
By the same token, existing POSIX/Linux
framework that implements all higher-level, device-
applications can immediately gain deterministic
independent code in libraries. The only code the
behavior. And since both realtime and non-
developer has to write is the hardware-specific code
realtime applications are running in the same
for the chip on their device.
message-based environment, IPC between them
While discussion of source licensing models is is greatly simplified.
beyond the scope of this article, it’s important to
note that this QNX source code isn’t provided under Less duplicated effort
the GPL that covers most Linux source. Rather, QNX As discussed, the dual-kernel approach can
Software Systems provides the source under its own force developers to write custom drivers, using
license agreement, which — unlike the GPL — gives an unfamiliar API. As in most OS environments,
developers the freedom to create derivative works developing these drivers requires kernel
without having to sacrifice any of their own intellec- debugging tools (hard to use), kernel rebuilds
tual property (IP). Put simply, QNX source is free of (time-consuming), and kernel programmers
the IP issues that prevent many embedded system (expensive).
manufacturers from using GPL-covered code. QNX Neutrino addresses this problem in several
ways. First, like any established OS with a large
Real(time) Benefits user base, QNX supports a variety of off-the-
Implementing POSIX/Linux APIs on a microkernel shelf drivers for standard hardware. And, as
architecture also addresses the drawbacks associated we’ve seen, QNX Neutrino runs all drivers in
with the realtime extensions discussed earlier: user space, so they can be developed using
standard source-level tools and techniques.
A tougher runtime model This job is made all the easier by the QNX
As a monolithic OS, Linux binds most drivers, DDKs, which provide documentation, libraries,
file systems, and protocol stacks to the OS headers, and ready-to-customize source for a
kernel. Hence a single programming error in any variety of drivers.
of these components can cause a fatal kernel
fault. In QNX Neutrino, these components can Additional Microkernel Features
all run in separate, memory-protected address
As a microkernel RTOS designed specifically for
spaces, so it’s very difficult for them to corrupt
the demands of embedded systems, QNX Neutrino
the kernel, or each other. QNX Neutrino
also offers Linux developers features unavailable
therefore provides an environment for realtime
with either standard Linux or realtime Linux
applications that is inherently more robust than
extensions. These include:
Linux — and certainly much tougher than the

Real Time or Real Linux? A Realistic Alternative Page 7


Real Time or Real Linux? A Realistic Alternative

Built-in distributed processing microGUI, also uses a microkernel architecture,


QNX Neutrino provides an OS service, the so designers can easily “unplug” GUI services
QNX micronetwork, that allows messages to that aren’t required by their memory-constrained
flow transparently across processor boundaries. devices.
Consequently, any process can, given appro- Consistent, field-tested kernel
priate permissions, access virtually any resource
Unlike the monolithic Linux kernel, which can
on any other node, as if that resource were local.
change from embedded system to embedded
For instance, if an application wishes to send an system, the QNX microkernel can be used
open message to a device driver, it doesn’t unmodified across an incredibly diverse range
matter whether the driver is local or remote: the of products. In fact, there is only one QNX
application sends the exact same open() call in microkernel binary for each family of supported
either case. If the pathname for the driver is CPUs. Developers have the assurance that they’re
local, the QNX microkernel will route the using the same microkernel lab-tested at QNX
message directly; if the driver is on a remote Software Systems and field-tested in other
node, the QNX micronetwork will transparently customer installations.
forward the message to that node.

Fault-tolerant networking A Matter of Synergy


Thanks to the network abstraction provided While QNX Neutrino offers a superior platform for
by QNX message passing, applications can running realtime applications, choosing between it
communicate transparently over redundant and Linux doesn’t have to be a mutually exclusive,
network links: if one link fails, the OS will either/or proposition. In fact, because the two OSs
automatically reroute traffic over the remaining share so much common ground, developers can
links. Network traffic can also be load-balanced readily target both OSs, using each where it fits
over all available links, resulting in higher best. Moreover, QNX supports TCP/IP, NFS, and
throughput. Again, this service is built-in; even a Linux file system, so it’s easy for a develop-
applications require no special networking code. ment shop that uses a mix of Linux and QNX
workstations to share resources across the two
Smaller memory footprint environments.
Because of the fine-grained scalability of
In short, Linux and QNX Neutrino do more than
microkernel architecture, the QNX RTOS can
simply coexist. Rather, they give developers the
provide a runtime environment considerably
opportunity to leverage many of the same APIs,
smaller than Linux — a critical advantage in
source code, and skill sets across a much wider
high-volume devices such as information
spectrum of applications than any operating system
appliances and in-car telematics systems, where
— whether realtime or general-purpose — could do
even a $2 reduction in memory costs per unit
on its own.
can return millions of dollars in profits. In fact,
QNX’s native windowing system, the Photon®

Page 8 Real Time or Real Linux? A Realistic Alternative


Porting Open Source Programs to QNX Neutrino

Supplement: Porting Open Source Applications to QNX Neutrino

Since QNX Neutrino is a POSIX operating system, it’s generally a simple exercise to port any open source
program — including any Linux program — that has been written to the POSIX API.

The following table lists a sample of the open-source applications that have already been ported to QNX
Neutrino. For a comprehensive listing, visit http://www.qnx.com/developer/download.

GCC* Perl Samba


GNU C/C++ compiler Scripting language Provides seamless access to files,
printers, and other shared
CVS* Python resources on Windows networks
Source code versioning control Scripting language
system Open SSH/SSL
Ruby Secure sockets and shells
Vim Scripting language
Open LDAP
Vi IMproved, a programmers’
Apache Light weight Directory Access
editor; the GUI version (gvim)
Web server Protocol
has been ported to QNX Photon
microGUI PVM
Mozilla*
Distributed processing system
GNU EMACS Web browser based on the
Programmers’ editor Netscape source code Zebra router
Software for managing TCP/IP-
GDB* Pine based routing protocols
Email client
GNU debugger
The GIMP
Mutt GNU Image Manipulation
DDD
Email client Program; similar to Photoshop,
Graphical debugger that uses uses X as its GUI
GDB as its back end for Sendmail
debugging (the GUI is X) Email server Abiword
Word processor
Doxygen Tin
Source code documentation tool Quake III
Newsgroup reader
Multimedia game

* Only available as part of the free QNX Momentics NC edition, which can be downloaded from http://www.qnx.com/nc.

Porting guidelines for QNX Neutrino


For most Linux or open-source applications, porting is as simple as recompiling the source and relinking
with QNX Neutrino libraries. System administration, computational, database, and networking
applications are all examples of applications that can be ported this way.

Porting Open Source Programs to QNX Neutrino Page 9


Porting Open Source Programs to QNX Neutrino

Porting: Easy as 1-2-3


If you’re porting an open source program that uses the GNU build system (i.e. it has a “configure”
script), make sure you have the GNU autoconf, GNU automake, GNU libtool, and GNU m4 packages
installed. (These are available as a free download from http://www.qnx.com/developer/download or on
the QNX third-party CD). If the program also uses the X GUI system, then you should also have the
XFree86 with XPhoton package installed as well (also available on the QNX website or QNX third-party
CD).

Once those packages are installed, run the configure script. Once that’s done, run make. Assuming
there were no errors in the build, type make install. Your Linux port is now complete.

When problems do arise, they tend to fall into the following categories:

• The configure script failed because it couldn’t guess what OS you were using — If this
happens, it means that the program hasn’t updated its configure scripts since QNX Neutrino v6
was added to the GNU build system. Copying config.sub and config.guess from
/usr/share/automake-1.6/ over the same files in the program’s source tree should solve
the problem.

• The required libraries aren’t available — Many common libraries have already been ported to
QNX Neutrino, and can be downloaded from the QNX website or from a community package
repository. If you still can’t find the library you need, you’ll need to download its source code
and port it yourself. Generally, porting libraries is as easy as porting POSIX applications. (And
once you’re done, you might want to submit the port to the QNX website or a community
repository so that others can use it!)

• When porting a library, the configure script doesn’t think it can create shared libraries —
Again, this is caused by out-of-date configure scripts. If you’re happy with static libraries you
can ignore this problem, but if you really want shared libraries, you can edit the configure script.
There is usually a case $host_os in block that sets up various parameters for building
shared libraries in the configure script. (Tip: Search for “soname_spec” to find the block.)
Once you’ve found it, you can add the following to the block:

# QNX ELF
*qnx* | *nto*)
version_type=qnx
need_lib_prefix=no
need_version=no
library_names_spec='${libname}${release}.so$versuffix
${libname}${release}.so$major $libname.so'
soname_spec='${libname}${release}.so$major'
shlibpath_var=LD_LIBRARY_PATH
shlibpath_overrides_runpath=no
dynamic_linker='QNX ldqnx.so'
;;

Page 10 Porting Open Source Programs to QNX Neutrino


Porting Open Source Programs to QNX Neutrino

You’ll also want to copy the ltmain.sh from /usr/share/libtool over the ltmain.sh in
the library source code. This should update the configure script for building shared libraries under
QNX Neutrino v6.

• When linking the program, socket-related symbols were missing — This happens when the
configure script incorrectly assumes that socket-based symbols are in the C library. You could edit
the configure script to fix it, but usually it’s just easier to add -lsocket to the LIBS= lines in
the makefiles.

If an open source program doesn’t use the GNU build system, it can still be pretty easy to port, once you
tweak the makefiles and remove or add a header file or two from the source files.

Quake III provides a good example of how easy it is to port Linux source to QNX Neutrino. The entire
port was completed in a few days, with most of the time spent tweaking the makefiles, changing the sound
code to work with the QNX implementation of ALSA, and converting the X code over to the Photon
microGUI (the native QNX windowing system). Ninety-five per cent of the Quake code just worked.

Case Study: Zebra Router


Now, let’s look at a detailed porting example created by QNX application engineers to demonstrate the
benefits of “drop-in” symmetric multiprocessing (SMP) for a load-stressed QNX Neutrino-based OSPF
network router.

We began with a QNX Neutrino host for our development platform and with a QNX Neutrino board
support package for our multi-processor PowerPC target. To obtain an OSPF router daemon, we elected
to port the Linux-based Zebra router protocol suite.

We downloaded zebra-0.92a.tar.gz from the Zebra website, http://www.zebra.org/, to our QNX


Neutrino host.

We used the following command to generate the QNX-specific, PowerPC-targeted header and makefiles
for Zebra:

./configure –enable-tcp-zebra –host=x86-pc-nto-qnx


–target=ppcbe-nto-qnx –prefix=/opt/zebra/zebra-0.92a/ppcbe/usr/local

The –host parameter is, in fact, unnecessary because the included config.guess script properly
determines that QNX Neutrino is running self-hosted on an Intel architecture PC.

The –target parameter instructs the configure script to generate QNX-target, big-endian, PowerPC
makefiles.

The –prefix parameter instructs the configure script to generate makefiles that will use /opt/zebra
as the installation directory for the installable products. QNX Neutrino’s default installation location for

Porting Open Source Programs to QNX Neutrino Page 11


Porting Open Source Programs to QNX Neutrino

third-party software is rooted at /opt. Use discretion and consider QNX Neutrino’s package installer if
you want to install into alternate locations.

Results
With the Zebra configuration and build, we encountered two configuration issues immediately:

• The configure operation failed to locate socket APIs and set the communication method between
the route daemons and QNX Neutrino to be ioctl-based.

• Sources including zebra.h failed to compile due to a missing fcntl.h header file.

The first issue arose because Linux incorporates the Berkeley Socket Library into the GNU C library,
glibc, whereas QNX Neutrino implements it within libsocket.a. Correcting this was easy: we simply
added a test for a QNX Neutrino host to the configure file and added –lsocket to the linker options
with the line LIBS=-lsocket $LIBS. Once we reconfigured and recompiled the code, the problem
was solved.

We encountered the second issue because Linux places the file control header into /usr/include/sys
whereas QNX Neutrino places it into /usr/include. To correct this, we added an OS-specific QNX
define to config.h.in (the template for config.h) and added a conditional compilation flag to
zebra.h to include <fcntl.h> rather than <sys/fcntl.h> when the host OS is QNX Neutrino.
Reconfiguring and compiling demonstrated that this solved the header file issue. Here’s the code snippet:

#ifdef __QNXNTO__
#include <fcntl.h>
#else
#include <sys/fcntl.h>
#endif

With these minor issues resolved, we compiled and installed the Zebra suite without errors. To run the
OSPF software router, we added appropriate TCP/IP service entries to /etc/services for the
networking daemons and configured QNX Neutrino’s telnetd. We then had our OSPF router running
on SMP PowerPC hardware.

Conclusion
Members of the QNX user community have been able to easily port many open-source applications
to the QNX Neutrino RTOS, including Samba (CIFS) servers, NTP time servers, CORBA managers,
SNMP managers, packet filters, commercial protocol suites, X applications, distributed processing
systems such as PVM, shells such as csh/tcsh, scripting languages such as Perl, Python, and TCL,
Quake, and so on.

Packaged versions of those applications are available from the QNX user community. For instance, the
http://www.qnxzone.com site provides references to many ported applications.

© 2002, QNX Software Systems Ltd. All rights reserved.


QNX, Momentics, Neutrino, Photon microGUI, and ‘Build a more reliable world’ are registered trademarks in certain jurisdictions, and PhAB, Phindows, and Qnet are trademarks,
of QNX Software Systems Ltd. All other trademarks and trade names belong to their respective owners.
Page 12 Porting Open Source Programs to QNX Neutrino

You might also like