Thursday, January 15, 2009

More Linux Tips

- Detailed info about system: Actually these are kernel messages and are stored as logs in /bin/dmesg.

- Determining runlevel {Shows previous & current runlevel}
0->Halt 1->Single User Mode
2-> Multiuser w/o NFS 3-> Full Multiuser 6-> Reboot

To modify init level-> /etc/inittab

- To switch runlevels, use init command.
$init 3

- Difference between Paging and Swapping
Paging refers to movement of pages to frames on the disk. It's a considerably cheaper operation. Swapping means to move entire address space of a process to disk. This is very expensive operation and happens when a process sleeps or when thrashing occurs.

Monday, January 12, 2009

Linux Linker Unveiled: The Secret Services

Linux linker does not seem to be a lead actor in play of application. But it work like the script which is essential to success of the play. Linker(ldd) is a piece of software that is primarily responsible for address patching a.k.a. relocation. Object files bear absolute and relative addresses.

// test.c
int main()

Disassembly of section .text:

0: 55 push %ebp
1: 89 e5 mov %esp,%ebp
3: 83 ec 08 sub $0x8,%esp
6: 83 e4 f0 and $0xfffffff0,%esp
9: b8 00 00 00 00 mov $0x0,%eax
e: 29 c4 sub %eax,%esp
10: e8 fc ff ff ff call 11
15: c9 leave
16: c3 ret

# An object file always starts on address 0x0000.

You can see that addresses are relative to the module and called function is completely unknown to foo. Linker take these object files, relocate their addresses to loading addresses(virtual addresses) and resolve calls to function by a function offset table.

To get a function offset table:
$objdump -x ./test.o

00000011 R_386_PC32 foo

All functions called from a file are listed in this table and here foo() has got 0x11 offset. Once all object files are there linker patches the offset with virtual address. Though call to foo() has been patched with correct virtual address, offset of the instruction is still the same(main+0x11).

8048344: 55 push %ebp
8048345: 89 e5 mov %esp,%ebp
8048347: 83 ec 08 sub $0x8,%esp
804834a: 83 e4 f0 and $0xfffffff0,%esp
804834d: b8 00 00 00 00 mov $0x0,%eax
8048352: 29 c4 sub %eax,%esp
8048354: e8 03 00 00 00 call 804835c
8048359: c9 leave
804835a: c3 ret
804835b: 90 nop

0804835c :
804835c: 55 push %ebp
804835d: 89 e5 mov %esp,%ebp
804835f: 5d pop %ebp
8048360: c3 ret

Friday, January 9, 2009

Linux Secrets!

1. Linux uses COW scheme with virtual memory management.
2. Threads in Linux can be LinuxThreads, NPTL(Redhat). NPTL is more efficient and from kernel 2.6 onwards it'll be used. Using env variable LD_ASSUME_KERNEL you can decide which thread library to choose.
3. Linux kernel do not discriminate between threads and processes while making scheduling decision.
4. Memory allocation of a process can be seen with 'pmap' command.
5. Linux CPU scheduler is O(1) scheduler i.e. regardless of number of processes, it always take a constant time to select a process.
6. Linux memory management for IA-32 can address only 1GB of physical memory. Beyond this memory has to mapped to the 1GB range hence allocation a page beyond 1GB degrades performance.
7. IA64 can address 64-128GB of memory.
8. Linux allocates most part of the disk's free space to swap. This improves the performance of VMM.
9. It follows Buddy System for page allocation which try to keep memory address contiguous. Have a loot at /proc/buddyinfo.
10. If no free page is available, kswapd kernel thread reclaims free pages. This thread is used by buddy system and follows LRU. Kernel pages are never swapped out of memory.

Thursday, January 8, 2009

Stack Unwinding

A very nice explanation of what stack unwinding is and why is it needed.

Wednesday, January 7, 2009

Linux Memory Management Secrets!

Tips to Improve Dynamic Memory Performance

- Instead of using memset() to initialize malloc()'ed memory, use calloc(). Because when you call memset(), VM system has to map the pages in to memory in order to zero initialize them. It's very expensive and wasteful if you don't intend to use the pages right away.
calloc() reserves the needed address space but does not zero initialize them unless memory is used. Hence it postpones the need to load pages in to memory. It also lets the system initialize pages as they’re used, as opposed to all at once.

- Lazy allocation: A global(normal variable or a buffer) can be replaced with a static and a couple of functions to allow its access.

- memcpy() & memmove() needs both blocks to be memory resident. Use them if size of blocks is small(>16KB), you would be using the blocks right away, s/d blocks are not page aligned, blocks overlap.
But if you intend to postpone the use, you would increasing the working set of the application. For small amount of data, use memcpy().

- To check heap dysfunctional behavior: $ MALLOC_CHECK_=1 ./a.out
It'll give an address related to each violation of dynamic memory routines.

- Electric fence : Works very well with gdb

- Libsafe: for libc routines