Unix Processes

MultiProcesses vs MultiThreaded




Unix Program Image in Main Memory

A program is a sequence of machine-language instructions stored in a file. Running a program means loading that list of machine-language instructions into memory and having the CPU execute the instructions, one by one.

Let's spend 1 minute to find out what is a process and how it is loaded into the memory.

A process is the memory space and settings with which the program runs.


To look at the processes from Unix SA's prospective, let's start with Unix command 'ps'.
[root@ipc4 ~]# ps -fal
F S UID PID PPID C PRI NI ADDR SZ WCHAN STIME TTY TIME CMD
0 S root 16611 3560 0 76 0 - 1487 - 11:14 tty7 0:00:00 /usr/
4 S root 16635 16522 0 77 0 - 1393 wait 11:20 pts/2 0:00:00 su
4 S root 16636 16635 0 75 0 - 1463 wait 11:20 pts/2 0:00:00 -bash
0 S shan 16710 15966 0 78 0 - 5570 322557
11:38 pts/0 0:00:00 ./multi
4 S root 16714 16166 0 77 0 - 1101 wait 11:39 pts/1 0:00:00 su
4 S root 16715 16714 0 77 0 - 1438 wait 11:39 pts/1 0:00:00 -bash
4 S root 16749 16715 0 60 -20 - 5996 322557
11:39 pts/1 0:00:00 ./multi
4 R root 16755 16636 0 77 0 - 729 - 11:43 pts/2 0:00:00 ps

The column marked S shows the status of each process. R is running, S is sleeping. WCHAN shows why a process is sleeping.

A process has a size, shown in the SZ column. This number
represents the amount of memory the process is using. The size of a process change as it runs. A program that allocates memory when it runs can get larger. Memory in a Unix system is divided into kernel space and user space. Processes live in user space.

Columns marked PRI and NI contain priority and nicesness levels of the process. The kernel uses these values to decide when to run processes or the priority of the processes.

TTY shows which terminal the process is connected to. If no tty, the process is started at startup.

Among the above processes, there are two instances of program "./multi", one runs under user "shan" and another runs under "root". The one under "root" pid 16749's nice value is "-20" and priority is "60", which has much higher priority than the one runs under "shan". That's because the root started multi with nice value of -20.
You can use command "renice" to adjust the nice value of a process.

#nice -n -20 ./multi


The commands "ps ax" or "ps lax" (in linux) will show you all the running system processes, you will realize that a lot of processes don't have terminal ( TTY column marked ?) because they are started when the system starts up not typed by a user at command line.


[root@ipc4 prog]# ps ax
PID TTY STAT TIME COMMAND
1 ? S 0:00 init [5]
2 ? S 0:00 [migration/0]
3 ? SN 0:00 [ksoftirqd/0]
4 ? S 0:00 [migration/1]
5 ? SN 0:00 [ksoftirqd/1]
6 ? S 0:00 [events/0]
7 ? S 0:00 [events/1]
8 ? S 0:00 [khelper]
9 ? S 0:00 [kacpid]
22 ? S 0:00 [kblockd/0]
23 ? S 0:00 [kblockd/1]
33 ? S 0:00 [pdflush]
24 ? S 0:00 [khubd]
34 ? S 0:00 [pdflush]
36 ? S 0:00 [aio/0]
37 ? S 0:00 [aio/1]
35 ? S 0:01 [kswapd0]
111 ? S 0:00 [kseriod]
182 ? S 0:00 [scsi_eh_0]
194 ? S 0:00 [kmirrord/0]
195 ? S 0:00 [kmirrord/1]
203 ? S 0:03 [kjournald]
982 ? Ss 0:00 udevd
1668 ? S 0:00 [kjournald]
2175 ? Ss 0:00 syslogd -m 0
2179 ? Ss 0:00 klogd -x
2190 ? Ss 0:08 irqbalance
2208 ? Ss 0:00 portmap
2228 ? Ss 0:00 rpc.statd
2261 ? Ss 0:00 rpc.idmapd
2306 ? S 0:00 /usr/local/sbin/ypserv
2309 ? S 0:00 /usr/local/sbin/rpc.yppasswdd
2317 ? Sl 0:00 ypbind
2372 ? Ss 0:00 /usr/sbin/acpid
2435 ? Ss 0:52 /usr/sbin/vmware-guestd --background /var/run/vmware-
2491 ? Ssl 0:00 /usr/sbin/named -u named -t /var/named/chroot
2504 ? Ss 0:00 /usr/sbin/sshd
2532 ? SLs 0:00 ntpd -u ntp:ntp -p /var/run/ntpd.pid -g
2552 ? Ss 0:02 sendmail: accepting connections
2560 ? Ss 0:00 sendmail: Queue runner@01:00:00 for /var/spool/client
2571 ? Ss 0:00 gpm -m /dev/input/mice -t imps2
2591 ? Ss 0:00 crond
2617 ? Ss 0:00 xfs -droppriv -daemon
2636 ? Ss 0:00 /usr/sbin/atd
2655 ? Ssl 0:00 dbus-daemon-1 --system
2666 ? Ss 0:00 cups-config-daemon
2677 ? Ss 0:26 hald
2699 ? S 0:00 /bin/sh /usr/bin/mysqld_safe --datadir=/var/lib/mysql
2713 tty1 Ss+ 0:00 /sbin/mingetty tty1
2715 tty2 Ss+ 0:00 /sbin/mingetty tty2

