• No results found

About Static Libraries, Shared Libraries, and Plug-ins

Static Libraries, Shared Libraries, and Plug-Ins

4.2 About Static Libraries, Shared Libraries, and Plug-ins

Static Libraries, Shared Libraries, and Plug-Ins

4.1 Introduction 63

4.2 About Static Libraries, Shared Libraries, and Plug-ins 63 4.3 Additional Documentation 66

4.4 Configuring VxWorks for Shared Libraries and Plug-ins 66 4.5 Common Development Issues: Initialization and Termination 67 4.6 Common Development Facilities 69

4.7 Developing Static Libraries 70 4.8 Developing Shared Libraries 70

4.9 Developing RTP Applications That Use Shared Libraries 82 4.10 Developing Plug-Ins 83

4.11 Developing RTP Applications That Use Plug-Ins 84 4.12 Using the VxWorks Run-time C Shared Library libc.so 88

4.1 Introduction

Custom static libraries, shared libraries, and plug-ins can be created for use with RTP applications. This chapter describes their features, comparative advantages and uses, development procedures, and debugging methods. It also describes the C run-time shared library provided with the VxWorks distribution, which can be used with applications as an alternative to statically linking them to C libraries.

4.2 About Static Libraries, Shared Libraries, and Plug-ins

Static libraries are linked to an application at compile time. They are also referred to as archives. Shared libraries are dynamically linked to an application when the

application is loaded. They are also referred to as dynamically-linked libraries, or DLLs. Plug-ins are similar in most ways to shared libraries, except that they are loaded on demand (programmatically) by the application instead of automatically.

Both shared libraries and plug-ins are referred to generically as dynamic shared objects.

Static libraries and shared libraries perform essentially the same function. The key differences in their utility are as follows:

Only the elements of a static library that are required by an application (that is, specific .o object files within the archive) are linked with the application.

The entire library does not necessarily become part of the system. If multiple applications (n number) in a system use the same library elements, however, those elements are duplicated (n times) in the system—in both the storage media and system memory.

The dynamic linker loads the entire shared library when any part of it is required by an application. (As with a .o object file, a shared library .so file is an indivisible unit.) If multiple applications in a system need the shared library, however, they share a single copy. The library code is not duplicated in the system.

Advantages and Disadvantages of Shared Libraries and Plug-Ins

Both dynamic shared objects—Shared libraries and plug-ins—can provide advantages of footprint reduction, flexibility, and efficiency, as follows (shared library is used to refer to both here, except where plug-in is used specifically):

The storage requirements of a system can be reduced because the applications that rely on a shared library are smaller than if they were each linked with a static library. Only one set of the required library routines is needed, and they are provided by the run-time library file itself. The extent to which shared libraries make efficient use of mass storage and memory depends primarily on how many applications are using how much of a shared library, and if the applications are running at the same time.

Plug-ins provide flexibility in allowing for dynamic configuration of applications—they are loaded only when needed by an application (programmatically on demand).

Shared libraries are efficient because their code requires fewer relocations than standard code when loaded into RAM. Moreover, lazy binding (also known as lazy relocation or deferred binding) allows for linking only those functions that are required.

! CAUTION: Applications that make use of shared libraries or plug-ins must be built as dynamic executables to include a dynamic linker in their image. The dynamic linker carries out the binding of the dynamic shared object and application at run time. For more information in this regard, see 4.9 Developing RTP Applications That Use Shared Libraries, p.82 and 4.11 Developing RTP Applications That Use Plug-Ins, p.84.

NOTE: Shared libraries and plug-ins are not supported for the Coldfire architecture.

4 Static Libraries, Shared Libraries, and Plug-Ins 4.2 About Static Libraries, Shared Libraries, and Plug-ins

At the same time, shared libraries use position-independent code (PIC), which is slightly larger than standard code, and PIC accesses to data are usually somewhat slower than non-PIC accesses because of the extra indirection through the global offset table (GOT). This has more impact on some architectures than on others.

Usually the difference is on the order of a fraction of a percent, but if a

time-sensitive code path in a shared library contains many references to global functions, global data or constant data, there may be a measurable performance penalty.

If lazy binding is used with shared libraries, it introduces non-deterministic behavior. (For information about lazy binding, see 4.8.8 Using Lazy Binding With Shared Libraries, p.77 and Using Lazy Binding With Plug-ins, p.85.)

The startup cost of shared libraries makes up the largest efficiency cost (as is the case with UNIX). It is also greater because of more complex memory setup and more I/O (file accesses) than for static executables.

In summary, shared libraries are most useful when the following are true:

Many programs require a few libraries.

Many programs that use libraries run at the same time.

Libraries are discrete functional units with little unused code.

Library code represents a substantial amount of total code.

Conversely, it is not advisable to use shared libraries when only one application runs at a time, or when applications make use of only a small portion of the routines provided by the library.

Additional Considerations

There are a number of other considerations that may affect whether to use shared libraries (or plug-ins):

Assembly code that refers to global functions or data must be converted by hand into PIC in order to port it to a shared library.

The relocation process only affects the data section of a shared library.

Read-only data identified with the const C keyword are therefore gathered with the data section and not with the text section to allow a relocation per executable. This means that read-only data used in shared libraries are not protected against erroneous write operations at run-time.

Code that has not been compiled as PIC will not work in a shared library. Code that has been compiled as PIC does not work in an executable program, even if the executable program is dynamic. This is because function prologues in code compiled as PIC are edited by the dynamic linker in shared objects.

All constructors in a shared library are executed together, hence a constructor with high priority in one shared library may be executed after a constructor with low priority in another shared library loaded later than the first one. All shared library constructors are executed at the priority level of the dynamic linker’s constructor from the point of view of the executable program.

Dynamic shared objects are not cached (they do not linger) if no currently executing program is using them. There is, therefore, extra processor overhead if a shared library is loaded and unloaded frequently.

There is a limit on the number of concurrent shared libraries, which is 1024.

This limit is imposed by the fact that the GOT table has a fixed size, so that indexing can be used to look up GOTs (which makes it fast).