Porting UNIX Applications to the Solaris Operating Environment
This article is a continuation of the Migration Primer, which covers the process of porting UNIX[r] applications to the Solaris
Operating Environment. This article is written at a high-level. It describes how to:
- Port UNIX applications to the Solaris Operating Environment
(versions 2.6, 7 and 8)
- Resolve porting issues
- Take advantage of Solaris Operating Environment migration support services
Resolving General Porting Issues
To successfully migrate UNIX applications to the Solaris Operating Environment, you must address a
variety of porting issues, grouped as follows:
- Hardware Dependency
- Operating System
- Build Environment
This article describes, at a high level, how to resolve these issues.
Resolving Hardware Dependencies
Many porting difficulties arise from nonportable applications written to a particular hardware platform.
This section addresses the following three hardware dependency issues: Proprietary interfaces, byte ordering
(endianness), and alignment.
Making Proprietary Interfaces Portable
Some UNIX applications use proprietary interfaces to perform data operations faster by using unique CPU
instructions. These interfaces often are written for system monitors, image filters, and device drivers.
In most cases, you can make these nonportable interfaces portable in one of the following ways:
- Mapping features to existing standards
- For example, the
aioread
routine used in Sun is the equivalent of POSIX's
aio_read
.
- Creating wrapper functions that encapsulate routines
- An example of a wrapper function is the AIX
compare_and_swap
routine. This routine performs an atomic operation that compares the contents of a single word variable
with a stored old value. An equivalent version for the Solaris Operating Environment has been developed
and was written in assembler.
- Rewriting applications to be hardware independent
Resolving Byte Ordering Issues
Microprocessor byte order, the ordering of individual bytes within a data structure, can be a source of porting problems.
These problems surface when:
- making incorrect assumptions about the byte ordering of the processor on which a program runs.
- exporting structured data from an environment that supports different byte ordering, which causes end-related collisions.
There are two types of byte ordering: big endian and little endian.
Big endian
processors, such as SPARC
processors, order bytes so the
most
significant byte of an integer is stored at the lowest byte address (i.e., low byte).
Little endian
processors, such as x86 processors, order bytes so that the
least
significant byte is stored at the lowest byte address (i.e., low byte).
For example, within a 32-bit word, bytes are ordered from high to low byte on the SPARC processor
(i.e., big endian machine); however, on an x86 processor (i.e., little endian machine), bytes are ordered
from low to high byte. shows how the byte order for the HEX value is different on big and little endian
machines.
Byte Ordering Differences
When addressing 1-byte storage units, both big and little endian machines address these units in the same way.
When addressing multibyte storage units, however, the byte ordering is different.
Big endian machines address larger storage units, typically called halfwords (16 bits), words (32 bits),
and doublewords (64 bits), by giving the address of the numerically
most significant byte of the multibyte storage unit, while little endian machines use the
least significant byte.
In the example in, the value obtained by loading the 32-bit word at the low byte address of a big endian
machine (e.g., 05, 05, 02, 04) is different from the value obtained by loading the 32-bit word at the low
byte address of a little endian machine (e.g., 04, 02, 05, 05).
shows the differences in byte order support among some of the most common hardware platforms.
Byte Order Comparison
Platform
Big End
Little End
Sun SPARC
X
IBM 360/370
X
Motorola 68000 and 88000
X
PA-RISC
X
Power PC
X
Intel family
X
PDP-11
X
VAX
X
Alpha
X
Back to Top
Resolving Alignment Issues
Differences in alignment of
double
and
long double
floating-point variables can cause porting problems. The SPARC processor enforces 8-byte alignment on
double float
variables while the x86 processor enforces only 4-byte alignment.
The following example demonstrates byte alignment problems:
#include <stdio.h>
main()
{
unsigned char bbb[5] = {0x12, 0x34, 0x56, 0x78, 0x9a };
printf("%x", *(int *)(bbb));
printf("%x", *(int *)(bbb + 1));
exit(0);
}
This is an example of a poorly written, non-portable C program. In most cases, however, you will not have a problem porting
between the SPARC and x86 environments because the Solaris 2.x compilation system manages most alignment and
structure padding.
The code in this example can be made to run (with a performance penalty) on SPARC processors using either the
-misalign
and
-misalign2
compiler options.
The
-misalign
option informs the compiler that data is not properly aligned and thus very conservative loads and stores must be
used for data, that is, one byte at a time. Using this option can cause significant performance degradation
when running the program.
The
-misalign2
option assumes that data is not properly aligned, but that data is at least half-word aligned. Although conservative uses of loads and stores must be used for data, the performance degradation when running a program is less than that seen for
-misalign.
Resolving General Operating System Issues
Operating system porting issues occur because of the differences between the Solaris Operating Environment
and the other UNIX operating systems. Some of these issues are standards-related (for example, non-compliance
with Solaris Operating Environment standards) and some are not.
Standards-Related Issues
Many operating system-related migration problems are caused by non-compliance with certain standards.
The Solaris Operating Environment complies with the following standards:
- SVID
- POSIX
- ANSI-C
- X11
- TCP/IP
- X/OPEN
[r]
- 64-bit processing
This article provides a compliance matrix for some common UNIX operating environments.
Back to Top
Compliance Matrix
Solaris 2.6/7
HPUX 10.20
HPUX 11.0
IBM-AIX 4.2
IBM-AIX 4.3
SGI-IRIX 5.3
SGI-IRIX 6.2
SVID
SVID3
SVR4 ABI
SVID3
Base Kernel
Level1API
SVID3
SVID2
Base
SVID2
Base
SVID3
Subset of SVID3
POSIX
IEEE1003.1
IEEE1003.1b
IEEE1003.1c
IEEE1003.2
IEEE1003.1
IEEE1003.2
IEEE1003.1b
IEEE1003.1c
IEEE1003.1
IEEE1003.2
IEEE1387.2
IEEE1003.1
IEEE1003.2
IEEE1003.1
IEEE1003.2
IEEE1003.1
IEEE1003.1b
IEEE1003.1
IEEE1003.1b
IEEE1003.1c
IEEE1003.2
ANSI-C
YES
X3.159
X3.159
X3.159
X3.159
YES
YES
X11
X11R6
OpenGL
X11R6
OSF/Motif1.2.5
X11R6
X11R5
OSF/Motif1.2
SGI-GL3.3
X11R6
OpenGL,1.1
PHIGS,1.0
X11R6
OpenGL
X11R6
OpenGL
TCP/IP
NFS3
PPP
Sockets
NFS
PPP
Sockets
NFS3
PPP
IPv6
NFS3
PPP
Sockets
IPv6
PPP
LDAP
SSLv3
NFS3
PPP
Sockets
NFS3
PPP
Sockets
X/OPEN
UNIX95
UNIX98 1
CDE1.2
UNIX95
CDE1.0
UNIX95
base95
CDE1.0
UNIX95
base95
CDE1.0
UNIX98
base95
CDE1.0
**
UNIX95
base95
64bit
no
yes 2
LP64 3
no
yes
LP64
no
yes
no
yes
Future
IPV6
**
**
OMG/
CORBA
**
**
**
Misc.
JVM,JDK
WebNFS
DirectIO, AIO
Neo/CORBA
Kodak
DCE1.0
KernelJVM
JIT, JDK
WebAdmin
JFS
VLM(4TB)
Monitor, API
Scientific, Lib
JIT,JDK
WebAdmin
DirectIO
DirectIO
KodakPhoto
DirectIO
MagicUI
CosmoVRML
DCE1.1
Back to Top
Solaris Operating Environment Standards
As defined in, the Solaris 7 Operating Environment complies with most SVR4 standards. A few of the
features in SVR4 were not included in the Solaris Operating Environment because these features offer little
to no value to programmers using the Solaris Operating Environment.
The Sun WorkShop compiler allows both old- and new-style C code. The
-X{s,t,a,c,v} options provide varying degrees of compliance to the ANSI C standard. You can choose from the options in.
Sun WorkShop Compiler Options
Option
Name
Description
Xs
K&R C mode
This mode accepts all (pre-ANSI) K&R C syntax. This is the old 4.x cc behavior but is not 100%
SunOS 4.x cc behavior. This is
not
porting your code. Do
not
use this option.
Xt
Transition mode
If the semantics differ between ANSI C and K&R C, this mode causes the compiler to print a warning and use
K&R C semantics. This is the default -X mode in Sun WorkShop 4.0 and up.
Xa
ANSI mode
If the semantics differ between ANSI C and K&R C, this mode causes the compiler to print a warning and use ANSI C
semantics (the opposite of -Xt). This is the default -X mode in SPARCWorks 4.0.
Xc
Conformance mode
In this mode, only ANSI C semantics are used. The compiler will reject any non-ANSI C constructs.
Xv
Verbose mode
Whenever the Xc flag rejects any non-ANSI C constructs, this mode causes the compiler to issue warnings about
any non-ANSI C constructs. This option is used with
Xc.
Back to Top
Non-Standards-Related Issues
Some issues, however, are not specifically standards related, such as out-of-band communications and networking issues.
Resolving Asynchronous Communications Issues
While writing a client/server program using UNIX sockets, it is often desirable to communicate out-of-band (OOB) data,
also called "urgent data" in the TCP world. Following are two examples:
- invoking a CTRL-C in your
telnet/rlogin session.
- using a database front-end requesting termination of an SQL query process.
The use of
ioctl()
and
fcntl()
can be OS specific. To set up a program to receive OOB data in the Solaris Operating Environment, do the following:
Set up a signal handler using
signal()
or
sigaction()
.
#include <signal.h>
/* oobdata is the out-of-band data handling routine */
sigset(SIGURG, oobdata);
...
- Use either
fcntl()
or
ioctl()
to set the process ID or process group ID to route the signal to its own process ID or process group ID.
- The
#ifdef
statements below are examples.
#ifdef USING_IOCTL
#include <unistd.h>
#include <stropts.h>
/* Set the process receiving SIGIO/SIGURG signals to us. */
int pid = -getpid();
if (ioctl(client, SIOCSPGRP, (char *) &pid) < 0) {
perror("ioctl: SIOCSPGRP");
}
#endif
#ifdef USING_FCNTL
#include <fcntl.h>
#include <sys/file.h>
/* Set the process receiving SIGIO/SIGURG signals to us. */
if (fcntl(s, F_SETOWN, getpid()) < 0) {
perror("fcntl F_SETOWN");
exit(1);
}
#endif
...
You can convert the socket to asynchronous using fcntl()
, in which case, you should also set up a signal handler for the SIGIO signal. The handler reads data asynchronously
off the socket.
With the Solaris Operating Environment, SIGIO is sent whenever the socket changes state from empty to non-empty
(not whenever new data arrives on the socket).
Back to Top
#include <fcntl.h>
#include <sys/file.h>
...
sigset(SIGURG, io_handler);
...
/* Make a socket asynchronous.
*/
int fileflags;
int s;
...
s = socket(AF_INET, SOCK_STREAM, 0);
...
if (fileflags = fcntl(s, F_GETFL ) == -1)
perror("fcntl F_GETFL");
exit(1);
}
if (fcntl(s, F_SETFL, fileflags | FNDELAY | FASYNC) == -1)
perror("fcntl F_SETFL, FNDELAY | FASYNC");
exit(1);
}
struct sockaddr_*
If code is being moved from a BSD Reno/4.4 environment to the Solaris Operating Environment, problems will
arise when dealing with the sin_family and sin_len fields of the BSD version of the sockaddr_* family of structures.
the Solaris Operating Environment has a two-byte sin_family field which includes both the sin_len and sin_family
fields found in the BSD version. The Solaris Operating Environment does not have a sin_len field in any sockaddr_* structure.
Resolving Signal Issues
A signal is a notification of an event that can be received by a process. A signal can be associated with an
event in the hardware (for example, a hardware fault, timer expiration, or terminal activity)
or the software.
Programming signals can become somewhat complicated. An excellent reference is "Advanced Programming in the UNIX
Environment" (Stevens, W. Richard. Advanced Programming in the UNIX Environment. Addison-Wesley). According
to this book, "SVR4 provides a signal function that provides the older, unreliable signal semantics" (page 298).
Stevens also provides an example of a "reliable version" of signal(), using POSIX sigaction().
Consider replacing any code using signal functions with code based on sigaction().
In some flavors of Unix, system calls are not restarted when a signal occurs while other flavors do restart the calls.
The default behavior of the Solaris Operating Environment is not to restart system calls when a signal occurs.
This behavior can be modified by using sigaction(2) when specifying behavior for signals. The signal(2)
interface is provided for backward compatibility.
Back to Top
The following sample code enables restart of system calls when a particular signal is seen:
struct sigaction act;
act.sa_handler = func;
sigemptyset(&act.sa_mask);
act.sa_flags = SA_RESTART;
if (sigaction (signo, &act, 0) == -1)
perror ("sigaction");
Additionally, some variants of UNIX have different behavior once a signal handler is activated. The Solaris Operating
Environment resets the signal disposition to the default value before activating the signal handler. This can lead to
some unexpected side effects when another signal is sent to a process before it can run its signal handler but after
the handler has been reset to the default action. If the default action is to ignore the signal, the second signal will
never be seen. If the action is to terminate the process, an unexplained core dump can occur.
This can be avoided by either using sigaction() to establish signal handlers and not setting the SA_RESETHAND
bit in the sa_flags field or if signal() is used, clearing the SA_RESETHAND bit in the sa_flags
field via sigaction().
To better understand the implementation of the signals, traditional UNIX signal behaviors can be grouped in the following
two categories:
- 4.3BSD
- When a signal occurs, further occurrences of the signal are automatically blocked and func is called.
- A return from the function unblocks the handled signal and continues the process at the point it was interrupted. The handler
func remains installed after a signal has been delivered.
- If a caught signal occurs during certain system calls, thus terminating the call prematurely, the call is automatically
restarted. In particular, this can occur during a read(2V).
- There is no definitive list of which system calls are restartable on any particular UNIX system when using BSD signals.
In the Solaris Operating Environment, this list would include read() and write() (on slow devices).
- System V
- When a signal occurs, func
is called. Further occurrences of the signal are not
automatically blocked. The value of func
for the caught signal is reset to
SIG_DFLbefore func is called, unless the signal is SIGILL or SIGTRAP.
- A return from the function continues the process at the point it was interrupted. The handler func
does not remain installed after a signal has been delivered.
The POSIX sigaction() function is highly recommended, since it provides considerable flexibility to achieve desired behaviors.
Furthermore, some UNIX systems provide a signal `broadcast' mechanism whereby an event can trigger the delivery of a signal to
each process in a process group. For example, AIX provides the (non-portable) pgsignal kernel service for this mechanism.
Building Shared Objects
Most, if not all UNIX systems now support shared objects and libraries in one form or another. Shared objects are usually
worthwhile and beneficial, except for some small applications that are very short-lived (where the load time is greater than
the runtime).
Porting issues related to the creation of shared objects generally revolve around environmental issues in build files,
compiler flags, link editor and run-time loader arguments.
Under older versions of AIX (3.x), for example, shared symbols (nonstatic variables and functions) were not, by default,
exported from or imported to shared objects. Symbols had to be explicitly specified in import and export lists (files) at
build time in order for them to be visible to other modules. AIX shared objects are archived into the .a
archives like any other object. HP-UX shared libraries use the
.sl suffix. the Solaris Operating Environment uses the .so suffix.
By default, the Solaris Operating Environment compiler (cc) and linker (ld) will compile and link dynamic
executables which use shared libraries.
To create a shared object in the Solaris Operating Environment, type:
Back to Top
-c libsource.so -Kpic source.c
Using the -Kpic option, the compiler generates code which can be shared among all users of the library without requiring that
each user have their own copy of the library text. Libraries with more than 2048 external symbol references must be
generated with the -KPIC option.
To create a shared library from two shared objects, for example, type:
cc -G -Kpic -o shared_lib_name.so source1.c source2.c
TheSolaris Operating Environment LD_LIBRARY_PATH environment variable and the -R compiler
flag also come into play and are used to tell the loader where to look for shared objects at run time.
Another related issue concerns the initialization of `static constructors' in shared objects generated by the C++ compiler. Typically, globally scoped objects (i.e., global variables of a class) in a C++ program are not explicitly initialized within the program, per se. C++ globals must, however, be constructed by the run-time loader before entering the `main' statement. The Solaris
CC command sets this all up for you (with the -G flag) automatically. Other UNIX systems, however, do not.
AIX, in particular, requires the programmer to build `munch' routines that help the compiler figure out how to initialize,
or construct, global objects from shared libraries.
Resolving 64-bit Issues
When moving to the Solaris 7 Operating Environment, new issues arise as a result of its 64-bit nature, in addition to the
other issues discussed in this article.
Because the 32-bit Application Programming Interfaces (APIs) supported in the Solaris 7 64-bit Operating Environment are
the same as the APIs supported in the 32-bit Solaris Operating Environments, no changes are required for
32-bit applications between the 32-bit and 64-bit environments. However, recompiling your application as a 64-bit application
can require some cleanup.
Two basic issues arise when converting 32-bit applications into 64-bit applications:
- Data type consistency and the different data model
- For example, because the size of the long data type changes to 64 bits from 32 bits on a 32-bit environment, many 32-bit to 64-bit conversion problems may occur.
- Interoperation between applications using different data models
- For example, your 32-bit application may have to exchange data with a
64-bit application. In this case, differences in data types may cause problems.
For more information about making your 32-bit applications run on the
Solaris 7 64-bit Operating Environment, refer to the "Extending 32-bit Applications" section in the
Developing 64-bit Applications for the Solaris 7 Operating Environment article.
Back to Top
Resolving Application Issues
Header Files
Various application porting issues unfortunately arise because of inconsistencies in header files (include files)
from one UNIX vendor, or UNIX standard, to another. Inconsistencies in the physical location of some header files
also occasionally occur, and less often, the name of a header file might differ from one UNIX platform to another.
In the simplest case where headers appear to be missing, all that needs to be done is to explicitly tell the compiler
where to look for by using the
-I
compiler argument.
cc -I /include_dir1 -I/include_dir2 source_file.c
In Solaris 2.6 andthe Solaris 7 Operating Environment, there are now the following entries:
-
/usr/include/Mrm
, a link to
/usr/dt/include/Mrm
-
/usr/include/X11
, a link to
/usr/openwin/include/X11
-
/usr/include/Xm
, a link to
/usr/dt/include/Xm
This allows many programs to compile without having to specify the
-I
option to specify a different location for X and Motif include files.
Along a similar line, a C source file might contain the following include directive.
#include <sys/limits.h>
The Solaris Operating Environment
limits.h
file appears in the
/usr/include
directory and not in
/usr/include/sys as the example above expects. In this case, one solution is to modify the source file using
conditional compiler directives.
#ifdef AIX
#include <sys/limits.h>
#endif
#ifdef __sun
#include <limits.h>
#endif
Using the conditional directive helps you migrate the code to the target the Solaris Operating Environment
platform while maintaining the original source unaltered.
Another twist, is where the application source provides its own custom prototype for a library function but
this custom declaration later causes a conflict during the migration to the Solaris Operating Environment.
For example, this code sample compiles successfully on HP-UX 9.x:
Back to Top
#include <string.h>
...
int strcasecmp(char *s1, char *s2);
...
Compiling under the Solaris Operating Environment, however, generates error messages:
% cc tx1.c
"strtest.c", line 16: identifier redeclared: strcasecmp
current : function(pointer to char,
pointer to char)
returning int
previous: function(pointer to const char,
pointer to const char)
returning int : "/usr/include/string.h", line 82
cc: acomp failed for tx1.c
The error messages indicate that the custom declaration is conflicting with a system provided prototype appearing in the
string.h header file. A solution is to remove the custom declaration.
#include <string.h>
#ifndef __sun
int strcasecmp(char *s1, char *s2);
#endif
...
When attempting to fix these sorts of problems, use the Solaris Operating Environment
man pages to help determine correct header dependencies. Using the correct prototypes and
signatures for function declarations and invocations helps you create portable code that behaves as expected.
Command Paths
Another issue with porting applications occurs when commands such as
make
,
vi
, and
cc
, are located in different places.
lists the host operating system and path for
make
in different versions of UNIX.
Back to Top
Paths for make
Operating System
Path for
make
Solaris 2.4, 2.5.1, 2.6, 2.7
/usr/ccs/bin/make
HP-UX 10.20
/usr/bin/make
SGI-IRIX 6.3
/sbin/make
,
/bin/make
,
/usr/bin/make
SCO OpenServer 5.0.2
/bin/make
,
/usr/bin/make
SCO UNIXware 2.11
/bin/make
,
/usr/bin/make
Redhat Linux 5.0
/usr/bin/make
SIEMENS-SINIX 5.44
/usr/bin/make
For more information about the paths of other frequently used commands, refer to
Paths to Frequently Used Commands
, an addendum to this article.
Resolving O.S. Specific Migration Issues
Some porting issues are specific to individual UNIX operating systems. Sun Microsystems has researched
many of these issues and developed ways to either avoid or resolve them, so your application will port easily.
This section describes how to meet most common porting challenges for the following three operating systems:
Resolving HP-UX Issues
Be aware of the following key issues when porting applications from HP-UX to the Solaris Operating Environment:
- Resolving Common HP-UX Issues
- Dealing with NULL Pointers
- Making NULL Address Valid (0@0)
Back to Top
Resolving Common HP-UX Issues
You might encounter the following issues when porting an application from HP-UX.
- ltoa() and lotstr() are proprietary HP-UX long-integer-to-string conversion routines. A workaround is to replace these functions with sprintf().
- libucb.a in /usr/ucblib is part of the Solaris Binary Compatibility Package (BCP) for Solaris Operating Environment compatibility. It contains Berkeley Software Distribution (BSD) and functions specific to the Solaris Operating Environment that were not included in SPEC 1170 or SV standards.
- When using the fourth optional argument to semctl(2), the semun union must be explicitly defined and passed. SV.3 and older systems, such as HP-UX, assumed the fourth argument type based on the command sent (i.e., argument 3).
A workaround is to replace the shl_*() functions that represent the HP-UX proprietary shared library programmatic
interface with the equivalent Solaris Operating Environment dl*() functions. For more information, refer to the
sections on dlopen(), dlclose(), and dlsym() in the Solaris Compiler Manual.
Libraries opened with
dlopen()
can call functions within the application, and the applications can locate static data members of the loaded shared
object. Also, the handle argument, returned from the open and used in subsequent API calls is referenced
differently. HP uses
shl_t*
, which is the address of the handle pointer returned in
shl_open()
. In the Solaris Operating Environment, only the reference to the handle is required,
void *
, as returned unchanged from
dlopen().
- HP-UX uses the ile suffix .sl to denote a shared library while the Solaris Operating Environment, and almost all other variants of UNIX, use .so.
- HP-UX 9.x conforms to an older revision of the POSIX thread specification, 1003.4a draft 4 DCE threads. The Solaris Operating Environment complies with the most current accepted version, 1003.1c. Slight changes have been made in
pthread interfaces since the earlier version, mainly to argument types.
- Access Control List API implementations differ, but equivalent functionality exists under Solaris 2.x with the
acl() and facl() function calls.
- File system interface routines in the Solaris Operating Environment use the SV.4 Virtual File System (VFS) capabilities
and, hence, the 'vfs' functions. Even though function names are similar, arguments and return types differ. For
example, HP-UX uses the checklist struct while the Solaris Operating Environment uses the
vfstab struct. In addition, Solaris Operating Environment functions take FS structure pointers as arguments and return
int.
Dealing with NULL Pointers
An all too common source of problems during a migration to the Solaris Operating Environment is the `erroneous' handling of
NULL pointers by many applications.
A NULL pointer is a pointer initialized to zero (0). Dereferencing a NULL pointer should literally mean dereferencing memory
address zero. Ordinarily, address zero should be considered to be an invalid memory location for most user level applications,
and attempting to access address zero, like any other invalid address should cause an error condition (one would think). The
system should send a SIGSEG signal (segmentation fault) to the application which will then abort with a core dump.
And this is exactly what the Solaris Operating Environment does (but there is a solution below). Many other UNIX systems are
apparently more accommodating with respect to NULL and this fact often leads application programmers using those systems to adapt
some seemingly `lazy' habits in their treatment of NULL.
A very common case is demonstrated by this "NULL is equivalent to Empty String" example.
char *p = NULL;
printf("P is %s\n",p);
HP-UX and AIX systems will execute the printf() above as though
p is pointing to an empty string (p = "";)
Another example:
struct {
int a;
} *sp;
...
sp = NULL;
printf("a is %d\n", sp->a);
...
Both HP-UX and AIX will print `
a is 0'.
The above examples illustrate poor coding practices which should ideally be fixed in the source. Because these
practices occur so often, identifying and fixing all occurrences can be impractical.
As described above, the Solaris Operating Environment aborts with a core dump on both of the above examples, by default.
There is a solution for the Solaris Operating Environment whereby a memory page can be explicitly mapped into a process
at address zero in order to avoid SIGSEV's when such programs dereference NULL pointers. A shared library is also
available which can be used to validate address zero without changing the source at all.
Back to Top
Making NULL Address Valid (0@0)
Sun Microsystems engineering developed a solution that allows mapping a page of memory into process address
0
; making
NULL
, address
0
, valid.
Setting the
LD_PRELOAD
environment variable to point to the
lib0@0.so
library causes the runtime linker to load
it upon any invocation of a process by the
user, before other libraries are loaded. The
#pragma
init
directive causes the runtime linker to invoke the
zero_at_zero()
function immediately after loading.
Runtime:
% setenv LD_PRELOAD/usr/lib/0@0.so.1
HPUX to Solaris Operating Environment System Call Issues
This section describes some of the system call issues that you must resolve when porting applications from the
HPUX platform to the Solaris Operating Environment.
Select
The default size of the fd_set used on Solaris systems is 1024. HPUX uses a default of 2048. Applications requiring
more than 1024 descriptors in an fd_set on the Solaris Operating Environment must include a #define FD_SETSIZE NNNN
line before any #include specifications.
Back to Top
sysconf
Various requests have no equivalent in the Solaris Operating Environment. These are:
AES_OS_VERSION
CLOCKS_PER_SEC
CPU_CHIP_TYPE
CPU_KEYBITS1
CPU_VERSION
HW_32_64_CAPABLE
IO_TYPE
KERNEL_BITS
LIBC_VERSION
PROC_RSRC_MGR
SECURITY_CLASS
All items beginning with
POSIX
,
XOPEN
, or
XBS5
(e.g.,
POSIX_FSYNC
) have the same name on the Solaris Operating Environment but are prefixed with an underscore (e.g.,
_POSIX_FSYNC
).
Back to Top
setacl
See
acl(2)
and
facl(2)
for the Solaris Operating Environment mechanisms for ACL manipulation.
ttrace and ttrace_wait
Process management (for both single and multi-threaded processes) is accomplished via the
proc(4)
interfaces on the Solaris Operating Environment.
vfsmount
This system call is deprecated in HPUX. Use
mount(2)
on the Solaris Operating Environment.
wait3
The Solaris Operating Environment will return
EFAULT
in addition to the errors returned by HPUX.
EFAULT
is returned if one or more of the arguments point to an illegal address.
Back to Top
waitid
The Solaris Operating Environment will return
EFAULT
in addition to the errors returned by HPUX.
EFAULT
is returned if one or more of the arguments point to an illegal address
Resolving AIX Issues
Be aware of the following key issues as you port applications from AIX to the Solaris Operating Environment:
- Resolving IPC Issues
- Dealing with NULL pointers
- Making NULL Address Valid(0@0)
Resolving IPC Issues
On AIX, all processes that are blocked on a
msgrcv()
against the same message queue will become unblocked when a message is delivered to the queue. One of the random processes will return successfully and receive the message. The other processes will return
-1
with
errno
set to
EINTR
.
In the Solaris Operating Environment, only one process will unblock when a message is sent to the queue.
AIX has a hard limit of 16 global shared memory segments. Because six of these are reserved for the kernel,
only 10 shared memory segments are available for user programming. Many third-party products providing more
extensive granularity are used in AIX, most of which are not necessary in the Solaris Operating Environment.
Back to Top
Dealing with NULL Pointers
- Freeing non-
malloc()
'd space dumps core, but the SIGSEGV occurs on a subsequent call to
malloc()
in
realfree().
- Passing a pointer to
realloc()
that has already been freed using
free()
causes a SIGSEGV (core dump).
- The information returned by
getrusage()
is significantly different. For more information, refer to the
proc(4)
man page (type
man proc(4))
, SunOpsis Volume 1, Number 3, and the Solaris Migration FAQ (http://
nce.sun.ca/resources/SolarisMigrationFAQ.html).
Solaris 2.5 only provides CPU time usage with the
RUSAGE_CHILDREN
argument and, as such, does not fully support the BSD
rusage()
semantics.
- When invoking
getpwent()
with the
/etc/shadow
file, the password in the returned structure is from
/etc/passwd
, which is not the correct passwd. For more information, refer to
getspent(3c)
.
- Also the information returned may differ depending on which name service provider is set in
nsswitch.conf
.
-
select()
is implemented using
poll()
; therefore, the timeout value has only millisecond resolution.
Making NULL Address Valid (0@0)
Refer to the same section under."
Resolving IRIX Issues
Be aware of the following two key issues when porting applications from IRIX to the Solaris Operating Environment:
- Implementing Replacements to the m_fork Function
- Dealing with NULL pointers
Only the first topic is discussed in this section. The second topic is discussed in the previous section:."
Back to Top
Implementing Replacements to the m_fork Function
The IRIX
m_fork()
function uses
sproc()
to create "subtasks" that have unique process IDs, but are otherwise very similar to threads. When using threads in Solaris in their place, be aware of other interfaces that could break, for example,
sleep()
.
Depending on the IRIX version,
sleep()
may be implemented with the
sginap
system call rather than with
alarm()
. With the Solaris Operating Environment's POSIX threads, the semantics of
alarm()
are perprocess, that is, the resulting SIGALRM is sent to the process and not necessarily to the calling thread. A replacement can be coded using
mutexes
and timed condition waits.
You will need to manage this thread count yourself. The number you set usually will be at least the number of CPUs, as returned by
sysconf
(
_SC_NPROCESSORS_ONLN
).
In the main thread, use
pthread_join()
to suspend processing and wait for the slave threads to finish. This function is analogous to
pthread_self().
It is possible to implement a replacement using POSIX threads, Solaris threads, or LWPs.
M_fork()
takes up to six arguments to pass through to the function, but the list is not terminated.
Dealing with NULL Pointers
Refer to the same section under."
Resolving Miscellaneous Porting Issues
This section describes solutions to miscellaneous issues that you might encounter while porting UNIX applications
to the Solaris Operating Environment.
Signed or Unsigned char
By default the Solaris Operating Environment
cc
compiler assumes all
char
definitions specify signed char. Some other vendor's compilers (such as AIX and IRIX) assume unsigned char.
This can lead to unusual differences in how a program appears to behave.
Back to Top
#include <stdio.h>
main()
{
char c;
int i;
c = 255;
i = c;
printf("c=%x, %d i=%x,%d\n", c, c, i, i);
exit(0);
}
The example above produces the following output on SGI IRIX:
c=ff, 255 i=ff,255
But under the Solaris Operating Environment the output is quite different:
c=ffffffff, -1 i=ffffffff,-1
Because both
c
and
i
are signed in the Solaris Operating Environment, the sign bit gets extended during the "promotion" from
char
to
int
.
Solution
Modify
char
definitions as in the following example:
unsigned char c;
NULL Arguments
Some library functions in the Solaris Operating Environment require non-null arguments, while other UNIX systems might allow
null
(
0
) values. For example
setsockopt()
in the Solaris Operating Environment requires that the 4th argument be non-null (
cf: man setsockopt
).
sleep Generates Alarm Signals Under the Solaris Operating Environment
The
sleep()
function under the Solaris Operating Environment is implemented by setting an alarm signal
(SIGALRM). Other UNIX systems do not necessarily operate in the same way.
Back to Top
Solution
If unexpected
SIGALRM
signals might become an issue when porting a program to the Solaris Operating Environment using
sleep()
function, use the Solaris Operating Environment
nanosleep()
call which does not use signals.
dirent Structures Can Differ
At least under AIX, the
dirent
structure related to directory operations such as
readdir()
is slightly different from the Solaris version.
Under AIX the structure contains the following members:
ulong_t d_offset;/* actual offset of this entry */
ino_t d_ino; /* inode number of entry */
ushort_t d_reclen; /* length of this entry */
ushort_t d_namlen; /* length of string in d_name */
char d_name[_D_NAME_MAX+1]; /* name of entry (filename) */
The Solaris Operating Environment (and IRIX) structure is:
struct dirent {
ino_t d_ino;
off_t d_off;
unsigned short d_reclen;
char d_name[1];
};
Back to Top
sys_errlist and sys_nerr
References to
sys_errlist
and
sys_nerr
in the Solaris Operating Environment are not allowed for 64-bit programs.
Solution
References to
sys_errlist
and
sys_nerr
in the Solaris Operating Environment are deprecated. All programs that want to access
sys_errlist
and
sys_nerr
should do so via the
strerror(3C)
interface. This will be the only supported way to do this in the future.
struct FILE
Sources using
struct FILE
and its members do not compile.
Solution
The 64-bit Solaris Operating Environment treats the
FILE
structure as an opaque structure. Any application that directly accesses the structure's fields does not compile on the 64-bit Solaris Operating Environment, but compiles on 32-bit Solaris as long as the application uses the visible fields. Use only the supported interfaces described in
stdio(3S)
and
eschew
, and avoid accessing the structure's fields directly.
Back to Top
flock
Relinking binaries that use
flock
might fail.
Solution
A short-term solution is to modify your link line to include the BSD libraries as follow:
LDFLAGS=$LDFLAGS -L /usr/ucblib -lucb
The
flock()
routine is provided by the BSD compatibility libraries from
/usr/ucblib/libucb.a
.
The right solution is to use the
flock(3C)
function instead which offers both advisory and mandatory locking.
Solaris Operating Environment Migration Support
Sun Microsystems offers a wide range of support services to meet your porting needs. The range extends from
free tools and focused migration consulting assistance, or having Sun Professional Services migrate your
applications for you.
The following four sections provide information on how to meet the most common migration challenges:
- Migration Support Tools
- Migration Consulting Support Services
- Training
- Sun MigrationSM
Back to Top
Migration Support Tools
Sun Microsystems offers a variety of tools to help you make the transition to the Solaris Operating Environment from other UNIX
[r]
platforms. The following tools are discussed:
- score - Porting Applications
- scriptran - Porting Scripts
- ABI Tools
- Sun WorkShop
These tools come with the Solaris 2 Competitive Migration Kit describes the tools for
porting source code and admin scripts.
Tools for Porting Source Code and Admin Scripts
Tool
Description
score
Helps identify year-2000 and migration issues in porting your old UNIX C and C++ code to the Solaris Operating Environment 2.x.
scriptran
Highlights issues in porting your old UNIX shell scripts to the Solaris Operating Environment 2.x.
In addition, the Application Binary Interface Program provides a series of ABI tools. The ABI tools function as
interface analyzers: They evaluate code for compatibility with the Solaris Operating Environment and help you write
better, more streamlined code.
Back to Top
score - Porting Applications
The
score
utility analyzes the difficulty of porting C and C++ source files from your previous UNIX environment
to the Solaris Operating Environment 2.x.
score
provides a quick way to estimate the total effort required for the port and to identify the porting
issues in your source files.
score
enables developers to print various reports, depending on the options given. These reports can either
estimate the effort required to port a section of code or provide detailed information about the
specific changes needed.
The
score
tool works by parsing C/C++ source code files. In the process, score identifies all
functions by referencing an issue database.
The
score
utility is available for each of the following four platforms:
- HP-UX 9.x, 10x
- IBM AIX 3.2.x
- IBM AIX 4.2
- SGI IRIX 6.
For additional information about
score
, refer to the
Solaris Competitive Migration Cookbook.
Back to Top
scriptran - Porting Scripts
The
scriptran
utility scans
Bourne
shell scripts and reports any porting issues caused by differences between your old UNIX and Solaris 2.x.
scriptran
scans Bourne shell scripts looking for functions addressing system commands to see if the command:
- is now obsolete.
- is in a new location that is not in the user's path.
- uses a flag that is obsolete.
- uses a flag that has changed functionality.
- output has changed and is redirected.
Passing shell scripts through the
scriptran
filter will identify most porting issues. After adjusting scripts for the Solaris Operating Environment,
developers can continue porting their applications.
The scriptran utility is available for each of the following platforms:
- HP-UX 9.x, 10x
- IBM AIX 3.2.x
- IBM AIX 4.2
- SGI IRIX 6.
For additional information about
scriptran
, refer to the
Solaris Competitive Migration Cookbook.
Back to Top
ABI Tools
The Solaris ABI Program produces tools to help developers test the binary compatibility of their
products on new releases of the Solaris Operating Environment. All these tools are
free of charge.
For example,
Appcert
, a free tool from Sun Microsystems, tests your applications' compatibility with the Solaris Operating Environment. Applications that pass the
Appcert
tool's compatibility test and have registered with Sun can legally
display the Solaris Compatible logo.
Consider the ABI tools as interface analyzers: They help you write better, more streamlined code.
Additional applications for these tools include:
- Interface call frequency analysis.
- Interface call type analysis. For example, the ABI technology allows an application to check specific interface usage. Sun developed a specific tool to help test your code for Year-2000 (Y2K) dependencies. Information about the Y2K tool and the ABI technology itself are available free to help you make your application Y2K ready.
- Assistance with the testing and release process for your release engineering teams.
Solaris ABI Tools are available at the Application Binary Interface Program web site.
Sun WorkShop
Sun Microsystems' award-winning, high-performance development environment--Sun Visual WorkShop
C++--is an intuitive, graphical toolset that speeds developers' performance and improves productivity.
The performance tools within Sun Visual WorkShop C++ allow you to run applications faster than ever.
Faster compilers optimize code, making for more efficient use of the architectural features of the SPARC
hardware. Multithreading makes the most efficient use of both single-processor and multiprocessor systems.
Sun WorkShop products are linked in a tightly integrated development environment that includes everything
you need--the elements don't have to be selected, assembled, and coordinated separately.
Migration Consulting Support Services
Sun Microsystems provides a broad range of support services for migrating UNIX applications
to the Solaris Operating Environment. These include the following services:
- Project planning
- Feasibility study
- Application porting
- Infrastructure migration
- Technical hotline/email support
Consider these services to help you migrate applications smoothly. After all, migration is an elaborate
task and varies depending on your environment. If you are interested, contact Solaris Developer Services.
Project Planning
The Competitive Migration Program provides project planning services to estimate the migration project cycle and the resources required, and to identify milestones and the migration path. The project plan and schedule are tailored to your environment, resources, and other requirements.
Back to Top
Feasibility Study
Before deciding to port to the Solaris Operating Environment, you must thoroughly analyze applications that
rely heavily on proprietary features of your old operating system. The Competitive Migration Team creates
a custom feasibility study to analyze a customer's existing system environment and applications, evaluate
the complexity, and provide a migration solution for the customer.
Application Porting
The Competitive Migration Team helps port your key applications, build environment, and production environment
to the Solaris 2.x Operating Environment.
Infrastructure Migration
The Competitive Migration Team helps you migrate your existing system configurations to the Solaris 2.x Operating
Environment. Advanced Solaris Operating Environment features can be introduced and applied
to enhance your environment.
Technical Hotline/Email Support
If you are a registered customer, NAFO Customer Engineering provides you with technical Hotline and Email
support. You can call a toll-free number or send email to the Competitive Migration Program email alias.
Calls are handled by the NAFO Customer Engineering Solaris Developer Support Center, which operates from
9 a.m. to 7 p.m. EST.
Back to Top
Training
Training is available from the North American Field Office (NAFO) and Sun Education Services (SunEd). NAFO
Customer Engineering Training Courses include:
- Solaris 2 Application Porting Course for Developers
- for HP-UX to the Solaris Operating Environment
- for IBM AIX to the Solaris Operating Environment
- for SGI IRIX to the Solaris Operating Environment
- Solaris 2 System Administration
- Multithreaded Programming
- Solaris 2 Realtime for Developers
- NIS+ Administration
SunEd Courses are available to all developers.
SunMigrationSM Services
If you are porting to Solaris 2.x, SunMigration Services can help. SunMigration Services provides a portfolio of
porting and migration services to help you migrate applications and Operating Environments
to Solaris 2.x.
SunMigration Services provides:
- Proven expertise
- Best-of-breed tools
- Substantial time savings
Currently, support is provided for migrating from Solaris 1.x to Solaris 2.x. Migration support
from additional environments is also available. For additional information,
contact SunMigration Services.
August 1999
Back to Top