Process is program in action.

How shell runs program?

A. User types program's name 'a.out'

B. The shell creates a new process to run the program ;

C. The shell loads the program from the disk into the process;
(done by execvp( const *prog, const char *argv[])

D. The program runs in its process until it is done.

Note: The kernel loads the program from the disk into CURRENT process, replacing the coe and data of current process.

In the following code, the message "ls is done. bye." will NOT be displayed, because it was erased by execvp.

The exec system call clears out the current program code from the current process, then, in the now empty process, puts the code of the program named in the exec call, and then runs that new program. exec also changes the memory allocation of the process to fit the space requirement of the new program. Note, the following code
printf("* * * ls is done. bye\n") will not be executed.

/* exec1.c
*/

main()
{
char *arglist[3];

arglist[0] = "ls";
arglist[1] = "-l";
arglist[2] = 0 ;
printf("* * * About to exec ls -l\n");
execvp( "ls" , arglist );
printf("* * * ls is done. bye\n");
}

[shan@ipc4 uulp]$ ./exec
* * * About to exec ls -l
total 124
-rw-rw-r-- 1 shan shan 2593 Nov 4 12:37 bounce.c
-rw-rw-r-- 1 shan shan 476 Nov 4 12:38 bounce.h
-rwxrwxr-x 1 shan shan 4924 Nov 4 15:03 exec
-rw-rw-r-- 1 shan shan 262 Nov 4 15:03 exec.c
-rw-rw-r-- 1 shan shan 1300 Nov 4 15:04 exec.out
drwxrwxr-x 2 shan shan 4096 Nov 4 12:43 game
-rwxrwxr-x 1 shan shan 4975 Nov 4 12:31 ignore
-rw-rw-r-- 1 shan shan 258 Nov 4 12:31 ignore.c
-rwxrwxr-x 1 shan shan 4989 Nov 4 12:21 job-1
-rwxrwxr-x 1 shan shan 6710 Nov 4 12:28 play
-rw-rw-r-- 1 shan shan 3271 Nov 4 12:28 play.c
-rwxrwxr-x 1 shan shan 5013 Nov 4 12:12 signal
-rw-rw-r-- 1 shan shan 399 Nov 4 12:21 signal.c




From Unix internal, let's see a process' memory layout:

1. Text Segment.
This is the machine instructions that are executed by CPU.

2.
Initialized data segment.
It contains variables that are specifically initialized in the program.


3. Uninitialized data segment or "bss" (block started by symbol).
Data in this segment is initialized by the kernel (0 or null pointers) before the program starts executing. e.g. C declaration long sum[2000];


4. Stack.
This is where automatic variables are stored, along with information that is saved each time a function is called.


5. Heap.
Dynamic memory allocation usually takes place in heap.


Unix 'size' command reports the sizes in bytes of the text, data, and bss segments.

[root@ipc4 prog]# size ~shan/prog/multi
text data bss dec hex filename
1389 280 8 1677 68d /home/shan/prog/multi

[root@ipc4 prog]# size /usr/bin/gcc

text data bss dec hex filename

89316 1576 932 91824 166b0 /usr/bin/gcc



Now, let's see how process (a running program) is loaded into the memory:



* In Linux processes loaded from a file system (using either the execve() or spawn() system calls) are in ELF format.

* If the file system is on a block-oriented device, the code and data are loaded into main memory.

* If the file system is memory mapped (e.g. ROM/Flash image), the code needn't be loaded into RAM, but may be executed in place.

* This approach makes all RAM available for data and stack, leaving the code in ROM or Flash. In all cases, if the same process is loaded more than once, its code will be shared.

* Before we can run an executable, firstly we have to load it into memory.

* This is done by the loader, which is generally part of the operating system. The loader does the following things (from other things):

1. Memory and access validation - Firstly, the OS system kernel reads in the program file’s header information and does the validation for type, access permissions, memory requirement and its ability to run its instructions. It confirms that file is an executable image and calculates memory requirements.

2. Process setup includes:

1) Allocates primary memory for the program's execution.
2) Copies address space from secondary to primary memory.
3) Copies the .text and .data sections from the executable into primary memory.
4) Copies program arguments (e.g., command line arguments) onto the stack.
5) Initializes registers: sets the esp (stack pointer) to point to top of stack, clears the rest.
6) Jumps to start routine, which: copies main()'s arguments off of the stack, and jumps to main().

