The IPL copies the IFS from flash into RAM. The kernel and the applications can begin
running only after this copy operation is complete. So the smaller you make the IFS, the
sooner those components can run.
-
Remove unused executables—Remove any unused executables from IFS, starting
with the larger ones. Before you cut to the bone and remove anything that could
help debug the target, you should measure your target's flash-to-RAM copy speed
(see Measuring the time to
copy from flash to RAM for more information). Remove executables from
the image only if the benefits of doing so outweigh the loss of useful tools.
Note that you don't have to manually strip executables of their debug
information; mkifs takes care of that automatically. Note
that mkefs doesn't automatically strip binaries—you
should do this in your makefile.
-
Use symbolic links—Shared libraries in POSIX systems, including the QNX
OS, typically have two representations in the filesystem: a regular filename
(with a version number) and a symbolic link (without a version number). For
instance, libc.so.2 and libc.so. The
target system should contain both representations; thus, code that requires a
specific version of the shared library can link to that version, and code that
doesn't care can link to the generic version. Under Windows, which doesn't
support true symbolic links, the QNX development installation creates duplicates
of linked files, instead of symbolic links.
If you use both versioned and
nonversioned representations of shared objects on your target, take the time
to make one a symbolic link to the other, either in the IDE or in the build
script. Otherwise, you risk ending up with two distinct copies of the
executable in the IFS. Since many shared libraries can be rather large
(libc.so, for instance, ranges from 600K to 700K),
taking this step can reduce the IFS significantly.
-
Move selected files into an external filesystem—If any file doesn't need
to start early in the boot process, move it into a flash external filesystem.
The smallest IFS consists of the kernel, libc, a UART
driver, a flash driver, and little else. After the flash driver loads, it can
automount the external filesystem partitions, and you can start running the
remainder of your drivers or applications files from there.
There is a
tradeoff here, of course. The IFS is completely loaded from flash into RAM
as one big chunk. Once loaded into the IFS, any executables that you run out
of IFS will load from RAM into RAM. For external filesystems, the files are
loaded out of flash into RAM each time they're needed. So if you need to
load an executable multiple times during bootup, it may be better to leave
it in IFS since you pay the flash-copying penalty only the first
time.
-
Use the system optimizer to remove unreferenced libraries and functions—In
many cases, you can shrink the IFS significantly by using the system optimizer
(aka dietician) in the QNX Momentics system builder. The system optimizer finds
any nonreferenced libraries and removes them completely. It can also remove
functions from shared objects if those functions aren't referenced anywhere in
the IFS. The system optimizer creates special reduced versions of the shared
objects that the IDE builds for the target. The IDE places these smaller
libraries in the Reductions subfolder of your system
builder project.
Some caveats:
- You can use this tool only from within the QNX Momentics IDE; there
is no command-line equivalent if you build your IFS outside of the
IDE.
- The reduced versions of the shared objects will contain only the
functions required to run the files within your IFS. If you
subsequently add a binary outside of the IFS, that binary will fail
to load if it relies on any of the removed functions.
- The system optimizer won't find code that uses dlsym() to
dynamically load function addresses. To work around this, you can:
a) create a stub library that references the required functions,
thereby forcing them to be included, or b) skip running the system
optimizer on a shared object if you will be dynamically loading the
object with dlopen().
- You will generate new versions of the shared objects every time you
run the system optimizer. This may require more configuration
management for your project to keep track of the extra, reduced
copies of the libraries.
- You won't be using the "QNX-blessed" versions of the libraries.
Despite these caveats, the system optimizer offers a very useful and
relatively effortless way to shrink the IFS. The savings will directly
translate into shorter boot times.