mirror of
https://github.com/apache/nuttx.git
synced 2026-08-02 20:59:02 +00:00
Fix repeated and misspelled words in the kernel modules versus shared libraries implementation notes so the text reads correctly. Signed-off-by: Old-Ding <35417409+Old-Ding@users.noreply.github.com>
176 lines
7.5 KiB
ReStructuredText
176 lines
7.5 KiB
ReStructuredText
.. _kernel-modules:
|
|
|
|
==================================
|
|
Kernel Modules vs Shared Libraries
|
|
==================================
|
|
|
|
Kernel Modules
|
|
==============
|
|
|
|
NuttX has had support for Kernel Modules for some time.
|
|
A kernel module allows you to extend the functionality of the OS
|
|
at runtime by installing ELF modules into the kernel.
|
|
A kernel module might be used, to example, to load device drivers
|
|
into RAM at runtime.
|
|
|
|
Here are some general properties of kernel modules:
|
|
|
|
* The first kernel module is loaded into the kernel address space
|
|
by ``insmod()`` using only a symbol table exported by the OS.
|
|
* Kernel modules can also (optionally) export a symbol table.
|
|
Such symbol tables are remembered and will be used by ``insmod()``
|
|
to resolved undefined symbols in subsequently loaded modules.
|
|
* This requires dependency checking logic: A module that imports symbols
|
|
from another module must be added after the modules that it depends upon.
|
|
And a module exports a symbol may not be removed while there are such
|
|
inter-module dependencies in place.
|
|
A module that imports symbols from another module must be removed before
|
|
the module that exports the symbol can be removed.
|
|
* There is a (non-standard) OS interface ``modsym()`` that will allow kernel
|
|
logic to look up symbols within a kernel module.
|
|
* Handles are used at the kernel module interfaces: ``insmod()`` returns
|
|
a handle to the module data structure. That handle can subsequently be used
|
|
to retrieve symbols with ``modsym()``.
|
|
* ``rmmod()`` uses the handle to remove the module.
|
|
* ``modhandle()`` is also available for backward compatibility:
|
|
Given the assigned module name, you can use this to retrieve
|
|
the module handle at any time.
|
|
* There is a test case at ``nuttx-apps/examples/module``.
|
|
|
|
In the FLAT build, ELF kernel modules are simply loaded into RAM and linked
|
|
with the base firmware. But things get a little more complex with PROTECTED
|
|
and KERNEL builds.
|
|
|
|
In those case, there are separate address spaces for the kernel
|
|
and for applications.
|
|
Kernel modules are only loaded in the kernel address space and, hence,
|
|
are not available to applications.
|
|
|
|
|
|
Shared Libraries
|
|
================
|
|
|
|
A shared library is another software module with these properties:
|
|
The ``.text`` address space is accessible to all applications.
|
|
The ``.data`` and ``.bss`` address space is in the same address space
|
|
as the application that uses the shared library.
|
|
So, they are shared in the sense that the ``.text`` is shared.
|
|
|
|
|
|
FLAT Build
|
|
==========
|
|
|
|
In the FLAT build environment, there is only one address space.
|
|
So what is the difference between a kernel module and a shared library
|
|
in this case? Certainly a kernel module meets all of the requirements
|
|
of a shared library in that environment.
|
|
In this case kernel modules really only differ from shared
|
|
libraries in their usage semantics:
|
|
|
|
For the FLAT build, I have added the standard ``include/dllfcn.h``
|
|
and have implemented the FLAT shared library support as a thin wrapper
|
|
around the kernel module support:
|
|
|
|
* ``dlopen()`` maps to ``insmod()``.
|
|
* ``dlclose()`` maps to ``rmmod()``.
|
|
* ``dlsym()`` maps to ``modsym()``.
|
|
* ``dlerror()`` is only a stub at the present time.
|
|
|
|
There is a shared library test case at ``nuttx-apps/examples/sotest``.
|
|
|
|
|
|
PROTECTED Build
|
|
===============
|
|
|
|
The PROTECTED build is equivalent to the FLAT build except that there are
|
|
two address spaces: The kernel address space and the user address space.
|
|
But all applications still share the same user address spaces.
|
|
|
|
As a result ``.text`` along with ``.data`` and ``.bss`` are naturally shared.
|
|
This requires using two copies of the module logic: One residing in kernel
|
|
address space and using the kernel symbol table and one residing in user space
|
|
using the user space symbol table.
|
|
The first provides only kernel module support; the second only PROTECTED mode
|
|
shared library support.
|
|
|
|
This is accomplished by breaking the kernel module logic in two components
|
|
with OS kernel module interfaces in sched/module but with a sharable module
|
|
library at libc/modlib.
|
|
|
|
The shared library functions no longer call the kernel module logic but rather
|
|
implement their one top-level management logic using the lower-level routines
|
|
in the module library.
|
|
|
|
|
|
Better FLAT and PROTECTED Mode Shared Libraries
|
|
===============================================
|
|
|
|
A better implementation of shared libraries in the FLAT and PROTECTED builds
|
|
would, however, have a separate copy of the ``.bss`` and ``.data`` region
|
|
for each NuttX task group.
|
|
|
|
A task group is the moral equivalent of a Unix process.
|
|
That is how a shared library would have to work in uClinux, for example.
|
|
But that would be a substantial effort! For example, since each
|
|
``.bss``/``.data`` would lie at a different physical addres,
|
|
the ``.text`` section logic would need support
|
|
Position-Independent-Data (PID).
|
|
Embedded PID support, however, is pretty much broken on all current GCC
|
|
implementations. See NxFlat Compatibility Problem.
|
|
|
|
Perhaps the xFLAT work that I did for uClinux shared libraries could be
|
|
ported to Nuttx: `xFLAT Web Page <https://sourceforge.net/projects/xflat/>`_.
|
|
|
|
For more information about task groups see :ref:`nuttx-tasking`
|
|
or :ref:`tasks-vs-threads`.
|
|
|
|
The current implementation also assumes that all firmware resides in base
|
|
FLASH and hence is fully linked prior to loading any modules or shared
|
|
libraries. There is no support for loading programs into RAM and binding
|
|
them to symbols exported by modules or shared libraries.
|
|
|
|
This extension would, however, not be so difficult for the FLAT build;
|
|
it would be a simple matter of integrating the exported module symbol
|
|
tables into the symbol lookup.
|
|
That is already done in ``sched/module`` files, but not yet in the
|
|
very similar ``binfmt/libelf`` files.
|
|
|
|
In the PROTECTED build, this would require some special start-up logic
|
|
in the user address space as the initial steps of the newly started task.
|
|
Some kind of dynamic loader, such as ``ld.so``, would have to integrate
|
|
with ``crt0`` logic to automatically bind user space tasks to shared libraries
|
|
as they are loaded into memory before the programs ``main()`` function
|
|
is called.
|
|
|
|
|
|
KERNEL Build
|
|
============
|
|
|
|
The KERNEL build, however, is a completely different creature.
|
|
In that build, the kernel and each process has its own address space.
|
|
|
|
This means that a shared library in the kernel build has to be considerably
|
|
more complex: In order to be shared, the ``.text`` portion of the module
|
|
(1) must lie in a single shared memory region accessible from all processes
|
|
and (2) built for Position-Independent-Code (PIC) operation since
|
|
it must execute from an arbitrarily different virtual address in each process
|
|
address space.
|
|
|
|
The ``.data``/``.bss`` portion of the module must be allocated
|
|
in the user address space of each process, but either:
|
|
|
|
1. ``.data``/``.bss`` section must lie at a consistent virtual address
|
|
so that it can be referenced from the one copy of the ``.text`` in
|
|
the shared memory region, OR
|
|
2. The ``.text`` section logic must support Position-Independent-Data (PID).
|
|
The latter approach provides for a simpler build, but embedded PID support
|
|
is pretty much broken on all current GCC implementations.
|
|
See :ref:`nxflat` Compatibility Problem.
|
|
|
|
Some kind of dynamic loader, such as ``ld.so``, would have to integrate with
|
|
``crt0`` logic to automatically bind processes to shared libraries as they
|
|
are loaded into memory before the programs ``main()`` logic is called.
|
|
|
|
.. note:: There is not yet any shared library support in the KERNEL build mode.
|
|
This would be quite a large effort and not on the plan of record
|
|
at the present time.
|