Template Information

Trang

Generic Architecture of an Embedded Linux System

Thứ Bảy, 11 tháng 6, 2011 / 07:43

Since Linux systems are made up of many components, let us take a look at the overall
architecture of a generic Linux system. This will enable us to set each component in context
and will help you understand the interaction between them and how to best take advantage of
their assembly. Figure 2-4 presents the architecture of a generic Linux system with all the
components involved. Although the figure abstracts to a high degree the content of the kernel
and the other components, the abstractions presented are sufficient for the discussion. Notice
that there is little difference in the following description between an embedded system and a
workstation or server system, since Linux systems are all structured the same at this level of
abstraction. In the rest of the book, however, emphasis will be on the details of the application
of this architecture in embedded systems.
Figure 2-4. Architecture of a generic Linux system
There are some broad characteristics expected from the hardware to run a Linux system. First,
Linux requires at least a 32-bit CPU containing a memory management unit (MMU).[2] Second,
a sufficient amount of RAM must be available to accommodate the system. Third, minimal I/O
capabilities are required if any development is to be carried out on the target with reasonable
debugging facilities. This is also very important for any later troubleshooting in the field. Finally,
the kernel must be able to load and/or access a root filesystem through some form of
permanent or networked storage. See Section 1.2.1 for a discussion of typical system
configurations.
[2] As we'll see below, a specially modified version of Linux called uClinux does run on some CPUs that aren't
equipped with MMUs. The development of applications for Linux on such processors differs, however, sufficiently
from standard Linux application development to require a separate discussion. I will therefore not cover the use of
Linux on MMU-less architectures.
Immediately above the hardware sits the kernel. The kernel is the core component of the
operating system. Its purpose is to manage the hardware in a coherent manner while providing
familiar high-level abstractions to user-level software. As with other Unix-like kernels, Linux
drives devices, manages I/O accesses, controls process scheduling, enforces memory
sharing, handles the distribution of signals, and tends to other administrative tasks. It is
expected that applications using the APIs provided by a kernel will be portable among the
various architectures supported by this kernel with little or no changes. This is usually the case
with Linux, as can be seen by the body of applications uniformly available on all architectures
supported by Linux.
Within the kernel, two broad categories of layered services provide the functionality required by
applications. The low-level interfaces are specific to the hardware configuration on which the
kernel runs and provide for the direct control of hardware resources using a hardwareindependent
API. That is, handling registers or memory pages will be done differently on a
PowerPC system and on an ARM system, but will be accessible using a common API to
higher-level components of the kernel, albeit with some rare exceptions. Typically, low-level
services will handle CPU-specific operations, architecture-specific memory operations, and
basic interfaces to devices.
Above the low-level services provided by the kernel, higher-level components provide the
abstractions common to all Unix systems, including processes, files, sockets, and signals.
Since the low-level APIs provided by the kernel are common among different architectures, the
code implementing the higher-level abstractions is almost constant regardless of the
underlying architecture. There are some rare exceptions, as stated above, where the higherlevel
kernel code will include special cases or different functions for certain architectures.
Between these two levels of abstraction, the kernel sometimes needs what could be called
interpretation components to understand and interact with structured data coming from or
going to certain devices. Filesystem types and networking protocols are prime examples of
sources of structured data the kernel needs to understand and interact with to provide access
to data going to and coming from these sources.
Disk devices have been and still are the main storage media for computerized data. Yet disk
devices, and all other storage devices for that matter, themselves contain little structure. Their
content may be addressable by referencing the appropriate sector of a cylinder on a certain
disk, but this level of organization is quite insufficient to accommodate the ever changing
content of files and directories. File-level access is achieved using a special organization of the
data on the disk where file and directory information is stored in a particular fashion so that it
can be recognized when it is read again. This is what filesystems are all about. Through the
evolution of OSes in time, however, many different incompatible filesystems have seen the
light of day. To accommodate these existing filesystems and the new ones being developed,
the kernel has a number of filesystem engines that can recognize a particular disk structure
and retrieve or add files and directories from this structure. The engines all provide the same
API to the upper layers of the kernel so that accesses to the various filesystems are identical
even though accesses to the lower-layer services vary according to the structure of the
filesystem. The API provided to the virtual filesystem layer of the kernel by, for instance, the
FAT filesystem and the ext2 filesystem is identical, but the operations both will conduct on the
block device driver will differ according to the respective structures used by FAT and ext2 to
store data on disk.
During its normal operation, the kernel requires at least one properly structured filesystem, the
root filesystem. It is from this filesystem that the kernel loads the first application to run on the
system. It also relies on this filesystem for future operations such as module loading and
providing each process with a working directory. The root filesystem may either be stored and
operated on from a real hardware storage device or loaded into RAM during system startup
and operated on from there. As we'll see later, the former is becoming much more popular than
the latter with the advent of facilities such as the JFFS2 filesystem.
You'd expect that right above the kernel we would find the applications and utilities making up
and running on the OS. Yet the services exported by the kernel are often unfit to be used
directly by applications. Instead, applications rely on libraries to provide familiar APIs and
abstract services that interact with the kernel on the application's behalf to obtain the desired
functionality. The main library used by most Linux applications is the GNU C library. For
embedded Linux systems, substitutes to this library can be used, as we'll see later, to
compensate for the GNU C library's main deficiency, its size. Other than the C library, libraries
such as Qt, XML, or MD5 provide various utility and functionality APIs serving all sorts of
purposes.
Libraries are typically linked dynamically with applications. That is, they are not part of the
application's binary, but are rather loaded into the application's memory space during
application startup. This allows many applications to use the same instance of a library instead
of each having its own copy. The C library found on a the system's filesystem, for instance, is
loaded only once in the system RAM, and this same copy is shared among all applications
using this library. But note that in some situations in embedded systems, static linking,
whereby libraries are part of the application's binary, is preferred to dynamic linking. When only
part of a library is used by one or two applications, for example, static linking will help avoid
having to store the entire library on the embedded system's storage device.

0 nhận xét:

Đăng nhận xét