* Address space is memory space that contains program code, stack, and data segments or in other word, all data the program uses as it runs.

* The memory layout, consists of three segments (text, data, and stack), see the attached figure.

* The dynamic data segment is also referred to as the heap, the place dynamically allocated memory (such as from malloc() and new) comes from. Dynamically allocated memory is memory allocated at run time instead of compile/link time.

* This organization enables any division of the dynamically allocated memory between the heap (explicitly) and the stack (implicitly). This explains why the stack grows downward and heap grows upward.



Below is a multithreaded C code, let's compile it and dump the object file content using readelf program.

[root@ipc4 prog]# cat multi.c
#include
#include

#define NUM 500

main()
{
pthread_t t1,t2;

long sum[1000];
int maxcount=99;

void *print_msg(void *);

pthread_create(&t1, NULL, print_msg, (void *) "hello");
pthread_create(&t2, NULL, print_msg, (void *) " world\n");
pthread_join(t1,NULL);
pthread_join(t2,NULL);
}

void *print_msg(void *m)
{
char *cp = (char *) m;
int i;
for (i=0 ; i<>
printf("%s",m);
fflush(stdout);
sleep(1);
}
return NULL;
}

[root@ipc4 prog]# gcc -g -v multi.c -lpthread -o multi
Reading specs from /usr/lib/gcc/i386-redhat-linux/3.4.3/specs
Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --enable-shared --enable-threads=posix --disable-checking --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-java-awt=gtk --host=i386-redhat-linux
Thread model: posix
gcc version 3.4.3 20050227 (Red Hat 3.4.3-22.1)
/usr/libexec/gcc/i386-redhat-linux/3.4.3/cc1 -quiet -v multi.c -quiet -dumpbase multi.c -auxbase multi -g -version -o /tmp/ccoHQEeG.s
ignoring nonexistent directory "/usr/lib/gcc/i386-redhat-linux/3.4.3/../../../../i386-redhat-linux/include"
#include "..." search starts here:
#include <...> search starts here:
/usr/local/include
/usr/lib/gcc/i386-redhat-linux/3.4.3/include
/usr/include
End of search list.
GNU C version 3.4.3 20050227 (Red Hat 3.4.3-22.1) (i386-redhat-linux)
compiled by GNU C version 3.4.3 20050227 (Red Hat 3.4.3-22.1).
GGC heuristics: --param ggc-min-expand=64 --param ggc-min-heapsize=64314
as -V -Qy -o /tmp/ccw7Cttf.o /tmp/ccoHQEeG.s
GNU assembler version 2.15.92.0.2 (i386-redhat-linux) using BFD version 2.15.92.0.2 20040927
/usr/libexec/gcc/i386-redhat-linux/3.4.3/collect2 --eh-frame-hdr -m elf_i386 -dynamic-linker /lib/ld-linux.so.2 -o multi /usr/lib/gcc/i386-redhat-linux/3.4.3/../../../crt1.o /usr/lib/gcc/i386-redhat-linux/3.4.3/../../../crti.o /usr/lib/gcc/i386-redhat-linux/3.4.3/crtbegin.o -L/usr/lib/gcc/i386-redhat-linux/3.4.3 -L/usr/lib/gcc/i386-redhat-linux/3.4.3 -L/usr/lib/gcc/i386-redhat-linux/3.4.3/../../.. /tmp/ccw7Cttf.o -lpthread -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed /usr/lib/gcc/i386-redhat-linux/3.4.3/crtend.o /usr/lib/gcc/i386-redhat-linux/3.4.3/../../../crtn.o





