Some constant varible defined in kernel about executing user-space programs.
_STK_LIM(include/linux/resource.h)(stack size):Define the stack size limitation. In a standard kernel, the value is 8MB
STACK_TOP ()(stack pointer):Define the stack pointer. In a standard kernel, the value is TASK_SIZE.
PAGE_OFFSET(arch/arm/include/asm/memory.h):Define the virtual address of the start of the kernel image. In a standard kernel, the value is 0xC0000000(CONFIG_PAGE_OFFSET).
TASK_SIZE(arch/arm/include/asm/memory.h)(process address space size):Define the maximum size of a user space task. In a standard kernel, the value is 0xBF000000(PAGE_OFFSET-0x01000000)
TASK_UNMAPPED_BASE(the start virtual address of shared libaries mapping region): Define the lower boundary of the mmap VM area. The area also is memory mapped region for shared libraries. Because the program interpreter (/lib/ld-2.X.X.so for glibc, /lib/ld-uClibc-0.9.29.so for uClibc) will use mmap() to let the shared libraries file map to the area. In a standard kernel, the value is 0x40000000(PAGE_OFFSET / 3).
When appling the FCSE patch (http://sisyphus.hd.free.fr/~gilles/pub/fcse/downloads/fcse-2.6.33-v4.patch.bz2), the varibes described as mentioned above will be changed:
_STK_LIM will be 1MB
TASK_SIZE will be 0x02000000 (32 MB)
STACK_TOP will at 0x02000000 (TASK_SIZE)
TASK_UNMAPPED_BASE will at 0x00800000 (8M)
According to our requirement, we can use "ulimit -s $new_stack_size" to increase or decrease the stack size.(http://www.mail-archive.com/openmoko-kernel@lists.openmoko.org/msg10517.html)
The heap region will follow process image region. The following is the process address space of "venc" (cat /proc/959/maps | more):
00008000-00025000 r-xp 00000000 01:00 213 /usr/sbin/venc
0002c000-0002e000 rwxp 0001c000 01:00 213 /usr/sbin/venc
0002e000-003fa000 rwxp 0002e000 00:00 0 [heap]
40000000-4000c000 r-xp 00000000 01:00 159 /lib/ld-uClibc-0.9.29.so
4000c000-40010000 rwxp 4000c000 00:00 0
40010000-40011000 rwxs 00000000 00:09 1441 /dev/vpl_vic0
40011000-40012000 rwxs 00000000 00:09 1441 /dev/vpl_vic0
40012000-40013000 rwxs 02424000 00:09 1337 /dev/vma_die
40013000-40014000 r-xp 0000b000 01:00 159 /lib/ld-uClibc-0.9.29.so
40014000-40015000 rwxp 0000c000 01:00 159 /lib/ld-uClibc-0.9.29.so
40015000-40017000 r-xp 00000000 01:00 400 /usr/lib/libbitmaskresizer.so.1.0.0.1
40017000-4001e000 ---p 40017000 00:00 0
4001e000-4001f000 rwxp 00001000 01:00 400 /usr/lib/libbitmaskresizer.so.1.0.0.1
4001f000-40022000 r-xp 00000000 01:00 399 /usr/lib/libdeinterlacer.so.3.0.0.3
40022000-40029000 ---p 40022000 00:00 0
40029000-4002a000 rwxp 00002000 01:00 399 /usr/lib/libdeinterlacer.so.3.0.0.3
4002a000-40046000 r-xp 00000000 01:00 373 /usr/lib/libexpat.so.0.5.0
40046000-4004d000 ---p 40046000 00:00 0
4004d000-4004f000 rwxp 0001b000 01:00 373 /usr/lib/libexpat.so.0.5.0
4004f000-40050000 r-xp 00000000 01:00 428 /usr/lib/libframeratectrl.so.1.0.0.0
40050000-40057000 ---p 40050000 00:00 0
40057000-40058000 rwxp 00000000 01:00 428 /usr/lib/libframeratectrl.so.1.0.0.0
40058000-4007e000 r-xp 00000000 01:00 376 /usr/lib/libfreetype.so.6.3.20
4007e000-40085000 ---p 4007e000 00:00 0
40085000-40086000 rwxp 00025000 01:00 376 /usr/lib/libfreetype.so.6.3.20
40086000-40091000 r-xp 00000000 01:00 379 /usr/lib/libh264enc.so.2.3.0.4
......
42a9c000-4329b000 rwxp 42a9c000 00:00 0
50000000-5010e000 rwxs 04000000 00:09 1217 /dev/vpl_edmc
5010e000-50fe3000 rwxs 0410e000 00:09 1217 /dev/vpl_edmc
50fe3000-50fe5000 rwxs 04fe2000 00:09 1217 /dev/vpl_edmc
50fe5000-50fe6000 rwxs 04fe3000 00:09 1217 /dev/vpl_edmc
......
641b0000-64233000 rwxs 14d81000 00:09 1217 /dev/vpl_edmc
be974000-be989000 rwxp befeb000 00:00 0 [stack]
One thing for using FCSE must be noted:
To utilize the FCSE, compile and link all programs to run in the first 32 MB block of virtual
memory (VA). (refer to "P.516, ARM System Developer’s Guide Designing and Optimizing System Software")
The start virtual address of executable ELF image compiled using the GNU toolchain for arm eabi is "0x00008000" (On X86, the address is "0x08048000"). (check "arm-eabi-uclibc/usr/lib/ldscripts/armelf_linux_eabi.xc")
The Execution process of program under linux:
1. 使用者在shell執行外部程式
2. shell以fork+exec syscall方式執行外部程式
3. 透過int 0x80軟體中斷觸發kernel的exec syscall服務 (sys_execvp)
4. exec syscall執行Program loader(ELF Loader),載入process image (ELF image)
5. Program loader找到PT_INTERP segment。
6. Program loader將PT_LOAD segment mapping為新的text/data segment
text segment 由虛擬位址0x0804_8000開始,data segment 緊接其後
7. Program loader呼叫interpreter loader將program interpreter (ld.so)載入,並mapping 到process
memory
interpreter的text segment由虛擬位址0x4000_0000開始,interpreter的data segment緊接其後
8. Program loader將BSS segment 準備好
9. Program loader將process 的 register %eip (user-mode)修改為program interpreter的進入點,並將%esp設定為user
mode的stack
10. Program interpreter會找到process所需的shared library(名稱與路徑)
11. Program interpreter透過mmap(2),將shared library予以mapping到process memory,以完成整個Process Image的建立
12. 更新 shared library 的符號表。
13. Program interpreter執行x86 jump動作,到process的進入點
紀錄於ELF header的entry point
14. 程式正式執行
步驟 4.~9. 由 kernel 的 ELF loader 所負責。
步驟 11.~14 由 user-space 的 program interpreter(dynamic loader/linker,也就是 /lib/ld-linux.so.2)所負責。
Reference:
1. http://www.jollen.org/blog/2007/03/elf_program_loading_4_flow_chart.html
2. http://jserv.sayya.org/helloworld/