分类:
2010-11-22 15:30:35
- | |
- | |
- |
许多开发者正在编写在 Linux 操作系统下运行的应用程序。随着 Solaris 10 OS 中引入许多新增功能,以及随着 Sun 最近对于在基于 AMD 和 Intel 处理器的计算机上支持 Solaris OS 的格外重视,开发者对于能够在 Solaris 平台上开发应用程序越来越感兴趣了。本文分析了这两种操作系统的开发环境之间的相似和不同之处。负责将应用程序从 Linux 移植到 Solaris OS 的人员,或者之前已具有 Linux 经验而想要学习在 Solaris OS 中进行开发的程序员,将会从本文中获益。
在本文中,术语 "Solaris" 指 Solaris 10 OS(和 OpenSolaris),而 "Linux" 指 Linux 2.6。所涵盖的许多详细信息也适用于 Solaris 和 Linux 的早期版本。Linux 分发版本是指通用分发版本,而示例在 SuSe 9.1 中进行了测试。另外,本文集中讲述使用 C 编程语言编写的应用程序,而使用 C++ 时的情况应该与使用 C 时类似。由于基于 Java 技术的应用程序不应有特定于 Linux 或 Solaris OS 的函数调用,因此可以按原样移植。
本文讨论应用程序程序员和分析员能够看到的有关 Solaris OS 与 Linux 的相似和不同之处。本文并不代表对不同之处的全部说明,也不是用于说明一种 OS 优于另一种。相反,本文旨在帮助那些熟悉其中一种 OS 的开发者能够尽可能快地使用另一种 OS。
与 POSIX 兼容且不含任何特定于 Solaris OS 或 Linux 的系统调用或库函数的简单应用程序应可在两种 OS 之间移植,而无需进行更改。您应该能够编写您的应用程序、针对 Solaris OS 或 Linux 进行编译,然后针对另一种 OS 进行简单重新编译,这样它应该就能正常使用。这两种 OS 中的大多数系统调用和库例程都属于这种类型。
Linux 中的许多系统调用在 Solaris OS 中作为库函数存在,反之亦然。例如,sched_setscheduler()
在 Linux 中为一个系统调用,而在 Solaris OS 中为一个调用 priocntl(2)
系统调用的库函数。priocntl(2)
系统调用在 Linux 中不存在,但 Linux 不支持除分时和实时以外的多个调度程序。本文接下来的一节将系统调用按功能分成多个部分逐一进行介绍,并对比每种 OS 提供的功能。
来自 Linux 领域的大多数应用程序和工具包都可直接编译和运行,而无需进行更改。这包括 gcc、emacs、MySQL、perl 以及许多其他应用程序和工具包。 中提供了许多软件包的预编译二进制代码。
所提供的有关比较 Linux 和 Solaris OS 的文章为数并不多,但大多数这样的文章都是对这两种操作系统的早期版本进行比较。您可以通过在 Web 中搜索 "Linux and Solaris comparison"(Linux 与 Solaris 的比较)来找到这些文章。请参见有关 Solaris OS 和 Linux 的《Seal Rock Research White Paper》(pdf),该文中涵盖了 Solaris 10 OS 和 2.6 Linux。 是讨论有关从 Solaris OS 移植到 Linux 问题的若干页的开始部分。
Solaris OS 和 Linux 之间以及 Linux 的不同分发版本之间存在着各种管理差异。Solaris 10 OS 中引入了“服务管理框架”(Service Management Framework, SMF),较之以前的 Solaris 版本,这是一个很大的变化。本文将不涵盖系统管理方面的差异,但某些对开发者有影响的部分除外。
Linux 中存在的大多数系统调用和库在 Solaris OS 中也同样存在。本节将介绍在两种系统间存在差异的系统调用和库例程。系统调用和库例程的分类如下:
Solaris OS 在 /usr/include/sys/syscall.h
中保存着系统调用的列表。Linux 在 /usr/include/asm/unistd.h
中维护着相同的信息。(请注意,Linux 和 Solaris OS 都有 unistd.h
和 syscall.h
文件,并且在某些情况下,这些文件的内容相同。)
Solaris OS 和 Linux 的 /usr/share/man/man2
中提供了系统调用的文档。(Solaris OS 具有一个从 /usr/man
到相同位置的符号链接。)库例程记录在各种手册部分。有关 Linux 和 Solaris OS 的库部分的概述,请参见 man intro.3
。请注意,与 Linux 相比,Solaris OS 对库例程的划分更细。例如,在 Solaris OS 中,aio_read()
记录在 aio_read(3RT)
中,而在 Linux 中,它记录在 aio_read(3)
中。其结果是,使用 aio_read()
在 Solaris OS 中编译程序时,您必须通过 -lrt
及 compilation/link 命令包括实时库,而在 Linux 中则不需要。
Linux 和 Solaris OS 都附带提供了 200 多种不同的库,这些库中定义了 50,000 多个函数。
下表列出了 Linux 和 Solaris OS 中的某些库。请注意,这并不代表完整的列表。另请注意,其中的某些库必须独立于标准系统安装而单独下载和安装。
表 1:Linux 和 Solaris OS 中的某些库 |
Solaris OS |
Linux |
说明 |
||
---|---|---|---|---|
libc |
libc |
标准 C 库(POSIX、SysV、ANSI,等),请参见 Solaris OS 中的 man libc。 |
||
libucb |
libc |
UCB(柏克莱加州大学,University California Berkeley)兼容性库 |
||
libmalloc |
libc |
有多种不同的 malloc 库;缺省库位于 libc 中。 |
||
libsocket |
libc |
套接字库(在 Linux 中,套接字位于 libc 中)。 |
||
libxnet |
libc |
X/Open 联网库 |
||
libresolv |
libresolv |
DNS 例程(在 Solaris OS 中为 inet_* 例程) |
||
libnsl |
libnsl/libc |
网络服务库(linux-nis/nis+ 例程) |
||
librpc |
librpc |
RPC 函数 |
||
libslp |
libslp |
服务定位协议 |
||
libsasl |
libsasl |
简单验证和安全层 |
||
libaio |
libaio |
异步 I/O 库 |
||
libdoor |
门支持( door_create() 、door_return() ,等) |
|||
librt |
librt |
POSIX 实时库 |
||
libcfgadm |
配置管理库 |
|||
libcontract |
约定管理库(请参见 Solaris OS 中的 man contract.4 ) |
|||
libcpc |
CPU 性能计数器库(在 Linux 中,可能需要安装内核模块) |
|||
libdat |
直接访问传输库(请参见 ) |
|||
libelf |
libelf |
ELF 支持库 |
||
libm |
libm |
数学库 |
||
以下各节将更加详细地介绍某些系统调用和库。我们将集中讲述它们在系统之间的不同之处。
对于大多数套接字和联网代码而言,只需针对所使用的 OS 对其进行重新编译,所生成的可执行代码应该就能正常使用。本节对通常在 Solaris OS 和 Linux 中使用的与网络有关的系统调用和库例程进行了比较。
socket()
除了 AF_UNIX
、AF_INET
和 AF_INET6
域参数以外,socket()
例程在 Solaris OS 和 Linux 中还具有其他值。在 Solaris OS 中,AF_NCA
域用于指定网络高速缓存和加速器(请参见 nca(1)
)以便与套接字一起使用。大多数地址族(域)都在 Linux 和 Solaris OS 中同时存在。注意:有关可能的地址族,请参见 Solaris OS 中的 /usr/include/sys/socket.h
以及 /usr/include/linux/socket.h
。但可能需要下载或编写代码才能支持某些域。
Linux 将若干其他域记录在 socket(2)
手册页中。Linux 中记录的其他域包括:
AF_IPX
-Novell IPX 协议(可能仅用于 SuSe)。
AF_NETLINK
-内核/用户接口设备,允许用户访问内核模块。注意:在 Solaris OS 和 Linux 中还存在一些其他方法用于进行这项工作。
AF_X25
-X25 协议。在 Solaris OS 中,此域包含在 Solstice X.25 产品中。
AF_AX25
-业余无线电 AX.25 协议。
AF_ATMPVC
-基于 ATM 的永久虚拟电路 (Permanent Virtual Circuits over ATM)。
AF_APPLETALK
-请参见 Linux 中的 man ddp
。它在 Solaris OS 中也存在,但未记录。
AF_PACKET
-请参见 Linux 中的 man packet.7
。原始包接口。在 Solaris OS 中,请打开 NIC 设备并使用 getmsg(2)/putmsg(2)
来通过 DLPI 接收/发送原始包。(有关 DLPI 的详细信息,请参见)。
bind()
Linux 手册页 (man bind.2
) 包含一些有关不同地址族(AF_INET
和 AF_UNIX
除外)的信息。Solaris 手册页为 man bind.3socket
。
listen()
在 Linux 和 Solaris OS 中,backlog
参数(listen()
的第二个参数)指正等待被接受的已建立连接的队列长度。Linux 手册页中是这么说的,而 Solaris 手册页中仅是指“待处理连接的队列”。
accept()
Linux 支持三种基于连接的套接字类型:SOCK_STREAM
、SOCK_SEQPACKET
和 SOCK_RDM
,而 Solaris OS 只记录了 SOCK_STREAM
。Linux 实现不继承某些套接字标志。这可能与其他实现不同。
connect()
Linux 手册页 (man connect.2
) 记录了 SOCK_SEQPACKET
,而 Solaris OS 中不记录。Linux 通过连接到 struct sockaddr
中 sa_family
设置为 AF_UNSPEC
的某个地址来中断无连接套接字和 connect()
之间的关联。此行为不会记录在 Solaris OS 中。
send()/recv()
如在其他 socket
库函数中的情况那样,它们在不同系统中的行为几乎完全相同。Linux 在手册页中包含一些其他 flags
参数文档。
shutdown()
在 Solaris OS 和 Linux 之间没有显著的差异。
查看一个其中存在着某些差异的应用程序可能会很有用。 程序使用包捕获库 () 在用户级读取以太网包。用于读取原始以太网的代码在 Solaris OS 和 Linux 之间完全不同。(也可使用 libpcap 来检查与其他系统(例如,FreeBSD、HP-UX 和 AIX)间的差异。)libpcap 的可用代码位于 pcap-linux.c
和 pcap-dlpi.c
中。DLPI 代码用于 Solaris、HP-UX、AIX 和其他操作系统。Linux 提供了一种用于通过标准 socket
调用读取原始套接字包的机制。Solaris OS 使用 getmsg(2)
和 putmsg(2)
调用来接收和发送 DLPI 包。
以下代码演示了一种在 Solaris OS 中对网络接口执行用户级包捕获的方法。在这段代码之后,列出了在 Linux 中采用的类似代码。这段代码提取自 libpcap 库(此处进行了大量删减)。
#include#include #include #include #include #include #include #include #include int main(int argc, char *argv[]) { register char *cp; int fd; dl_info_ack_t *infop; union DL_primitives dlp; dl_info_req_t inforeq; dl_bind_req_t bindreq; dl_attach_req_t attachreq; dl_promiscon_req_t promisconreq; struct strbuf ctl, data; int flags; char buffer[8192]; dl_error_ack_t *edlp; fd = open(argv[1], O_RDWR); /* for instance, /dev/elxl0 */ /* attach to a specific interface */ attachreq.dl_primitive = DL_ATTACH_REQ; attachreq.dl_ppa = 0; /* assume we want /dev/xxx0 */ ctl.maxlen = 0; ctl.len = sizeof(attachreq); ctl.buf = (char *)&attachreq; flags = 0; /* send attach req */ putmsg(fd, &ctl, (struct strbuf *)NULL, flags); ctl.maxlen = sizeof(dlp); ctl.len = 0; ctl.buf = (char *)&dlp; /* get ok ack, may contain error */ getmsg(fd, &ctl, (struct strbuf*)NULL, &flags); memset((char *)&bindreq, 0, sizeof(bindreq)); /* the following bind might not need to be done */ bindreq.dl_primitive = DL_BIND_REQ; bindreq.dl_sap = 0; bindreq.dl_max_conind = 1; bindreq.dl_service_mode = DL_CLDLS; bindreq.dl_conn_mgmt = 0; bindreq.dl_xidtest_flg = 0; ctl.maxlen = 0; ctl.len = sizeof(bindreq); ctl.buf = (char *)&bindreq; flags = 0; /* send bind req */ putmsg(fd, &ctl, (struct strbuf *)NULL, flags); ctl.maxlen = sizeof(dlp); ctl.len = 0; ctl.buf = (char *)&dlp; /* get bind ack */ getmsg(fd, &ctl, (struct strbuf*)NULL, &flags); promisconreq.dl_primitive = DL_PROMISCON_REQ; promisconreq.dl_level = DL_PROMISC_PHYS; ctl.maxlen = 0; ctl.len = sizeof(promisconreq); ctl.buf = (char *)&promisconreq; flags = 0; /* send promiscuous on req */ putmsg(fd, &ctl, (struct strbuf *)NULL, flags); ctl.maxlen = sizeof(dlp); ctl.len = 0; ctl.buf = (char *)&dlp; /* get get ok ack */ getmsg(fd, &ctl, (struct strbuf*)NULL, &flags); promisconreq.dl_primitive = DL_PROMISCON_REQ; promisconreq.dl_level = DL_PROMISC_SAP; ctl.maxlen = 0; ctl.len = sizeof(promisconreq); ctl.buf = (char *)&promisconreq; flags = 0; /* send promiscuous on req */ putmsg(fd, &ctl, (struct strbuf *)NULL, flags); ctl.maxlen = sizeof(dlp); ctl.len = 0; ctl.buf = (char *)&dlp; /* get get ok ack */ getmsg(fd, &ctl, (struct strbuf*)NULL, &flags); /* read and echo to stdout whatever comes to us */ while (1) { data.buf = buffer; data.maxlen = sizeof(buffer); data.len = 0; ctl.buf = (char *) &dlp; ctl.maxlen = sizeof(dlp); ctl.len = 0; flags = 0; getmsg(fd, &ctl, &data, &flags); write(1, "\nCTL:\n", 6); write(1, ctl.buf, ctl.len); write(1, "\nDAT:\n", 6); write(1, data.buf, data.len); } }
The Solaris code forms DLPI requests and gets DLPI responses to tell the interface that the application wants a copy of all packets arriving at the interface.
The code in Linux is much simpler, as a socket(2)
call allows one to specify raw packets. Linux does not use DLPI or STREAMS.
#include |
A process on both the Solaris OS and Linux is a running instance
of a program. In both the Solaris OS and in Linux (2.6), a process is
a container for an address space and one or more threads.
Every process in the system has a unique process ID (PID), which
remains unique for some time after the process dies.
Processes are created using fork(2)
and its variants.
On Linux, processes (and threads) can also be created using clone(2)
,
but pthread_create(3)
is more portable.
On the Solaris OS, the undocumented lwp_create()
system call is somewhat analogous to clone(2)
.
vfork()
performs similarly on both systems. The Solaris OS has fork1()
and forkall()
. In the case of fork1()
, this causes the child process to only have the thread that executed the fork()
call; in the case of forkall()
, all the threads that were in the parent are replicated in the child. The default fork is fork1()
. forkall()
must be explicitly used.
forkall()
does not exist in Linux, (i.e., Linux only supports fork1()
semantics).
The ps -elfL
command can be used on both the Solaris OS and Linux to see the threads
in a process. Both systems report the number of LWPs and the
lwpid
for each thread in the process.
Note that an lwpid
is unique across processes in Linux. In the Solaris OS, the lwpid
is unique within the process.
In Linux, the process ID of a multithreaded process is actually a thread group ID.
The thread group ID is equivalent to the process ID of the main thread.
Sending a signal (via kill(1)/kill(2)
) to any lwpid
is equivalent to sending the signal to the process. In the Solaris OS, you send the signal to the pid
. In both cases, if the default action is taken, the process typically exits and all threads are terminated.
See the man page for ps(1)
for more details.
Both Linux and the Solaris OS support the notion of binding a
process or thread to a processor. Linux allows binding to a set of
processors for non-exclusive use of those processors. The Solaris OS
allows binding to a set of processors for exclusive use, (that is, CPU fencing), but does not allow binding to a group for non-exclusive use (except via Solaris Zones?).
Linux does not have a mechanism for CPU fencing, though implementations can
be found on the web (see, for example, the on the bullopensource.org site).
The Linux system calls that are processor affinity based are sched_setaffinity(2)
and sched_getaffinity(2)
.
The Solaris OS has the following:
processor_bind(2)
to bind/unbind LWPs or processes to a processor
pset_create(2)
to set up a processor set
pbind(1)
and psrset(1)
, which are command-line interfaces
For completeness, output of the ps(1)
command, first on Linux, then
on the Solaris OS, is shown in the section on Threads.
On Linux and the Solaris OS, all forms of the exec
system call
result in calling execve(2)
. The Solaris OS documents all six flavors
of exec(2)
on the same manual page. The Linux man page exec(3)
documents execv
, execl
, execle
, execlp
, and execvp
. A separate page covers execve(2)
.
The /proc
file system exists in slightly different variations on Linux
and the Solaris OS.
On both systems, /proc
is a directory containing files
whose names are the process IDs of the current active processes on the
system. Each PID-named file is in turn a directory. /proc
on Linux has various other directories besides processes.
Most of these deal with processors, devices, and statistics on the system.
On Linux, one looks in /proc
to find information about
processes, processors, devices, machine architecture, and so on. On the
Solaris OS, the same kind of information is typically available by using
a command.
For instance, prtconf(1)
can be used to learn about machine configuration on the Solaris OS.
On Linux, this is done largely by looking at files in /proc
.
The virtual address space used by processes can be examined using pmap(1)
on the Solaris OS, and by catting the /proc/pid/maps
file on Linux, as shown below.
See pmap(1)
on the Solaris OS and proc(5)
on Linux
for more details.
<-- on solaris, address space of this instance of bash --> bash-3.00$ pmap -x $$ 1043: /usr/bin/bash -i Address Kbytes RSS Anon Locked Mode Mapped File 08045000 12 12 4 - rw--- [ stack ] 08050000 528 468 - - r-x-- bash 080E3000 76 72 8 - rwx-- bash 080F6000 124 108 40 - rwx-- [ heap ] FED8E000 4 4 - - rwxs- [ anon ] FEDA0000 4 4 - - rwx-- [ anon ] FEDB0000 760 660 - - r-x-- libc.so.1 FEE7E000 24 24 8 - rw--- libc.so.1 FEE84000 8 8 - - rw--- libc.so.1 FEE90000 24 8 4 - rwx-- [ anon ] FEEA0000 524 324 - - r-x-- libnsl.so.1 FEF33000 20 20 4 - rw--- libnsl.so.1 FEF38000 32 - - - rw--- libnsl.so.1 FEF50000 44 40 - - r-x-- libsocket.so.1 FEF6B000 4 4 - - rw--- libsocket.so.1 FEF70000 4 4 4 - rwx-- [ anon ] FEF80000 144 132 - - r-x-- libcurses.so.1 FEFB4000 28 24 - - rw--- libcurses.so.1 FEFBB000 8 - - - rw--- libcurses.so.1 FEFC0000 4 4 - - r-x-- libdl.so.1 FEFC7000 140 140 - - r-x-- ld.so.1 FEFFA000 4 4 4 - rwx-- ld.so.1 FEFFB000 8 8 4 - rwx-- ld.so.1 -------- ------- ------- ------- ------- total Kb 2528 2072 80 - bash-3.00$ |
pldd(1)
.user@linuxhost:~$ cat /proc/$$/maps <-- get mapping for current shell(bash)
08048000-080e9000 r-xp 00000000 03:01 1954568 /bin/bash
080e9000-080ef000 rw-p 000a0000 03:01 1954568 /bin/bash
080ef000-081b4000 rw-p 080ef000 00:00 0 [heap]
b7acb000-b7ae6000 r-xp 00000000 03:06 716774 /usr/lib/gconv/GBK.so
b7ae6000-b7ae8000 rw-p 0001a000 03:06 716774 /usr/lib/gconv/GBK.so
b7ae8000-b7af1000 r-xp 00000000 03:01 1645899 /lib/tls/i686/cmov/libnss_files-2.3.6.so
b7af1000-b7af3000 rw-p 00008000 03:01 1645899 /lib/tls/i686/cmov/libnss_files-2.3.6.so
b7af3000-b7afb000 r-xp 00000000 03:01 1645901 /lib/tls/i686/cmov/libnss_nis-2.3.6.so
b7afb000-b7afd000 rw-p 00007000 03:01 1645901 /lib/tls/i686/cmov/libnss_nis-2.3.6.so
b7afd000-b7b0f000 r-xp 00000000 03:01 1645896 /lib/tls/i686/cmov/libnsl-2.3.6.so
b7b0f000-b7b11000 rw-p 00011000 03:01 1645896 /lib/tls/i686/cmov/libnsl-2.3.6.so
b7b11000-b7b13000 rw-p b7b11000 00:00 0
b7b13000-b7b1a000 r-xp 00000000 03:01 1645897 /lib/tls/i686/cmov/libnss_compat-2.3.6.so
b7b1a000-b7b1c000 rw-p 00006000 03:01 1645897 /lib/tls/i686/cmov/libnss_compat-2.3.6.so
b7b1c000-b7c21000 r--p 002d4000 03:06 719486 /usr/lib/locale/locale-archive
b7c21000-b7e21000 r--p 00000000 03:06 719486 /usr/lib/locale/locale-archive
b7e21000-b7e22000 rw-p b7e21000 00:00 0
b7e22000-b7f49000 r-xp 00000000 03:01 1645890 /lib/tls/i686/cmov/libc-2.3.6.so
b7f49000-b7f4e000 r--p 00127000 03:01 1645890 /lib/tls/i686/cmov/libc-2.3.6.so
b7f4e000-b7f50000 rw-p 0012c000 03:01 1645890 /lib/tls/i686/cmov/libc-2.3.6.so
b7f50000-b7f54000 rw-p b7f50000 00:00 0
b7f54000-b7f56000 r-xp 00000000 03:01 1645893 /lib/tls/i686/cmov/libdl-2.3.6.so
b7f56000-b7f58000 rw-p 00001000 03:01 1645893 /lib/tls/i686/cmov/libdl-2.3.6.so
b7f58000-b7f90000 r-xp 00000000 03:01 1628907 /lib/libncurses.so.5.5
b7f90000-b7f98000 rw-p 00038000 03:01 1628907 /lib/libncurses.so.5.5
b7f98000-b7f99000 rw-p b7f98000 00:00 0
b7fa2000-b7fa8000 r--s 00000000 03:06 716680 /usr/lib/gconv/gconv-modules.cache
b7fa8000-b7faa000 rw-p b7fa8000 00:00 0
b7faa000-b7fab000 r-xp b7faa000 00:00 0 [vdso]
b7fab000-b7fc0000 r-xp 00000000 03:01 1628802 /lib/ld-2.3.6.so
b7fc0000-b7fc2000 rw-p 00014000 03:01 1628802 /lib/ld-2.3.6.so
bfca4000-bfcb9000 rw-p bfca4000 00:00 0 [stack]
user@linuxhost:~$
Linux and the Solaris OS support POSIX threads, Linux via , and the Solaris OS as part of the standard C library. See , specifically, , for details of threads on the Solaris OS. Also quite good is the white paper .
In addition to POSIX threads, the Solaris OS supports "Solaris threads".
The threads(5)
man page describes the similarities and differences between the POSIX thread library and the Solaris thread library.
The implementations are interoperable and can be used with care
within the same application. The following is straight from the man page.
Most of the functions in the libpthread and libthread libraries have a counterpart in the other corresponding library. POSIX function names, with the exception of the semaphore names, have a "pthread" prefix. Names for similar POSIX and Solaris functions have similar endings. Typically, similar POSIX and Solaris functions have the same number and use of arguments.
fork(2)
calls.
The following is a very simple MT program. Very few differences are found in the ways in which multithreaded applications work between the two OSes. Of course, the underlying implementations have several differences.
#include |
Use the following to compile and run the program on the Solaris platform:
bash-3.00$ cc simplepthread.c -o simplepthread bash-3.00$ ./simplepthread main thread id = 1 new thread id = 2 bash-3.00$Using
gcc
on the Solaris platform gives the same results.
On Linux it appears thus:max@linux:~/source> cc simplepthread.c /tmp/cc8u7kZs.o(.text+0x1e): In function `main': simplepthread.c: undefined reference to `pthread_create' /tmp/cc8u7kZs.o(.text+0x4a):simplepthread.c: undefined reference to `pthread_join' collect2: ld returned 1 exit status max@linux:~/source> cc simplepthread.c -lpthread -o simplepthread max@linux:~/source> ./simplepthread main thread id = 4015c6c0 new thread id = 4035cbb0 max@linux:~/source>
On Linux, the POSIX thread library needs to be explicitly linked. Note that
Solaris 9 and earlier versions also require this. In the Solaris 10 OS, POSIX threads are in the standard C library (libc.so
).
Note
also that the Solaris OS assigns thread IDs using a monotonically
increasing integer starting at 1. Linux uses the user virtual address of
the pthread
structure (structure used internally by the thread library).
Visibility to threads is provided on both systems by the ps(1)
command,
and via the /proc
file system.
See Figure 2 for the output of the ps(1)
command on the
Solaris platform and Figure 3 for the output on Linux. You'll see that,
given the same options, the output is very similar between the machines.
user@solaris:~$ ps -elfcL
F S UID PID PPID LWP NLWP CLS PRI ADDR SZ WCHAN STIME TTY LTIME CMD
1 T root 0 0 1 1 SYS 96 ? 0 07:34:50 ? 0:49 sched
0 S root 1 0 1 1 TS 59 ? 619 ? 07:35:07 ? 0:06 /sbin/init
1 S root 2 0 1 1 SYS 98 ? 0 ? 07:35:07 ? 0:00 pageout
1 S root 3 0 1 1 SYS 60 ? 0 ? 07:35:07 ? 0:53 fsflush
0 S root 180 1 1 4 TS 59 ? 836 ? 07:35:13 ? 0:00 /usr/lib/picl/picld
0 S root 180 1 2 4 TS 59 ? 836 ? 07:35:13 ? 0:00 /usr/lib/picl/picld
0 S root 180 1 3 4 TS 59 ? 836 ? 07:35:16 ? 0:00 /usr/lib/picl/picld
0 S root 180 1 4 4 TS 59 ? 836 ? 07:35:16 ? 0:00 /usr/lib/picl/picld
0 S root 7 1 1 15 TS 59 ? 3341 ? 07:35:07 ? 0:00 /lib/svc/bin/svc.startd
0 S root 7 1 2 15 TS 59 ? 3341 ? 07:35:07 ? 0:00 /lib/svc/bin/svc.startd
0 S root 7 1 3 15 TS 59 ? 3341 ? 07:35:08 ? 0:00 /lib/svc/bin/svc.startd
0 S root 7 1 4 15 TS 59 ? 3341 ? 07:35:08 ? 0:00 /lib/svc/bin/svc.startd
0 S root 7 1 5 15 TS 59 ? 3341 ? 07:35:08 ? 0:00 /lib/svc/bin/svc.startd
0 S root 7 1 6 15 TS 59 ? 3341 ? 07:35:08 ? 0:00 /lib/svc/bin/svc.startd
0 S root 7 1 7 15 TS 59 ? 3341 ? 07:35:08 ? 0:00 /lib/svc/bin/svc.startd
0 S root 7 1 8 15 TS 59 ? 3341 ? 07:35:08 ? 0:00 /lib/svc/bin/svc.startd
0 S root 7 1 9 15 TS 59 ? 3341 ? 07:35:08 ? 0:00 /lib/svc/bin/svc.startd
0 S root 7 1 59 15 TS 59 ? 3341 ? 07:35:08 ? 0:00 /lib/svc/bin/svc.startd
0 S root 7 1 311 15 TS 59 ? 3341 ? 07:36:04 ? 0:00 /lib/svc/bin/svc.startd
0 S root 7 1 263 15 TS 59 ? 3341 ? 07:35:19 ? 0:00 /lib/svc/bin/svc.startd
0 S root 7 1 98 15 TS 59 ? 3341 ? 07:35:08 ? 0:00 /lib/svc/bin/svc.startd
0 S root 7 1 260 15 TS 59 ? 3341 ? 07:35:18 ? 0:00 /lib/svc/bin/svc.startd
0 S root 7 1 294 15 TS 59 ? 3341 ? 07:35:22 ? 0:00 /lib/svc/bin/svc.startd
0 S root 9 1 1 16 TS 59 ? 2342 ? 07:35:07 ? 0:00 /lib/svc/bin/svc.configd
0 S root 9 1 2 16 TS 59 ? 2342 ? 07:35:08 ? 0:01 /lib/svc/bin/svc.configd
0 S root 9 1 3 16 TS 59 ? 2342 ? 07:35:08 ? 0:00 /lib/svc/bin/svc.configd
0 S root 9 1 4 16 TS 59 ? 2342 ? 07:35:08 ? 0:00 /lib/svc/bin/svc.configd
0 S root 9 1 5 16 TS 59 ? 2342 ? 07:35:08 ? 0:00 /lib/svc/bin/svc.configd
0 S root 9 1 6 16 TS 59 ? 2342 ? 07:35:08 ? 0:00 /lib/svc/bin/svc.configd
0 S root 9 1 7 16 TS 59 ? 2342 ? 07:35:08 ? 0:00 /lib/svc/bin/svc.configd
0 S root 9 1 8 16 TS 59 ? 2342 ? 07:35:08 ? 0:00 /lib/svc/bin/svc.configd
0 S root 9 1 9 16 TS 59 ? 2342 ? 07:35:08 ? 0:00 /lib/svc/bin/svc.configd
0 S root 9 1 10 16 TS 59 ? 2342 ? 07:35:08 ? 0:00 /lib/svc/bin/svc.configd
0 S root 9 1 11 16 TS 59 ? 2342 ? 07:35:08 ? 0:01 /lib/svc/bin/svc.configd
0 S root 9 1 12 16 TS 59 ? 2342 ? 07:35:08 ? 0:00 /lib/svc/bin/svc.configd
0 S root 9 1 13 16 TS 59 ? 2342 ? 07:35:11 ? 0:00 /lib/svc/bin/svc.configd
0 S root 9 1 14 16 TS 59 ? 2342 ? 07:35:11 ? 0:00 /lib/svc/bin/svc.configd
0 S root 9 1 15 16 TS 59 ? 2342 ? 07:35:11 ? 0:00 /lib/svc/bin/svc.configd
0 S root 9 1 16 16 TS 59 ? 2342 ? 07:35:11 ? 0:00 /lib/svc/bin/svc.configd
0 S daemon 161 1 1 3 TS 59 ? 1079 ? 07:35:12 ? 0:00 /usr/lib/crypto/kcfd
0 S daemon 161 1 2 3 TS 59 ? 1079 ? 07:35:12 ? 0:00 /usr/lib/crypto/kcfd
0 S daemon 161 1 3 3 TS 59 ? 1079 ? 07:35:24 ? 0:00 /usr/lib/crypto/kcfd
0 S root 297 1 1 1 TS 59 ? 709 ? 07:35:16 ? 0:00 /usr/sbin/cron
0 S root 139 1 1 15 TS 59 ? 1331 ? 07:35:12 ? 0:00 /usr/lib/sysevent/syseventd
<-- output omitted (on bash) -->
user@solaris:~$
user@linuxhost:~$ ps -elfcL
F S UID PID PPID LWP NLWP CLS PRI ADDR SZ WCHAN STIME TTY TIME CMD
4 S root 1 0 1 1 TS 24 - 486 - Nov07 ? 00:00:01 init [2]
1 S root 2 1 2 1 FF 139 - 0 migrat Nov07 ? 00:00:00 [migration/0]
1 S root 3 1 3 1 TS 0 - 0 ksofti Nov07 ? 00:00:00 [ksoftirqd/0]
1 S root 4 1 4 1 FF 139 - 0 migrat Nov07 ? 00:00:00 [migration/1]
1 S root 5 1 5 1 TS 0 - 0 ksofti Nov07 ? 00:00:00 [ksoftirqd/1]
1 S root 6 1 6 1 TS 29 - 0 worker Nov07 ? 00:00:00 [events/0]
1 S root 7 1 7 1 TS 29 - 0 worker Nov07 ? 00:00:00 [events/1]
1 S root 8 1 8 1 TS 29 - 0 worker Nov07 ? 00:00:00 [khelper]
1 S root 9 1 9 1 TS 29 - 0 worker Nov07 ? 00:00:00 [kthread]
1 S root 13 9 13 1 TS 29 - 0 worker Nov07 ? 00:00:00 [kblockd/0]
1 S root 14 9 14 1 TS 29 - 0 worker Nov07 ? 00:00:00 [kblockd/1]
1 S root 15 9 15 1 TS 24 - 0 worker Nov07 ? 00:00:00 [kacpid]
1 S root 108 9 108 1 TS 28 - 0 serio_ Nov07 ? 00:00:00 [kseriod]
1 S root 150 9 150 1 TS 19 - 0 pdflus Nov07 ? 00:00:00 [pdflush]
1 S root 151 9 151 1 TS 24 - 0 pdflus Nov07 ? 00:00:00 [pdflush]
1 S root 152 9 152 1 TS 29 - 0 kswapd Nov07 ? 00:00:02 [kswapd0]
1 S root 153 9 153 1 TS 23 - 0 worker Nov07 ? 00:00:00 [aio/0]
1 S root 154 9 154 1 TS 22 - 0 worker Nov07 ? 00:00:00 [aio/1]
1 S root 304 1 304 1 TS 24 - 0 - Nov07 ? 00:00:00 [kirqd]
1 S root 630 9 630 1 TS 29 - 0 hub_th Nov07 ? 00:00:00 [khubd]
1 S root 772 9 772 1 TS 26 - 0 worker Nov07 ? 00:00:00 [ata/0]
1 S root 773 9 773 1 TS 25 - 0 worker Nov07 ? 00:00:00 [ata/1]
1 S root 774 9 774 1 TS 26 - 0 worker Nov07 ? 00:00:00 [ata_aux]
1 S root 779 9 779 1 TS 26 - 0 scsi_e Nov07 ? 00:00:00 [scsi_eh_0]
1 S root 781 9 781 1 TS 28 - 0 scsi_e Nov07 ? 00:00:00 [scsi_eh_1]
1 S root 1071 9 1071 1 TS 29 - 0 kjourn Nov07 ? 00:00:00 [kjournald]
5 S root 1259 1 1259 1 TS 24 - 690 429496 Nov07 ? 00:00:00 udevd --daemon
1 S root 1634 9 1634 1 TS 19 - 0 worker Nov07 ? 00:00:00 [kpsmoused]
1 S root 1679 9 1679 1 TS 22 - 0 worker Nov07 ? 00:00:00 [hda_codec]
1 S root 1849 9 1849 1 TS 26 - 0 worker Nov07 ? 00:00:00 [kmirrord]
1 S root 1896 9 1896 1 TS 29 - 0 kjourn Nov07 ? 00:00:00 [kjournald]
1 S root 1898 9 1898 1 TS 29 - 0 kjourn Nov07 ? 00:00:00 [kjournald]
1 S root 1900 9 1900 1 TS 29 - 0 kjourn Nov07 ? 00:00:03 [kjournald]
5 S daemon 2271 1 2271 1 TS 23 - 422 - Nov07 ? 00:00:00 /sbin/portmap
1 S root 2429 1 2429 1 TS 21 - 406 429496 Nov07 ? 00:00:00 /sbin/syslogd
5 S root 2435 1 2435 1 TS 24 - 394 syslog Nov07 ? 00:00:00 /sbin/klogd -x
1 S root 2458 1 2458 1 TS 18 - 1221 375710 Nov07 ? 00:00:00 /usr/sbin/hpiod
1 S root 2531 1 2531 1 TS 24 - 394 - Nov07 ? 00:00:00 /usr/sbin/acpid -c
5 S root 2553 1 2553 1 TS 24 - 1173 - Nov07 ? 00:00:00 /usr/sbin/cupsd
5 S 103 2561 1 2561 1 TS 24 - 629 - Nov07 ? 00:00:00 /usr/bin/dbus-daemo5 S 105 2569 1 2569 1 TS 21 - 1430 - Nov07 ? 00:00:01 /usr/sbin/hald
0 S root 2570 2569 2570 1 TS 15 - 724 - Nov07 ? 00:00:00 hald-runner
4 S 105 2576 2570 2576 1 TS 15 - 505 - Nov07 ? 00:00:00 hald-addon-acpi: li0 S root 2586 2570 2586 1 TS 21 - 453 - Nov07 ? 00:00:04 hald-addon-storage:1 S root 2600 1 2600 1 TS 24 - 466 - Nov07 ? 00:00:00 /usr/sbin/dhcdbd --5 S root 2607 1 2607 1 TS 24 - 996 - Nov07 ? 00:00:00 /usr/sbin/NetworkMa5 S avahi 2619 1 2619 1 TS 24 - 638 - Nov07 ? 00:00:00 avahi-daemon: runni1 S avahi 2620 2619 2620 1 TS 14 - 638 - Nov07 ? 00:00:00 avahi-daemon: chroo1 S root 2627 1 2627 1 TS 16 - 727 - Nov07 ? 00:00:00 /usr/sbin/NetworkMa5 S 100 2674 1 2674 1 TS 21 - 1329 429496 Nov07 ? 00:00:00 /usr/sbin/exim4 -bd5 S root 2692 1 2692 1 TS 24 - 437 429496 Nov07 ? 00:00:00 /usr/sbin/inetd
5 S root 2702 1 2702 1 TS 24 - 1231 429496 Nov07 ? 00:00:00 /usr/sbin/sshd
4 S root 2706 1 2706 1 TS 24 - 878 375734 Nov07 ? 00:00:00 /usr/sbin/vsftpd
5 S root 2745 1 2745 1 TS 17 - 3707 - Nov07 ? 00:00:06 /usr/sbin/gdm
5 S root 2751 2745 2751 1 TS 21 - 3506 pipe_w Nov07 ? 00:00:00 /usr/sbin/gdm
4 S root 2752 2751 2752 1 TS 22 - 6752 429496 Nov07 tty7 00:00:00 /usr/bin/X :0 -dpi
5 S statd 2759 1 2759 1 TS 21 - 440 429496 Nov07 ? 00:00:00 /sbin/rpc.statd
1 S daemon 2800 1 2800 1 TS 21 - 458 - Nov07 ? 00:00:00 /usr/sbin/atd
1 S root 2807 1 2807 1 TS 21 - 549 - Nov07 ? 00:00:00 /usr/sbin/cron
<-- output omitted (on bash) -->
user@linuxhost:~$
The command shows state, user, PID, parent PID, LWP ID, number of LWPs
(for user processes, this is the number of threads), scheduling class,
scheduling priority, user virtual size, wait channel,
start time, tty, time spent running, and command.
Linux does not report ADDR
, and the Solaris OS shows the (kernel) virtual address of the proc_t
data structure, which the kernel uses to maintain the process.
Linux shows WCHAN
as a symbol, while the Solaris OS shows it as an address.
In the Solaris OS, the WCHAN
column is the address of a synchronization variable
on which the thread is blocked. On Linux, WCHAN
is the routine in which the thread is sleeping.
To get the equivalent information in the Solaris OS, use ::threadlist -v
inside of mdb -k
.
Note that on a machine running a 64-bit kernel (that is, SPARC or AMD64 architecture based), the
ADDR
and WCHAN
fields will display a question mark (?
). To see the values for these two fields, use ps -e -o addr,wchan,comm
.
More likely, you are interested in what the application threads are doing.
For this, use pstack(1)
on the process ID of interest.
There is a pstack
on Linux, but it must be downloaded.
Search for it on .
Note that it only gives the stack backtrace of one thread (the thread ID that is passed to it as an argument).
If you want a backtrace of all threads within a process, you need to pass the thread IDs as separate arguments.
<-- get user-level stack(s) of a process on Solaris --> bash-3.00$ pstack `pgrep mozilla-bin` 21528: /usr/sfw/bin/../lib/mozilla/mozilla-bin -UILocale en-US ----------------- lwp# 1 / thread# 1 -------------------- fef68967 pollsys (896dac8, 9, 0, 0) fef2b2aa poll (896dac8, 9, ffffffff) + 52 fe793242 g_main_context_iterate () + 39d ----------------- lwp# 2 / thread# 2 -------------------- fef68967 pollsys (fbf5bd04, 1, 0, 0) fef2b2aa poll (fbf5bd04, 1, ffffffff) + 52 fede047d _pr_poll_with_poll (816fa0c, 1, ffffffff, fbf5bf64, fc0558aa, 816fa0c) + 2d5 fede05f1 PR_Poll (816fa0c, 1, ffffffff) + 11 fc0558aa __1cYnsSocketTransportServiceEPoll6M_i_ (816f6b8) + 58 fc055f7d __1cYnsSocketTransportServiceDRun6M_I_ (816f6b8) + 18f fc3d1262 __1cInsThreadEMain6Fpv_v_ (816eb60) + 32 fede1693 _pt_root (816fcc0) + 9e fef67b30 _thr_setup (feec2400) + 51 fef67f40 _lwp_start (feec2400, 0, 0, 0, 0, 0) ----------------- lwp# 4 / thread# 4 -------------------- fef67f7b lwp_park (0, fa87deb8, 0) fef620bb cond_wait_queue (825cfec, 816b8d0, fa87deb8, 0) + 3e fef62462 cond_wait_common (825cfec, 816b8d0, fa87deb8) + 1e9 fef62691 _cond_timedwait (825cfec, 816b8d0, fa87df38) + 4a fef62722 cond_timedwait (825cfec, 816b8d0, fa87df38) + 27 fef62761 pthread_cond_timedwait (825cfec, 816b8d0, fa87df38) + 21 feddc598 pt_TimedWait (825cfec, 816b8d0, f1c) + b8 feddc767 PR_WaitCondVar (825cfe8, f1c) + 64 fc3d417e __1cLTimerThreadDRun6M_I_ (81e5108) + 16e fc3d1262 __1cInsThreadEMain6Fpv_v_ (820d690) + 32 fede1693 _pt_root (820e6b0) + 9e fef67b30 _thr_setup (fb520400) + 51 fef67f40 _lwp_start (fb520400, 0, 0, 0, 0, 0) bash-3.00$ |
max@linux:~> cd /proc/`pgrep mozilla`/task max@linux:/proc/3991/task> pstack * 3991: /opt/mozilla/lib/mozilla-bin (No symbols found) 0xffffe410: ???? (8803488, 8, ffffffff, 8803488, 9, 400fbea0) + 40 0x404b0a6d: ???? (8129258, 4035236c, 57f, 4011e4e6, 4048de14, 403513c4) + 20 0x404b0d07: ???? (814b898, 814b898, 0, 0, 415a8f64, 814b898) + 30 0x401dc11f: ???? (8106350, bfffee80, bfffede8, 807673e, 8084cf4, 0) 0x415c4006: ???? (8106350, 0) 0x414fbae4: ???? (8105ee8, 0, 8079c2c, bfffee90, 80a67b8, 40ad841c) + 1f0 0x08059b7c: ???? (80e7f08, bffff058, 40017068, 14, 4081ccf8, 1) + 90 0x08055a47: ???? (1, bffff134, bffff13c, 4081ccf8, 406eebd0, 400168c0) + 40 0x405f2500: ???? (8055840, 1, bffff134, 80557b0, 8055740, 4000d330) + 40000ed8 4001: /opt/mozilla/lib/mozilla-bin (No symbols found) 0xffffe410: ???? (413eb7f0, 1, ffffffff, 18, 413eb7f8, 0) + 230 0x400c7439: ???? (818911c, 1, ffffffff, 40c5a0a8, ffffffff, 8188dec) 0x40bc8a52: ???? (8188dc8, 8188df4, 1, 8188dec, 8188f7c, 1) + 10 0x40bc8bcb: ???? (8188dc8, 413ebbb0, 40102ce0, 400d5238, 8189478, 0) 0x40a8da6b: ???? (81893f8, 8189478, 4000ca40, 40102be8, 0, 0) 0x400cb7a6: ???? (8189478, 413ebac4, 0, 0, 0, 0) + 54 0x400fa9dd: ???? (413ebbb0, 0, 0, 0, 0, 0) + bec144d4 4004: /opt/mozilla/lib/mozilla-bin (No symbols found) 0xffffe410: ???? (40656756, 400d5238, 81ed160, 81ed2d0, 41ffba08, 400c5721) + 170fd55 crawl: Input/output error Error tracing through process 4004 0x1afcdbf8: ????max@linux:/proc/3991/task>
Solaris threads are given a default user stack size of 1MB. For Linux, the default stack size is 2MB (SuSe 9.1).
Both OSes support POSIX synchronization mechanisms, i.e., mutexes, condition variables, reader/writer locks, semaphores, and barriers. The underlying mechanisms rely on mutexes. In Solaris, user-level mutexes are implemented using "adaptive" spin locks. On Linux, the mechanism is the "futex", or fast user level mutex. Both mechanisms avoid going into the kernel in the non-contention case, and should give comparable performance and behavior.
The Solaris user-level adaptive spin mutexes are described in . Linux futexes are described in .
The Solaris OS mechanisms lwp_park()
and lwp_unpark()
,
and Linux mechanisms futex_up()
and futex_down()
,
can be used by applications. However, I have not found any source code examples.
It is probably best to stick with the POSIX APIs.
If you want to compare relative speeds of the POSIX locking mechanisms (as well as
performance of various other library routines and system calls), I recommend
getting a copy of the libmicro micro benchmark and trying it out on both the Solaris OS and Linux. (You can
libmicro from the OpenSolaris site.)
Be aware that the upcoming Solaris 11 release (the latest build
available through OpenSolaris and Solaris Express, code named Nevada),
is a debug build, which will have an effect on any performance numbers
you are seeing.
Without describing differences in the kernels' handling of memory, we can say that at user level several different memory allocation (malloc) libraries exist, most of which are available (or can be built) for either OS. A comparison of some of the user-level memory allocators can be found in the Sun Developer Network article A Comparison of Memory Allocators in Multiprocessors. "A Memory Allocator" at contains a (dated) description of a memory allocator used on Linux. More comments can be found in the source code.
At application level, the Solaris OS and Linux both offer POSIX timer routines,
including timer_create()
, timer_delete()
, and
nanosleep()
. The Solaris OS has an additional timer, CLOCK_HIGHRES
, that attempts to
use an optimal hardware source, and may give close to nanosecond resolution.
A CLOCK_HIGH_RES
timer may give similar resolution
on Linux, but needs to be installed as a kernel patch
(see home page for the high resolution timers project at for details).
The following is example code that uses the CLOCK_HIGHRES
timer
to fire on user-specified intervals for a user-specified duration.
The interval is specified in nanoseconds, and the duration in seconds.
When the program completes, it prints the number of times the timer fired, and
the number of times the timer was "overrun".
The "overrun" value is a count of the number of timer expirations that
occurred between the time a timer fired (causing a signal to be generated), and
the time the signal is handled (see timer_getoverrun(3RT)
.
Running the program real-time with too short an interval may cause
the system to hard hang.
#include |
And here are some examples of running the compiled code.
<-- realtime library and best optimization --> bash-3.00$ cc timerex1.c -lrt -o timerex1 -O -fast bash-3.00$ ./timerex1 <-- only root can use high res timer timer_create failed: Not owner bash-3.00$ su Password: <-- default interval is .5 seconds, duration is 120 seconds --> # ./timerex1 timerentered = 240 <-- timer fired every .5 seconds timeroverrun = 0 # ./timerex1 1000000 10 <-- interval is 1 msec for 10 secs timerentered = 9912 timeroverrun = 88 # priocntl -e -c RT ./timerex1 1000000 10 <-- run it real time timerentered = 10000 <-- timer fired once each msec for 10 secs timeroverrun = 0 # ./timerex1 100000 10 <-- interval is 100 usecs for 10 seconds timerentered = 99615 <-- we missed a few timeroverrun = 386 # priocntl -e -c RT ./timerex1 100000 10 <-- try real time timerentered = 99871 <-- almost 1 every 100 microseconds timeroverrun = 129 # ./timerex1 10000 10 <-- interval is 10 microseconds timerentered = 485905 <-- here we miss over half timeroverrun = 514125 <-- (sig handler takes > 10 usecs?) <-- using RT 1 usec interval causes hang on my machine --> # priocntl -e -c RT ./timerex1 1000 10 |
Both the Solaris OS and Linux support System V IPC (shared memory, message queues, and semaphores).
Both systems also support pipes and the real-time shared memory operations (shm_open()
, shm_unlink()
,
and so on).
Both systems support the tmpfs file system (using memory and swap space for files).
The Solaris OS places /tmp
, /var/run
, and /etc/svc/volatile
in tmpfs. Linux uses /dev/shm
. Both systems allow other mount points to be added.
Here are the steps for using tmpfs on the Solaris OS; steps for Linux
are shown below. Note that "swap" on the Solaris OS uses memory as well
as disk (if needed). In other words, files created in /tmp
are stored in memory. If memory gets full, the pageout
daemon may write data from /tmp
to swap space on disk.
# mkdir /foo <-- create a tmpfs file system using swap on /foo # mount -F tmpfs swap /foo # df -h /foo Filesystem size used avail capacity Mounted on swap 652M 0K 652M 0% /foo # df -h /tmp Filesystem size used avail capacity Mounted on swap 652M 52K 652M 1% /tmp # |
And here are the analogous steps on Linux.
linux:/home/max # mkdir /foo <-- tmpfs also uses swap space and memory --> linux:/home/max # mount tmpfs /foo -t tmpfs linux:/home/max # df -h /foo Filesystem Size Used Avail Use% Mounted on tmpfs 248M 0 248M 0% /foo linux:/home/max # df -h /dev/shm Filesystem Size Used Avail Use% Mounted on tmpfs 248M 16K 248M 1% /dev/shm linux:/home/max # |
It might be interesting to run the libmicro benchmarks mentioned earlier in the article to get some idea of relative performance between the systems.
The Solaris OS and Linux treat signals similarly. Some signals exist in
the Solaris OS and not in Linux, and vice versa. Also, some of the same
signals use different signal numbers. Both OSes recommend using sigaction(2)
over signal()
to catch signals, and the use of sigwait()
to handle asynchronous signals in multithreaded applications.
The sigwait(3)
manual page on Linux has a BUGS
section.
The Linux signal handling differs from the POSIX standard.
POSIX states that an asynchronously delivered signal (a signal sent externally
to the process), is handled by any thread that does not have the signal currently blocked.
In Linux, asynchronous signals may be sent to specific threads (signals can be
sent to the thread ID via kill(1)
). The Solaris OS implements the POSIX standard for this.
There is no way to send a signal to a specific thread externally to the process. One
can send a signal via kill(1)
to the process, not to a specific thread
within the process.
Some of the differences are described in "Building Applications with the Linux Standard Base" at .
Note that this page may not be entirely accurate. For instance, the page says that Linux
sets SIGBUS
to SIGUNUSED
because
there is no "bus error" in Linux. However, the Linux man page for mmap(2)
documents receiving SIGBUS
when accessing a memory range that does not correspond to a valid location in the file that mmap
was used with.
(The Solaris OS does the same).
On both the Solaris OS and Linux, signals are handled when a non-held,
non-ignored signal is found pending for a thread returning from kernel
to user mode.
On both systems, SIGKILL
and SIGSTOP
take priority
over other signals. Otherwise, on Solaris signals are handled in
an undocumented order (lowest signal number first). On Linux, signals
are handled in the order they are delivered (again, excepting SIGKILL
and SIGSTOP
).
On the Solaris OS, to see the signal settings for a running process,
use psig
.
bash-3.00$ psig $$ <-- signal disp for current shell 954: /usr/bin/bash -i HUP caught termination_unwind_protect 0 HUP,INT, ILL,TRAP,ABRT,EMT,FPE,BUS,SEGV,SYS,PIPE,ALRM,TERM,USR1,USR2, VTALRM,XCPU,XFSZ,LOST INT caught sigint_sighandler 0 QUIT ignored ILL caught termination_unwind_protect 0 HUP,INT, ILL,TRAP,ABRT,EMT,FPE,BUS,SEGV,SYS,PIPE,ALRM,TERM,USR1,USR2, VTALRM,XCPU,XFSZ,LOST TRAP caught termination_unwind_protect 0 HUP,INT, ILL,TRAP,ABRT,EMT,FPE,BUS,SEGV,SYS,PIPE,ALRM,TERM,USR1,USR2, VTALRM,XCPU,XFSZ,LOST ABRT caught termination_unwind_protect 0 HUP,INT, ILL,TRAP,ABRT,EMT,FPE,BUS,SEGV,SYS,PIPE,ALRM,TERM,USR1,USR2, VTALRM,XCPU,XFSZ,LOST EMT caught termination_unwind_protect 0 HUP,INT, ILL,TRAP,ABRT,EMT,FPE,BUS,SEGV,SYS,PIPE,ALRM,TERM,USR1,USR2, VTALRM,XCPU,XFSZ,LOST FPE caught termination_unwind_protect 0 HUP,INT, ILL,TRAP,ABRT,EMT,FPE,BUS,SEGV,SYS,PIPE,ALRM,TERM,USR1,USR2, VTALRM,XCPU,XFSZ,LOST KILL default BUS caught termination_unwind_protect 0 HUP,INT, ILL,TRAP,ABRT,EMT,FPE,BUS,SEGV,SYS,PIPE,ALRM,TERM,USR1,USR2, VTALRM,XCPU,XFSZ,LOST SEGV caught termination_unwind_protect 0 HUP,INT, ILL,TRAP,ABRT,EMT,FPE,BUS,SEGV,SYS,PIPE,ALRM,TERM,USR1,USR2, VTALRM,XCPU,XFSZ,LOST SYS caught termination_unwind_protect 0 HUP,INT, ILL,TRAP,ABRT,EMT,FPE,BUS,SEGV,SYS,PIPE,ALRM,TERM,USR1,USR2, VTALRM,XCPU,XFSZ,LOST PIPE caught termination_unwind_protect 0 HUP,INT, ILL,TRAP,ABRT,EMT,FPE,BUS,SEGV,SYS,PIPE,ALRM,TERM,USR1,USR2, VTALRM,XCPU,XFSZ,LOST ALRM caught termination_unwind_protect 0 HUP,INT, ILL,TRAP,ABRT,EMT,FPE,BUS,SEGV,SYS,PIPE,ALRM,TERM,USR1,USR2, VTALRM,XCPU,XFSZ,LOST TERM ignored USR1 caught termination_unwind_protect 0 HUP,INT, ILL,TRAP,ABRT,EMT,FPE,BUS,SEGV,SYS,PIPE,ALRM,TERM,USR1,USR2, VTALRM,XCPU,XFSZ,LOST USR2 caught termination_unwind_protect 0 HUP,INT, ILL,TRAP,ABRT,EMT,FPE,BUS,SEGV,SYS,PIPE,ALRM,TERM,USR1,USR2, VTALRM,XCPU,XFSZ,LOST CLD blocked,caught 0x807d4d7 0 PWR default WINCH caught 0x807e182 0 <-- not all syms are present URG default POLL default STOP default TSTP ignored CONT default TTIN ignored TTOU ignored VTALRM caught termination_unwind_protect 0 HUP,INT, ILL,TRAP,ABRT,EMT,FPE,BUS,SEGV,SYS,PIPE,ALRM,TERM,USR1,USR2, VTALRM,XCPU,XFSZ,LOST PROF default XCPU caught termination_unwind_protect 0 HUP,INT, ILL,TRAP,ABRT,EMT,FPE,BUS,SEGV,SYS,PIPE,ALRM,TERM,USR1,USR2, VTALRM,XCPU,XFSZ,LOST XFSZ caught termination_unwind_protect 0 HUP,INT, ILL,TRAP,ABRT,EMT,FPE,BUS,SEGV,SYS,PIPE,ALRM,TERM,USR1,USR2, VTALRM,XCPU,XFSZ,LOST WAITING default LWP default FREEZE default THAW default CANCEL default LOST caught termination_unwind_protect 0 HUP,INT, ILL,TRAP,ABRT,EMT,FPE,BUS,SEGV,SYS,PIPE,ALRM,TERM,USR1,USR2, VTALRM,XCPU,XFSZ,LOST XRES default JVM1 default JVM2 default RTMIN default RTMIN+1 default RTMIN+2 default RTMIN+3 default RTMAX-3 default RTMAX-2 default RTMAX-1 default RTMAX default bash-3.00$ |
As far as I can tell, there is no easy way to do this in Linux, but someone has probably implemented a kernel patch/module to give you the information. Certainly it should be do-able with User Mode Linux.
Generally, if you are developing a POSIX-compliant application
on Linux or the Solaris OS, the application should port to the other OS
simply by recompilation. Of course, many applications will have
parts that are not addressed by POSIX. For instance, device
ioctl(2)
handling tends to be OS (and, of course, device)
specific.
Getting documentation for the Solaris OS is reasonably straightforward, since most of the documentation is at . Getting documentation for Linux is sometimes simple (search on the web), and sometimes not so simple. You'll find that Linux typically offers multiple ways to do the same thing (different implementations of threads, for example). My impression is that much of the Linux documentation is in the source code itself. This is fine if you have access to all the source code. You do have access to all of the source code, but it is not all in one place. In fact, it seems scattered all over the place. Sun's source is currently available all in one place (), but not all of it is there. I expect that over time, developers will add software to OpenSolaris that may not be available in the OpenSolaris source tree.
This article touched on some of the visibility tools
available on the two systems, but did not get into much detail.
Prior to Sun's coming out with OpenSolaris, Linux advocates could
always point to the source as a differentiator when it
came to visibility as to how things work.
Now, with OpenSolaris and tools such as DTrace, Linux will have to play
catch up. And at the rate of change of Linux, I'm sure it won't take
long.
I'm looking forward to both systems benefiting from each other's
good features, and learning from their mistakes.
chinaunix网友2010-11-23 15:45:21
很好的, 收藏了 推荐一个博客,提供很多免费软件编程电子书下载: http://free-ebooks.appspot.com