[root@ipc4 prog]# readelf -hS ~shan/prog/multi
ELF Header:
Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
Class: ELF32
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: EXEC (Executable file)
Machine: Intel 80386
Version: 0x1
Entry point address: 0x8048410
Start of program headers: 52 (bytes into file)
Start of section headers: 2460 (bytes into file)
Flags: 0x0
Size of this header: 52 (bytes)
Size of program headers: 32 (bytes)
Number of program headers: 7
Size of section headers: 40 (bytes)
Number of section headers: 28
Section header string table index: 25

Section Headers:
[Nr] Name Type Addr Off Size ES Flg Lk Inf Al
[ 0] NULL 00000000 000000 000000 00 0 0 0
[ 1] .interp PROGBITS 08048114 000114 000013 00 A 0 0 1
[ 2] .note.ABI-tag NOTE 08048128 000128 000020 00 A 0 0 4
[ 3] .hash HASH 08048148 000148 000040 04 A 4 0 4
[ 4] .dynsym DYNSYM 08048188 000188 0000b0 10 A 5 1 4
[ 5] .dynstr STRTAB 08048238 000238 0000aa 00 A 0 0 1
[ 6] .gnu.version VERSYM 080482e2 0002e2 000016 02 A 4 0 2
[ 7] .gnu.version_r VERNEED 080482f8 0002f8 000050 00 A 5 2 4
[ 8] .rel.dyn REL 08048348 000348 000010 08 A 4 0 4
[ 9] .rel.plt REL 08048358 000358 000030 08 A 4 11 4
[10] .init PROGBITS 08048388 000388 000017 00 AX 0 0 4
[11] .plt PROGBITS 080483a0 0003a0 000070 04 AX 0 0 4
[12] .text PROGBITS 08048410 000410 00023c 00 AX 0 0 4
[13] .fini PROGBITS 0804864c 00064c 00001a 00 AX 0 0 4
[14] .rodata PROGBITS 08048668 000668 000019 00 A 0 0 4
[15] .eh_frame PROGBITS 08048684 000684 000004 00 A 0 0 4
[16] .ctors PROGBITS 08049688 000688 000008 00 WA 0 0 4
[17] .dtors PROGBITS 08049690 000690 000008 00 WA 0 0 4
[18] .jcr PROGBITS 08049698 000698 000004 00 WA 0 0 4
[19] .dynamic DYNAMIC 0804969c 00069c 0000d0 08 WA 5 0 4
[20] .got PROGBITS 0804976c 00076c 000004 04 WA 0 0 4
[21] .got.plt PROGBITS 08049770 000770 000024 04 WA 0 0 4
[22] .data PROGBITS 08049794 000794 00000c 00 WA 0 0 4
[23] .bss NOBITS 080497a0 0007a0 000008 00 WA 0 0 4
[24] .comment PROGBITS 00000000 0007a0 000123 00 0 0 1
[25] .shstrtab STRTAB 00000000 0008c3 0000d7 00 0 0 1
[26] .symtab SYMTAB 00000000 000dfc 0004c0 10 27 44 4
[27] .strtab STRTAB 00000000 0012bc 0002a8 00 0 0 1
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings)
I (info), L (link order), G (group), x (unknown)
O (extra OS processing required) o (OS specific), p (processor specific)
[root@ipc4 prog]# readelf -a ~shan/prog/multi
ELF Header:
Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
Class: ELF32
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: EXEC (Executable file)
Machine: Intel 80386
Version: 0x1
Entry point address: 0x8048410
Start of program headers: 52 (bytes into file)
Start of section headers: 2460 (bytes into file)
Flags: 0x0
Size of this header: 52 (bytes)
Size of program headers: 32 (bytes)
Number of program headers: 7
Size of section headers: 40 (bytes)
Number of section headers: 28
Section header string table index: 25

Section Headers:
[Nr] Name Type Addr Off Size ES Flg Lk Inf Al
[ 0] NULL 00000000 000000 000000 00 0 0 0
[ 1] .interp PROGBITS 08048114 000114 000013 00 A 0 0 1
[ 2] .note.ABI-tag NOTE 08048128 000128 000020 00 A 0 0 4
[ 3] .hash HASH 08048148 000148 000040 04 A 4 0 4
[ 4] .dynsym DYNSYM 08048188 000188 0000b0 10 A 5 1 4
[ 5] .dynstr STRTAB 08048238 000238 0000aa 00 A 0 0 1
[ 6] .gnu.version VERSYM 080482e2 0002e2 000016 02 A 4 0 2
[ 7] .gnu.version_r VERNEED 080482f8 0002f8 000050 00 A 5 2 4
[ 8] .rel.dyn REL 08048348 000348 000010 08 A 4 0 4
[ 9] .rel.plt REL 08048358 000358 000030 08 A 4 11 4
[10] .init PROGBITS 08048388 000388 000017 00 AX 0 0 4
[11] .plt PROGBITS 080483a0 0003a0 000070 04 AX 0 0 4
[12] .text PROGBITS 08048410 000410 00023c 00 AX 0 0 4
[13] .fini PROGBITS 0804864c 00064c 00001a 00 AX 0 0 4
[14] .rodata PROGBITS 08048668 000668 000019 00 A 0 0 4
[15] .eh_frame PROGBITS 08048684 000684 000004 00 A 0 0 4
[16] .ctors PROGBITS 08049688 000688 000008 00 WA 0 0 4
[17] .dtors PROGBITS 08049690 000690 000008 00 WA 0 0 4
[18] .jcr PROGBITS 08049698 000698 000004 00 WA 0 0 4
[19] .dynamic DYNAMIC 0804969c 00069c 0000d0 08 WA 5 0 4
[20] .got PROGBITS 0804976c 00076c 000004 04 WA 0 0 4
[21] .got.plt PROGBITS 08049770 000770 000024 04 WA 0 0 4
[22] .data PROGBITS 08049794 000794 00000c 00 WA 0 0 4
[23] .bss NOBITS 080497a0 0007a0 000008 00 WA 0 0 4
[24] .comment PROGBITS 00000000 0007a0 000123 00 0 0 1
[25] .shstrtab STRTAB 00000000 0008c3 0000d7 00 0 0 1
[26] .symtab SYMTAB 00000000 000dfc 0004c0 10 27 44 4
[27] .strtab STRTAB 00000000 0012bc 0002a8 00 0 0 1
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings)
I (info), L (link order), G (group), x (unknown)
O (extra OS processing required) o (OS specific), p (processor specific)

Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
PHDR 0x000034 0x08048034 0x08048034 0x000e0 0x000e0 R E 0x4
INTERP 0x000114 0x08048114 0x08048114 0x00013 0x00013 R 0x1
[Requesting program interpreter: /lib/ld-linux.so.2]
LOAD 0x000000 0x08048000 0x08048000 0x00688 0x00688 R E 0x1000
LOAD 0x000688 0x08049688 0x08049688 0x00118 0x00120 RW 0x1000
DYNAMIC 0x00069c 0x0804969c 0x0804969c 0x000d0 0x000d0 RW 0x4
NOTE 0x000128 0x08048128 0x08048128 0x00020 0x00020 R 0x4
GNU_STACK 0x000000 0x00000000 0x00000000 0x00000 0x00000 RW 0x4

Section to Segment mapping:
Segment Sections...
00
01 .interp
02 .interp .note.ABI-tag .hash .dynsym .dynstr .gnu.version .gnu.version_r .rel.dyn .rel.plt .init .plt .text .fini .rodata .eh_frame
03 .ctors .dtors .jcr .dynamic .got .got.plt .data .bss
04 .dynamic
05 .note.ABI-tag
06

