📄 migrating to linux kernel 2_6 -- part 5 migrating apps to the 2_6 kernel and nptl.htm
字号:
one process creating another is fundamental. The most
obvious example is a shell such as the Bash shell, the
standard Linux command interpreter. The shell executes
applications in response to user commands, and can
either start commands and wait for them to finish or
execute them as separate, concurrent processes (commonly
referred to as "running in the background").<BR><BR>One
process typically creates another through a set of
<B>fork()</B> and <B>exec()</B> function calls. The
initial process calls the <B>fork()</B> function,
creating a clone of itself (known as a child process)
that inherits the entire execution environment of the
process that created it. <B>The fork()</B> call returns
the child's process identifier (PID) in the parent
process, and a PID of 0 in the child process. The child
process then uses the <B>exec()</B> call to execute some
other command, which totally replaces its existing
execution context with that of the exec()'d command. At
the same time, the parent process typically either exits
immediately or waits until the child process returns its
status. A simple example of this is the following:<CODE><PRE>int pid;<BR>if (pid=fork()) {<BR> /* parent code */<BR> exit(1);<BR>} else {<BR> /* child code */<BR> execl( "command", "arg1", "arg2", ...);<BR> printf("Should never get here...\n");<BR> exit (-1);<BR>}</PRE></CODE>This
model for process creation is simple and easy to use,
but requires substantial system overhead. Child
processes inherit a separate copy of the complete state
of their parent, including its address space, global
variables, open file descriptors, and so on. This
consumes a fair amount of system resources, makes it
relatively complex for child processes to share
resources or communicate with each other, and is
extremely resource-intensive for use at the operating
system level.<BR><BR>Threads are similar to processes,
but with some notable exceptions that make them far more
suitable for use in complex, modern systems. Threads are
essentially sub-processes that share the majority of the
resources of their parent process, and thus require a
lesser amount of system resources. A traditional way of
thinking about threads is by referring to them as
lightweight processes. All of the threads created by a
process share the same address space, global variables,
open file descriptors, pending alarms, signals and
signal handlers, and system accounting information. Each
thread maintains its own program counter, registers,
stack, and state information. <BR><BR>A key
differentiator between different thread implementations
is the interaction between kernel threads, user-space
processes, and user-space threads. This will be
discussed in more detail later in this white
paper.<BR><BR><B>Linux Threading Models</B><BR><BR>The
standard Linux threading library in all stable versions
of Linux prior to 2.6 is known as LinuxThreads. This
library has been supported for use with the GNU C
library, glibc, since glibc 2.0, and is largely
POSIX-compliant. <BR><BR>NOTE: The primary libraries
produced when compiling the LinuxThreads and Native
POSIX Thread Library source code are libpthread.so and
libpthread.a (for POSIX thread library). For this
reasons, the terms LinuxThreads and pthreads have
historically been used interchangeably, which confusing
in light of the adoption of the NPTL. This whitepaper
uses the term LinuxThreads and NPTL to clearly
differentiate between the two threading libraries and
their capabilities. The actual library names were
preserved to minimize changes to existing Makefiles and
linking commands.<BR><BR>LinuxThreads has a variety of
performance, scalability, and usability limitations. It
uses a compile-time setting for the number of threads
that a single process can create, and uses a per-process
manager thread to create and coordinate between all
threads owned by each process. This significantly
increases the overhead of creating and destroying
threads. Signal handling is done on a per-process,
rather than a per-thread, basis, though each thread has
a separate process ID. Issues such as these, in
combination with design issues such as an asymmetric
relationship between kernel and user-space threads, and
the lack of per-thread synchronization primitives for
inter-thread communication and resource sharing, places
some fundamental limitations on the number of threads
that can simultaneously be created and do meaningful
work in a LinuxThreads implementation.<BR><BR>The next
threading model introduced for Linux was IBM's Next
Generation POSIX Threads (NGPT) project. This was an
external threading library that worked in conjunction
with the LinuxThreads package, but provided additional
POSIX compliance and better performance than the
standard LinuxThreads package. This threading package is
still available for use with 2.4 and earlier Linux
kernels, but is no longer actively being worked on due
to the new threading model introduced with the 2.5 and
kernel series and made publicly available in the 2.6
kernel tree. <BR><BR>The Native POSIX Threading Library
replaces LinuxThreads and NGPT in the 2.5 and later
kernels. NPTL brings high-performance threading support
to Linux, and provides the foundation required by
multi-threaded enterprise applications such as database
systems, high-capacity and high-load web and mail
servers, and so on. NPTL was developed as part of the
2.5 kernel development process and was integrated with
Linux run-time elements such as glibc at that time. NPTL
is the strategic direction for Linux threading in the
future.<BR><BR>Some Linux vendors, such as later
versions of Red Hat Linux, have backported NPTL to
earlier kernels and have even made the threading
environment for specific processes selectable through an
environment variable (<CODE>LD_ASSUME_KERNEL</CODE>). On
systems that support this feature, the variable is set
via a command such as the following:<CODE><PRE># export LD_ASSUME_KERNEL=2.4.1</PRE></CODE>This is
a clever way to enable some existing applications that
rely on LinuxThreads to continue to work in an NPTL
environment, but is a short-term solution. To make the
most of the design and performance benefits provided by
NPTL, you should update the code for any existing
applications that use threading.<BR><BR>The next
sections discuss the implications of the changes between
the LinuxThreads and NPTL threading implementations as
far as your applications are concerned. The first
section discusses development changes related to the
updated toolchains used with the 2.6 kernel highlights.
A subsequent section highlights aspects of your
applications that you must change due to differences
between the LinuxThreads and NPTL implementations, in
order to make the most of the increased power and
performance of NPTL.<BR><BR><B>Recompiling Applications
for 2.6 and NPTL</B><BR><BR>Though many applications
will migrate from Linux 2.4 to 2.6 without
recompilation, the addition of Native POSIX Thread
Library technology will require minor modifications in
most threaded applications. A subsequent section of this
whitepaper, "Updating Applications for NPTL", discusses
the primary situations where recompilation may be
required.<BR><BR>Those applications that do require
recompilation may be affected by the updated compilers
included with distributions such as TimeSys Linux that
are based around a 2.6-based kernel. TimeSys ships its
2.6 Reference Distributions with version 3.3.2 of the C
and C++ compilers from the GNU Compiler Collection
(GCC), and uses an updated version of the binutils
package that makes up the remainder of a standard Linux
toolchain (providing the assembler, linker, library
archiver, and so).<BR><BR>Simply using a 2.6 based
kernel does not mean that you are automatically using
the NPTL. To determine the threading library that a
system uses, you can execute the getconf command (part
of the glibc package), to examine the
GNU_LIBPTHREAD_VERSION environment variable, as in the
following command example:<CODE><PRE># getconf GNU_LIBPTHREAD_VERSION<BR>linuxthreads-0.10</PRE><CODE>If
your system uses the NPTL, the command would return the
value of NPTL that your system was using, as in the
following example:<PRE><CODE># getconf GNU_LIBPTHREAD_VERSION<BR>nptl-0.60</CODE></PRE>If
you are building your own toolchain to work with a 2.6
system you must, of course, make sure that you've built
the toolchain on a 2.6 system, and that you have enabled
NPTL support in the version of the C library used by
your toolchain. You will also need recent source
codeyou're your C library. For example, if you are
building glibc with NPTL support, version 2.3.3 or
better of the glibc source is recommended. Enabling NPTL
support when building a C library, such as glibc, is
analogous to the mechanism used for enabling
LinuxThreads support for glibc. This is done by using
the configuration option --<B>enable-add-ons=nptl</B>
when configuring glibc, rather than
<B>--enable-add-ons=linuxthreads</B>. The latest NPTL
source code is available <A
href="http://people.redhat.com/drepper/nptl"
target=new><U>here</U></A>. You will also need a recent
version of GCC (3.3.2 or better suggested for x86
platforms, 3.4 suggested for PPC platforms), and a
version of binutils that supports the Call Frame
Information (CFI) directive (2.14.90.0.7 or better
suggested; available <A
href="http://www.kernel.org/pub/linux/devel/binutils/"
target=new><U>here</U></A>).<BR><BR>In general, if your
applications were compiled with earlier versions of GCC,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -