2007年5月22日火曜日

5/15分の宿題

  1. Experimentally construct a rough memory map for an application on your operating system.
    1. Write a program that prints out (in hexadecimal) the addresses of the following:
      1. main()
      2. a variable on the outermost stack frame (main()'s stack frame)
      3. a variable on the stack frame of a recursively-called function, called to a depth of five times
      4. a statically-defined but uninitialized variable
      5. a statically-defined, initialized variable
      6. several large chunks of malloc()ed memory
      7. a library routine, such as strcpy()
      8. a system call wrapper, such as the one for write()
    2. Take that information and draw a memory map for your OS. It should indicate which direction the stack and the heap grow in. An ASCII picture is okay, or you can use a drawing program of some sort if you wish.
      1. How big is the distance between your stack and your heap?
      2. Was your program compiled with static libraries or shared libraries?

A:
1: 0x8048454
2: 0xbfd8cc70
3: 0xbfd8cc04
4: 0x80497e0
5: 0x80497d8
6: 0xb5fc6008
7: 0x8048364
8: 0x8048334

source code:
#include <stdio.h>
#include <string.h>
#include <unistd.h>

#define ALLOC_SIZE (1024 * 1024 * 32)

void rec_call(int);

int uninitialized_int;
int initialized_int = 0xbeaf;

int main(){
char *buff;
printf("main: 0x%x\n", main);
printf("uninitialized_int: 0x%x\n", &uninitialized_int);
printf("initialized_int: 0x%x\n", &initialized_int);
printf("calling recursive function...\n");
rec_call(5);
printf("...done.\n");
buff = malloc(sizeof(char) * ALLOC_SIZE);
printf("32MB malloc() address: 0x%x\n", buff);
free(buff);
printf("strcpy() address: 0x%x\n", strcpy);
printf("write() address: 0x%x\n", write);
}

void rec_call(int count){
if(count > 0){
rec_call(--count);
}
}

result:
$ ./a.out
main: 0x8048454 (1)
uninitialized_int: 0x80497e0 (4)
initialized_int: 0x80497d8 (5)
calling recursive function...
...done.
32MB malloc() address: 0xb5f34008 (6)
strcpy() address: 0x8048364 (7)
write() address: 0x8048334 (8)

GDB result:
$ gdb ./a.out
GNU gdb Red Hat Linux (6.5-15.fc6rh)
Copyright (C) 2006 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "i386-redhat-linux-gnu"...Using host libthread_db library "/lib/libthread_db.so.1".

(gdb) b main
Breakpoint 1 at 0x8048465: file HWA.c, line 14.
(gdb) run
Starting program: /home/morimori/SS/06/a.out

Breakpoint 1, main () at HWA.c:14
14 printf("main: 0x%x\n", main);
(gdb) info f
Stack level 0, frame at 0xbff57f30 (2):
eip = 0x8048465 in main (HWA.c:14); saved eip 0xbcff2c
source language c.
Arglist at 0xbff57f28, args:
Locals at 0xbff57f28, Previous frame's sp at 0xbff57f24
Saved registers:
ebp at 0xbff57f28, eip at 0xbff57f2c
(gdb) b rec_call
Breakpoint 2 at 0x8048529: file HWA.c, line 28.
(gdb) c
Continuing.
main: 0x8048454
uninitialized_int: 0x80497e0
initialized_int: 0x80497d8
calling recursive function...

Breakpoint 2, rec_call (count=5) at HWA.c:28
28 if(count > 0){
(gdb) c
Continuing.

Breakpoint 2, rec_call (count=4) at HWA.c:28
28 if(count > 0){
(gdb) c
Continuing.

Breakpoint 2, rec_call (count=3) at HWA.c:28
28 if(count > 0){
(gdb) c
Continuing.

Breakpoint 2, rec_call (count=2) at HWA.c:28
28 if(count > 0){
(gdb) c
Continuing.

Breakpoint 2, rec_call (count=1) at HWA.c:28
28 if(count > 0){
(gdb) c
Continuing.

Breakpoint 2, rec_call (count=0) at HWA.c:28
28 if(count > 0){
(gdb) info f
Stack level 0, frame at 0xbfbac324 (3):
eip = 0x8048529 in rec_call (HWA.c:28); saved eip 0x804853e
called by frame at 0xbfbac330
source language c.
Arglist at 0xbfbac31c, args: count=0
Locals at 0xbfbac31c, Previous frame's sp is 0xbfbac324
Saved registers:
ebp at 0xbfbac31c, eip at 0xbfbac320

B:Mac OS Xの場合
カーネルアドレススペース(32bit,PowerPC, Mac OS X 10.4 Mac OS X Internals pp.910 TABLE 8-3)

0x00000000-0x00004fff : Exception vectors and low-memory code
0x00005000-0x00005fff: Low-memory globals
0x00006000-0x00006fff: Low-memory shared page used for low-level debugging
0x00007000-0x0000dfff: Boot processor interrupt and debug stacks
0x0000e000-0x0fffffff: Kernel code and data
0x10000000-0xdfffffff: Physical memory window
0xe0000000-0xffffffff: User memory window

ユーザアドレススペース(Mac OS X Internals pp.910-911 TABLE 8-4)
0x00000000-0x00001000: So-called zero page(__PAGEZERO)--inaccessible by default so that dereferencing a NULL pointer(including small offsets from a NULL pointer) causes a protection fault
0x00001000-0x8fdfffff: Application address range(about 2.3GB)
0x8fe00000-0x8fffffff: Space reserved exclusively for Apple system libraries; e.g., the dynamic linker's text segment, mapped starting at 0x8fe00000
0x90000000-0x9fffffff: Global shared text segment, reserved exclusively for Apple system libraries; e.g., the system library's text segment, mapped starting at 0x90000000
0xa0000000-0xafffffff: Global shared data segment, reserved exclusively for Apple system libraries; e.g., the system library's data segment, mapped starting at 0xa0000000
0xb0000000-0xbfffffff: Preferred address range for the application's main thread
0xc0000000-0xebffffff: Additional space available for third-party applications and framework code
0xf0000000-0xfdffffff: Range preferred for use by additional thread stacks, although applications may use this range as necessary
0xfe000000-0xffbfffff: Range reserved for use by the pasteboard and other system services; not to be used by user programs
0xffc00000-0xfffdffff: Range preferred for use by other system services, although applications may use this range as necessary
0xfffe0000-0xffff7fff: Range reserved for use by system services and not to be used by user programs; e.g., a portion of the address range starting at 0xfffec000 is used by the Objective-C library as a commpage for optimizing message dispatch
0xffff8000-0xffffefff: System-shared commpage(seven pages)
0xfffff000-0xffffffff: Last page of a 32-bit address space; cannot be mapped by the Mack VM subsystem

1.メモリマップを調べた限りでは,スタックフレームとヒープのアドレスは分からなかったので,プログラムを書いて推測した.


source:
#include

void func();

int main(){
char *c, *c2;
c = malloc(sizeof(char));
c2 = malloc(sizeof(char));
printf("heap c: 0x%x\n", c);
printf("heap c2: 0x%x\n", c2);
func();
free(c);
free(c2);
printf("Hello, world.\n");
}

void func(){
int tmp;
tmp = 1;
}


result:
$ ./a.out
heap c: 0x3000f0
heap c2: 0x300100
Hello, world.


$ gdb ./a.out
GNU gdb 6.3.50-20050815 (Apple version gdb-563) (Wed Jul 19 05:10:58 GMT 2006)
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "i386-apple-darwin"...Reading symbols for shared libraries .. done

(gdb) b main
Breakpoint 1 at 0x1efa: file ./hello.c, line 7.
(gdb) run
Starting program: /Users/mmori/tmp/a.out
Reading symbols for shared libraries . done

Breakpoint 1, main () at ./hello.c:7
7 c = malloc(sizeof(char));
(gdb) info f
Stack level 0, frame at 0xbffffa50:
eip = 0x1efa in main (./hello.c:7); saved eip 0x1ed2
source language c.
Arglist at 0xbffffa48, args:
Locals at 0xbffffa48, Previous frame's sp is 0xbffffa50
Saved registers:
ebx at 0xbffffa44, ebp at 0xbffffa48, eip at 0xbffffa4c
(gdb) b func
Breakpoint 2 at 0x1f77: file ./hello.c, line 19.
(gdb) c
Continuing.
heap c: 0x3000f0
heap c2: 0x300100

Breakpoint 2, func () at ./hello.c:19
19 tmp = 1;
(gdb) info f
Stack level 0, frame at 0xbffffa20:
eip = 0x1f77 in func (./hello.c:19); saved eip 0x1f47
called by frame at 0xbffffa50
source language c.
Arglist at 0xbffffa18, args:
Locals at 0xbffffa18, Previous frame's sp is 0xbffffa20
Saved registers:
ebp at 0xbffffa18, eip at 0xbffffa1c
(gdb) c
Continuing.
Hello, world.

Program exited with code 016.


実行結果から,ヒープの開始アドレスは0x3000f0か,それよりも手前から下方向にのびていくことが分かる.
また,スタックフレームは,0xbffffa50から,上方向にのびていることがわかる.
スタックとヒープの間の距離は,0xbfcff960,すなわち10進で3218078048,3068MBとなる.

2.GCCでは,通常明示的にstaticオプションを付けない限りはshared libraryとしてコンパイルされる.そのため,今回使用したプログラムは全てshared libraryである.

2. Extend your project proposal to answer the questions above.

調査内容: Apacheのログファイルが2GBを超えた際に,システムのLoadが非常に高くなるのはなぜか調べる.
詳細: Redhat系Linuxで,Apache 2.0系を利用してサーバを運用していた際,ログファイルaccess_logのファイルサイズが2GBを超えた時点で極端にシステムの負荷が高くなった.恐らくEXT3ファイルシステムの問題か何かであると予想されるが,この原因について調査する.

Output: システム負荷増大の原因と,その対策
Midterm Milestones: 実験環境の構築と再現性の確認
Equipment and Skills: サーバ構築,及びファイルシステムに関する技術.必要であればソースコードを参照することで原因を調査したい
What will you learn if the project is successful? : ファイルシステムに関する動作の詳細,及び実際の挙動を知ることができる
What will you learn if the project fails? : システム障害の原因を辿るプロセスを学ぶことができる.

1 件のコメント:

rdv さんのコメント...

1. memory map: good initiative to find a map online, but I expected
you to build more of the map yourself and integrate it into a
picture.
2. revised proposal: this is still very vague.
* What variables do you intend to measure? You mention that you
think it might have something to do with ext3, but how do you
intend to either prove or disprove that hypothesis? strace? just
by reading the access logs? do you have a tool to generate load on
the Apache server, or are you just going to wait for real-world
activity? *be specific*.

Score: 7/10