Dynamic section at offset 0x69c contains 21 entries:
Tag Type Name/Value
0x00000001 (NEEDED) Shared library: [libpthread.so.0]
0x00000001 (NEEDED) Shared library: [libc.so.6]
0x0000000c (INIT) 0x8048388
0x0000000d (FINI) 0x804864c
0x00000004 (HASH) 0x8048148
0x00000005 (STRTAB) 0x8048238
0x00000006 (SYMTAB) 0x8048188
0x0000000a (STRSZ) 170 (bytes)
0x0000000b (SYMENT) 16 (bytes)
0x00000015 (DEBUG) 0x0
0x00000003 (PLTGOT) 0x8049770
0x00000002 (PLTRELSZ) 48 (bytes)
0x00000014 (PLTREL) REL
0x00000017 (JMPREL) 0x8048358
0x00000011 (REL) 0x8048348
0x00000012 (RELSZ) 16 (bytes)
0x00000013 (RELENT) 8 (bytes)
0x6ffffffe (VERNEED) 0x80482f8
0x6fffffff (VERNEEDNUM) 2
0x6ffffff0 (VERSYM) 0x80482e2
0x00000000 (NULL) 0x0

Relocation section '.rel.dyn' at offset 0x348 contains 2 entries:
Offset Info Type Sym.Value Sym. Name
0804976c 00000a06 R_386_GLOB_DAT 00000000 __gmon_start__
080497a0 00000305 R_386_COPY 080497a0 stdout

Relocation section '.rel.plt' at offset 0x358 contains 6 entries:
Offset Info Type Sym.Value Sym. Name
0804977c 00000107 R_386_JUMP_SLOT 00000000 fflush
08049780 00000207 R_386_JUMP_SLOT 00000000 pthread_create
08049784 00000407 R_386_JUMP_SLOT 00000000 sleep
08049788 00000507 R_386_JUMP_SLOT 00000000 __libc_start_main
0804978c 00000607 R_386_JUMP_SLOT 00000000 printf
08049790 00000707 R_386_JUMP_SLOT 00000000 pthread_join

There are no unwind sections in this file.

Symbol table '.dynsym' contains 11 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 00000000 0 NOTYPE LOCAL DEFAULT UND
1: 00000000 293 FUNC GLOBAL DEFAULT UND fflush@GLIBC_2.0 (2)
2: 00000000 396 FUNC GLOBAL DEFAULT UND pthread_create@GLIBC_2.1 (3)
3: 080497a0 4 OBJECT GLOBAL DEFAULT 23 stdout@GLIBC_2.0 (2)
4: 00000000 626 FUNC GLOBAL DEFAULT UND sleep@GLIBC_2.0 (2)
5: 00000000 221 FUNC GLOBAL DEFAULT UND __libc_start_main@GLIBC_2.0 (2)
6: 00000000 54 FUNC GLOBAL DEFAULT UND printf@GLIBC_2.0 (2)
7: 00000000 692 FUNC GLOBAL DEFAULT UND pthread_join@GLIBC_2.0 (4)
8: 0804866c 4 OBJECT GLOBAL DEFAULT 14 _IO_stdin_used
9: 00000000 0 NOTYPE WEAK DEFAULT UND _Jv_RegisterClasses
10: 00000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__

Symbol table '.symtab' contains 76 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 00000000 0 NOTYPE LOCAL DEFAULT UND
1: 08048114 0 SECTION LOCAL DEFAULT 1
2: 08048128 0 SECTION LOCAL DEFAULT 2
3: 08048148 0 SECTION LOCAL DEFAULT 3
4: 08048188 0 SECTION LOCAL DEFAULT 4
5: 08048238 0 SECTION LOCAL DEFAULT 5
6: 080482e2 0 SECTION LOCAL DEFAULT 6
7: 080482f8 0 SECTION LOCAL DEFAULT 7
8: 08048348 0 SECTION LOCAL DEFAULT 8
9: 08048358 0 SECTION LOCAL DEFAULT 9
10: 08048388 0 SECTION LOCAL DEFAULT 10
11: 080483a0 0 SECTION LOCAL DEFAULT 11
12: 08048410 0 SECTION LOCAL DEFAULT 12
13: 0804864c 0 SECTION LOCAL DEFAULT 13
14: 08048668 0 SECTION LOCAL DEFAULT 14
15: 08048684 0 SECTION LOCAL DEFAULT 15
16: 08049688 0 SECTION LOCAL DEFAULT 16
17: 08049690 0 SECTION LOCAL DEFAULT 17
18: 08049698 0 SECTION LOCAL DEFAULT 18
19: 0804969c 0 SECTION LOCAL DEFAULT 19
20: 0804976c 0 SECTION LOCAL DEFAULT 20
21: 08049770 0 SECTION LOCAL DEFAULT 21
22: 08049794 0 SECTION LOCAL DEFAULT 22
23: 080497a0 0 SECTION LOCAL DEFAULT 23
24: 00000000 0 SECTION LOCAL DEFAULT 24
25: 00000000 0 SECTION LOCAL DEFAULT 25
26: 00000000 0 SECTION LOCAL DEFAULT 26
27: 00000000 0 SECTION LOCAL DEFAULT 27
28: 08048434 0 FUNC LOCAL DEFAULT 12 call_gmon_start
29: 00000000 0 FILE LOCAL DEFAULT ABS crtstuff.c
30: 08049688 0 OBJECT LOCAL DEFAULT 16 __CTOR_LIST__
31: 08049690 0 OBJECT LOCAL DEFAULT 17 __DTOR_LIST__
32: 08049698 0 OBJECT LOCAL DEFAULT 18 __JCR_LIST__
33: 0804979c 0 OBJECT LOCAL DEFAULT 22 p.0
34: 080497a4 1 OBJECT LOCAL DEFAULT 23 completed.1
35: 08048458 0 FUNC LOCAL DEFAULT 12 __do_global_dtors_aux
36: 0804848c 0 FUNC LOCAL DEFAULT 12 frame_dummy
37: 00000000 0 FILE LOCAL DEFAULT ABS crtstuff.c
38: 0804968c 0 OBJECT LOCAL DEFAULT 16 __CTOR_END__
39: 08049694 0 OBJECT LOCAL DEFAULT 17 __DTOR_END__
40: 08048684 0 OBJECT LOCAL DEFAULT 15 __FRAME_END__
41: 08049698 0 OBJECT LOCAL DEFAULT 18 __JCR_END__
42: 08048628 0 FUNC LOCAL DEFAULT 12 __do_global_ctors_aux
43: 00000000 0 FILE LOCAL DEFAULT ABS multi.c
44: 0804969c 0 OBJECT GLOBAL DEFAULT 19 _DYNAMIC
45: 08048668 4 OBJECT GLOBAL DEFAULT 14 _fp_hw
46: 00000000 293 FUNC GLOBAL DEFAULT UND fflush@@GLIBC_2.0
47: 00000000 396 FUNC GLOBAL DEFAULT UND pthread_create@@GLIBC_2.1
48: 08049688 0 NOTYPE GLOBAL HIDDEN ABS __fini_array_end
49: 08049798 0 OBJECT GLOBAL HIDDEN 22 __dso_handle
50: 080485e4 66 FUNC GLOBAL DEFAULT 12 __libc_csu_fini
51: 08048388 0 FUNC GLOBAL DEFAULT 10 _init
52: 080497a0 4 OBJECT GLOBAL DEFAULT 23 stdout@@GLIBC_2.0
53: 08048410 0 FUNC GLOBAL DEFAULT 12 _start
54: 00000000 626 FUNC GLOBAL DEFAULT UND sleep@@GLIBC_2.0
55: 08049688 0 NOTYPE GLOBAL HIDDEN ABS __fini_array_start
56: 08048590 82 FUNC GLOBAL DEFAULT 12 __libc_csu_init
57: 080497a0 0 NOTYPE GLOBAL DEFAULT ABS __bss_start
58: 080484b8 123 FUNC GLOBAL DEFAULT 12 main
59: 00000000 221 FUNC GLOBAL DEFAULT UND __libc_start_main@@GLIBC_
60: 08049688 0 NOTYPE GLOBAL HIDDEN ABS __init_array_end
61: 08049794 0 NOTYPE WEAK DEFAULT 22 data_start
62: 00000000 54 FUNC GLOBAL DEFAULT UND printf@@GLIBC_2.0
63: 0804864c 0 FUNC GLOBAL DEFAULT 13 _fini
64: 08049688 0 NOTYPE GLOBAL HIDDEN ABS __preinit_array_end
65: 08048533 91 FUNC GLOBAL DEFAULT 12 print_msg
66: 00000000 692 FUNC GLOBAL DEFAULT UND pthread_join@@GLIBC_2.0
67: 080497a0 0 NOTYPE GLOBAL DEFAULT ABS _edata
68: 08049770 0 OBJECT GLOBAL DEFAULT 21 _GLOBAL_OFFSET_TABLE_
69: 080497a8 0 NOTYPE GLOBAL DEFAULT ABS _end
70: 08049688 0 NOTYPE GLOBAL HIDDEN ABS __init_array_start
71: 0804866c 4 OBJECT GLOBAL DEFAULT 14 _IO_stdin_used
72: 08049794 0 NOTYPE GLOBAL DEFAULT 22 __data_start
73: 00000000 0 NOTYPE WEAK DEFAULT UND _Jv_RegisterClasses
74: 08049688 0 NOTYPE GLOBAL HIDDEN ABS __preinit_array_start
75: 00000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__

Histogram for bucket list length (total of 3 buckets):
Length Number % of total Coverage
0 0 ( 0.0%)
1 1 ( 33.3%) 10.0%
2 0 ( 0.0%) 10.0%
3 1 ( 33.3%) 40.0%
4 0 ( 0.0%) 40.0%
5 0 ( 0.0%) 40.0%
6 1 ( 33.3%) 100.0%

Version symbols section '.gnu.version' contains 11 entries:
Addr: 00000000080482e2 Offset: 0x0002e2 Link: 4 (.dynsym)
000: 0 (*local*) 2 (GLIBC_2.0) 3 (GLIBC_2.1) 2 (GLIBC_2.0)
004: 2 (GLIBC_2.0) 2 (GLIBC_2.0) 2 (GLIBC_2.0) 4 (GLIBC_2.0)
008: 1 (*global*) 0 (*local*) 0 (*local*)

Version needs section '.gnu.version_r' contains 2 entries:
Addr: 0x00000000080482f8 Offset: 0x0002f8 Link to section: 5 (.dynstr)
000000: Version: 1 File: libpthread.so.0 Cnt: 2
0x0010: Name: GLIBC_2.0 Flags: none Version: 4
0x0020: Name: GLIBC_2.1 Flags: none Version: 3
0x0030: Version: 1 File: libc.so.6 Cnt: 1
0x0040: Name: GLIBC_2.0 Flags: none Version: 2




Bonus for UNIX Admins:

[shan@ipc4 uulp]$ which ps options can do this?

PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND
7196 7197 7197 7197 pts/5 7424 Ss 500 0:00 -bash
7197 7415 7415 7197 pts/5 7424 S 500 0:00 \_ ./fork2
7415 7416 7415 7197 pts/5 7424 S 500 0:00 | \_ ./fork2
7416 7417 7415 7197 pts/5 7424 S 500 0:00 | | \_ ./fork2
7417 7419 7415 7197 pts/5 7424 S 500 0:00 | | | \_ ./fork2
7416 7421 7415 7197 pts/5 7424 S 500 0:00 | | \_ ./fork2
7415 7418 7415 7197 pts/5 7424 S 500 0:00 | \_ ./fork2
7418 7420 7415 7197 pts/5 7424 S 500 0:00 | | \_ ./fork2
7415 7422 7415 7197 pts/5 7424 S 500 0:00 | \_ ./fork2
7197 7424 7424 7197 pts/5 7424 R+ 500 0:00 \_ ps ajf


Or this?

7194 7194 7194 ? 00:00:00 sshd
7196 7194 7194 ? 00:00:02 sshd
7197 7197 7197 pts/5 00:00:00 bash
7426 7426 7197 pts/5 00:00:00 fork2
7427 7426 7197 pts/5 00:00:00 fork2
7428 7426 7197 pts/5 00:00:00 fork2
7429 7426 7197 pts/5 00:00:00 fork2
7431 7426 7197 pts/5 00:00:00 fork2
7430 7426 7197 pts/5 00:00:00 fork2
7432 7426 7197 pts/5 00:00:00 fork2
7433 7426 7197 pts/5 00:00:00 fork2
7434 7434 7197 pts/5 00:00:00 ps
2514 2514 2514 ? 00:00:00 xinetd


(answers in whites: ps ajf and ps -ejH )