Apache MPM worker ã® pmap ãåãããã¨ãã話ãã Linux pthread (NPTL) ã®ã¹ã¿ãã¯ãµã¤ãºã¨ã¬ã¼ãé åã¾ã§
ã²ãããªãã¨ãã 32bit ã«ã¼ãã«ã§åãã¦ãã Apache (MPM㯠worker = ãã«ãã¹ã¬ãã) ã /usr/bin/pmap ã§èª¿ã¹ã¦ãã¾ããã調ã¹ã¦ããä¸ã§ pthread ã®ã¹ã¿ãã¯ã®å²å½ãæ¹ã«ãèå³ããããã®ã§ glibc ãªã©ã深追ããã¦èª¿ã¹ã¾ããã
以éã®å 容ã¯æ¬¡ã®ç°å¢ã§èª¿ã¹ãå 容ã§ãã
pmap 㧠[anon] ãä¸æ¯ã§ã¦ãã
worker ããã»ã¹ã® pmapãåãã¨ä¸å®ãµã¤ãºã® [anon] ãé£ç¶ãã¦åºã¦ããã®ã¯ãªãã ã£ãã㪠? ã¨ã
- /usr/bin/pmap
ã®åºå
# 説æã®ããã« pmap ã®åºåãä¸é¨çç¥ b23de000 4K ----- [ anon ] b23df000 10240K rw--- [ anon ] b2ddf000 4K ----- [ anon ] b2de0000 10240K rw--- [ anon ] b37e0000 4K ----- [ anon ] b37e1000 10240K rw--- [ anon ] b41e1000 4K ----- [ anon ] b41e2000 10240K rw--- [ anon ] b4be2000 4K ----- [ anon ] b4be3000 10240K rw--- [ anon ] b55e3000 4K ----- [ anon ] b55e4000 10240K rw--- [ anon ] b5fe4000 4K ----- [ anon ] b5fe5000 10240K rw--- [ anon ] b69e5000 4K ----- [ anon ] b69e6000 10240K rw--- [ anon ] b73e6000 4K ----- [ anon ] b73e7000 10240K rw--- [ anon ] b7de7000 244K rw-s- /dev/zero (deleted) b7e24000 504K rw-s- /dev/zero (deleted) b7ea2000 520K rw--- [ anon ] b7f24000 100K rw-s- /dev/zero (deleted) b7f3d000 28K rw--- [ anon ] bf865000 84K rw--- [ stack ]
10240KB ⦠4kB ... 10240KB ... 4KB ã® [anon] (Anoymous memory region = ç¡åã¡ã¢ãªãªã¼ã¸ã§ã³) ãé£ãªã£ã¦ãã¾ã
ã¹ã¬ããã®ã¹ã¿ãã¯ã ã£ã
http://mail-archives.apache.org/mod_mbox/httpd-dev/200710.mbox/%[email protected]%3E
ä¸è¨ML㧠Apache ã® ThreadStackSize è¨å®ãå¤æ´ãã pmap ã®åºåãæ稿ããã¦ãã¾ãããããã 10240KB [anon] ã®ãªã¼ã¸ã§ã³ã¯ã¹ã¬ãããã¨ã«ç¨æãããã¹ã¿ãã¯ã®ã¡ã¢ãªãªã¼ã¸ã§ã³ã ã¨åããã¾ãããApache ã® MPM ã worker ã ã¨ã¹ã¬ãããçããã¾ãããã
ThreadStackSize ã å¤æ´ãã¦ã¿ã
ã¹ã¿ãã¯ã®ãµã¤ãºã¯ httpd.conf 㧠ThreadStackSize ãæå®ãããã¨ã§å¤æ´ã§ãã¾ããé©å½ã« 2MBã«ãã¦ã¿ã¾ãã
- /etc/httpd/conf/httpd.conf
# ã¹ã¿ãã¯ã®ãµã¤ãºã¯ bytes æå® ThreadStackSize 2097152
- /usr/bin/pmap
ã®åºå
# 説æã®ããã« pmap ã®åºåãä¸é¨çç¥ b6e8f000 4K ----- [ anon ] b6e90000 2048K rw--- [ anon ] b7090000 4K ----- [ anon ] b7091000 2048K rw--- [ anon ] b7291000 4K ----- [ anon ] b7292000 2048K rw--- [ anon ] b7492000 4K ----- [ anon ] b7493000 2048K rw--- [ anon ] b7693000 4K ----- [ anon ] b7694000 2048K rw--- [ anon ] b7894000 4K ----- [ anon ] b7895000 2048K rw--- [ anon ] b7a95000 4K ----- [ anon ] b7a96000 2048K rw--- [ anon ] b7c96000 4K ----- [ anon ] b7c97000 2048K rw--- [ anon ] b7e97000 244K rw-s- /dev/zero (deleted) b7ed4000 504K rw-s- /dev/zero (deleted) b7f52000 520K rw--- [ anon ] b7fd4000 100K rw-s- /dev/zero (deleted) b7fed000 28K rw--- [ anon ] bfcc2000 84K rw--- [ stack ]
10MB (10240 KB) ãã -> 2M(2048 KB) ã«å¤ãã£ãã®ã確èªã§ãã¾ããã
ãããã㯠pthread ã®è©±
Apacheã®è©±ã¯ä¸æ¦ä¼æ©ã
ã¹ã¿ãã¯ã®ãµã¤ãºãå¤æ´ããå®è£ ãã©ããªã£ã¦ãããæ°ã«ãªã£ãã®ã§ pthread å¨ãããã深追ããã¾ãããLinux ã®å ´åã¯ãApache ãå©ç¨ãã¦ããã¹ã¬ããå®è£ 㯠NPTL = Native POSIX Thread Library ã§ããã§ããã
$ getconf GNU_LIBPTHREAD_VERSION NPTL 2.5 # http://orz.makegumi.jp/archives/1258430.html ã§ã³ãã³ããç¥ãã¾ãã
( LinuxThreads ãªã©ä»ã®å®è£
ã«ã¤ãã¦ã¯ã¡ãã£ã¨åããã¾ãã :q )
è¬ã®ãªã¼ã¸ã§ã³
å ã»ã©ã® pmap ã§è¡¨ç¤ºããã 10240KB ... 4KB ... 10240KB ... 4KB ... ã¨ãã並ã³ã® 4KB ã®é¨åãæ°ã«ãªã£ãã®ã§ãå½¹å²ã調ã¹ã¾ãã
b572b000 4 - - - ----- [ anon ] # ãã㤠b572c000 10240 - - - rw--- [ anon ]
pthread_attr_getguardsize(3) ã«è§£èª¬ãã®ã£ã¦ãã¾ãããã¬ã¼ãé å ( guard area ) ã¨å¼ã¶ããã§ã
ã¬ã¼ãé åã¯ãèªã¿åºã/æ¸ãè¾¼ã¿ã¢ã¯ã»ã¹ãè¡ãããªãããã«ä¿è·ããã ãããä»®æ³ã¡ã¢ãªãã¼ã¸ã§æ§æã§æ§æããããã¹ã¬ãããã¹ã¿ãã¯ãã¬ã¼ã é åã¾ã§ãªã¼ãã¼ããã¼ãããå ´åãã»ã¨ãã©ã®ãã¼ãã¦ã§ã¢ã¢ã¼ããã¯ã㣠ã§ã¯ãã¹ã¬ããã« SIGSEGV ã·ã°ãã«ãéããããªã¼ãã¼ããã¼ãçºçãã ãã¨ãéç¥ãããã
ã¹ã¿ãã¯ã®ã¡ã¢ãªãªã¼ã¸ã§ã³ã®å±æ§ã« rw (èªã¿æ¸ã) ãã¤ãã¦ããã®ã«å¯¾ãã¦ãã¬ã¼ãé åã¯å±æ§ãã¤ãã¦ãã¾ãããããã»ã¹ãã¬ã¼ãé åã®ã¢ãã¬ã¹ã«ã¢ã¯ã»ã¹ããã¨ãã«ã¼ãã«ã以ä¸ã®æ§ã«å¦çããã¯ãã§ã
- 1. ã¬ã¼ãé åã®ã¡ã¢ãªãªã¼ã¸ã§ã³ã«ã¯ãã¼ã¸ãã¬ã¼ã ãå²ãå½ã¦ããã¦ããªã
- 2. ããã»ã¹ãã¢ã¯ã»ã¹ããã¨ãã¼ã¸ãã©ã«ããçºç
- 3. èªã¿/æ¸ã/å®è¡ã許å¯ãããªããªã¼ã¸ã§ã³ã§ã®ãã¼ã¸ãã©ã«ããªã®ã§ã»ã°ã¡ã³ãã¼ã·ã§ã³ãã©ã«ãã¨ãã¦æ±ããã
- 4. ããã»ã¹ã« SIGSEGV ãé£ã¶
ãããã¦ã¹ã¿ãã¯ãªã¼ãã¼ããã¼ã®ã¬ã¼ã ã¨ãã¦åãã®ã§ããã(詳ãããã¨ã¯ã詳解Linuxã«ã¼ãã«ããªã©ãããã£ã¦ãã ãã )
pthread 㧠ã¹ã¿ãã¯ã®ãµã¤ãºã¨ã¬ã¼ãé åã®ãµã¤ãºãå¤ãã
ã¹ã¿ãã¯ã®ãµã¤ãºã¨ã¬ã¼ãé åã®ãµã¤ãºãå¤æ´ãããå ´åã¯ãpthread ã® pthread_attr_setstacksize(3), pthread_attr_setguardsize(3) ã使ã£ã¦å¤æ´ã§ãããã¨ãåããã¾ããã
åä½ã確ãããããã«ãä¸è¨ã®æ§ãªã³ã¼ãã§ã¹ã¿ãã¯ãµã¤ãºã¨ã¬ã¼ãé åã®ãµã¤ãºãå¤æ´ããªãã pmap ãããããåã£ã¦ã¿ã¾ããã (64bit ã«ã¼ãã«ã®ããã»ã¹ã®ã¡ã¢ãªã¬ã¤ã¢ã¦ããããç¥ããªãã®ã§32bit ã«ã¼ãã«ã§è©¦ãã¦ãã¾ã)
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <err.h> #include <errno.h> #include <limits.h> #include <pthread.h> #define NUM_THREADS 10 void * do_nothing(void *arg) { pause(); return NULL; } int main(int argc, char *argv[]) { if (argc != 3) { errx(1, "usage: %s <page frames for stack> <page frames for guard>", argv[0]); } size_t stack_size = sysconf(_SC_PAGESIZE) * atoi(argv[1]); size_t guard_size = sysconf(_SC_PAGESIZE) * atoi(argv[2]); /** * ã¹ã¿ãã¯ãµã¤ãºã PTHREAD_STACK_MIN ããå°ãã㨠* pthread_attr_setstacksize ã EINVAL - invalid argument ãè¿ã **/ if (stack_size < PTHREAD_STACK_MIN) { errx(1, "stack size must be greater than PTHREAD_STACK_MIN (%d bytes)", PTHREAD_STACK_MIN); } pthread_attr_t attribute; int status = pthread_attr_init(&attribute); if(status != 0) { errx(1, "pthread_attr_init: %s", strerror(status)); } status = pthread_attr_setstacksize(&attribute, stack_size); if(status != 0) { errx(1, "pthread_attr_setstacksize: %s", strerror(status)); } status = pthread_attr_setguardsize(&attribute, guard_size); if(status != 0) { errx(1, "pthread_attr_setguardsize: %s", strerror(status)); } status = pthread_attr_getstacksize(&attribute, &stack_size); if(status != 0) { errx(1, "pthread_attr_getstacksize: %s", strerror(status)); } status = pthread_attr_getguardsize(&attribute, &guard_size); if(status != 0) { errx(1, "pthread_attr_getguardsize: %s", strerror(status)); } printf("stack_size: %zd\nguard_size: %zd\n", stack_size, guard_size); pthread_t thread[NUM_THREADS]; for (int i = 0; i < NUM_THREADS; i++) { status = pthread_create(&thread[i], &attribute, do_nothing, NULL); if(status != 0) { errx(1, "pthread_create: %s",strerror(status)); } } char shell_pmap[128]; snprintf(shell_pmap, sizeof(shell_pmap), "/usr/bin/pmap %d", getpid()); system(shell_pmap); exit(0); }
$ gcc pmap_of_pthread.c -o pmap_of_pthraed -pthread -std=gnu99 -W -Wall -Wno-unused-parameter
- ãã¼ã¸ãã¬ã¼ã æ°ã§ã¹ã¿ãã¯ã¨ã¬ã¼ãé åã®ãµã¤ãºãæå®ãã¾ã
[usage] ./pmap_of_pthraed <page frames for stack> <page frames for guard>
ãªãã¹ã¬ããã®ã¹ã¿ãã¯ã¯ PTHREAD_STACK_MIN ãã大ãããµã¤ãºãæå®ããå¿
è¦ãããã¾ããããããå°ããå ´å㯠EINVAL ãè¿ãã¾ãã
ã¹ã¿ãã¯ãµã¤ãºã 100KB , ã¬ã¼ãé åã 4KB ã«ããå ´å
$ ./pmap_of_pthraed 25 1 stack_size: 102400 guard_size: 4096 4442: ./pmap_of_pthraed 25 1 00224000 108K r-x-- /lib/ld-2.5.so 0023f000 4K r-x-- /lib/ld-2.5.so 00240000 4K rwx-- /lib/ld-2.5.so 006b8000 1372K r-x-- /lib/libc-2.5.so 0080f000 8K r-x-- /lib/libc-2.5.so 00811000 4K rwx-- /lib/libc-2.5.so 00812000 12K rwx-- [ anon ] 008b0000 4K r-x-- [ anon ] 00d37000 88K r-x-- /lib/libpthread-2.5.so 00d4d000 4K r-x-- /lib/libpthread-2.5.so 00d4e000 4K rwx-- /lib/libpthread-2.5.so 00d4f000 8K rwx-- [ anon ] 08048000 4K r-x-- /root/pmap_of_pthraed 08049000 4K rw--- /root/pmap_of_pthraed 08491000 132K rw--- [ anon ] b7e93000 4K ----- [ anon ] b7e94000 96K rw--- [ anon ] b7eac000 4K ----- [ anon ] b7ead000 96K rw--- [ anon ] b7ec5000 4K ----- [ anon ] b7ec6000 96K rw--- [ anon ] b7ede000 4K ----- [ anon ] b7edf000 96K rw--- [ anon ] b7ef7000 4K ----- [ anon ] b7ef8000 96K rw--- [ anon ] b7f10000 4K ----- [ anon ] b7f11000 96K rw--- [ anon ] b7f29000 4K ----- [ anon ] b7f2a000 96K rw--- [ anon ] b7f42000 4K ----- [ anon ] b7f43000 96K rw--- [ anon ] b7f5b000 4K ----- [ anon ] # ã¬ã¼ã b7f5c000 96K rw--- [ anon ] # ã¹ã¿ã㯠96KB ? b7f74000 4K ----- [ anon ] # ã¬ã¼ã b7f75000 104K rw--- [ anon ] b7f96000 4K rw--- [ anon ] bfd7e000 84K rw--- [ stack ] total 2856K
ã¹ã¿ãã¯ã®ãµã¤ãºã 100KB ã¨æå®ãã¦ããã®ã« pmap ãåã㨠96K ã«ãªã£ã¡ãã£ã¦ã¾ããééã£ãã³ã¼ããæ¸ããã®ãã¨æã£ããã©ããã glibc ã®å®è£ ãã°ãããããã§ã
ãã° glibc 2.8 ã®æç¹ã§ã¯ã NPTL ã¹ã¬ããå®è£ ã§ã¯ã¬ã¼ãé åã¯ã¹ã¿ãã¯ãµã¤ãº ã§å²ãå½ã¦ãããé åã®ä¸ã«å«ã¾ãã¦ãããä¸æ¹ãPOSIX.1 ã§ã¯ãã¹ã¿ãã¯ã® æ«å°¾ã«è¿½å ã®é åãå²ãå½ã¦ããã¨ãæ±ãããã¦ãã
Man page of PTHREAD_ATTR_SETSTACKSIZE ããå¼ç¨
ã¨ããã®ã§ãã SL6 glibc-2.12-1 ã§è©¦ãã¦ã¿ã¦ãåãã¬ã¤ã¢ã¦ãã«ãªãã¾ãããåãããªã
ã¹ã¿ãã¯ãµã¤ãºã 100KB , ã¬ã¼ãé åã 8KB ã«ããå ´å
./pmap_of_pthraed 25 2 stack_size: 102400 guard_size: 8192 4454: ./pmap_of_pthraed 25 2 00264000 1372K r-x-- /lib/libc-2.5.so 003bb000 8K r-x-- /lib/libc-2.5.so 003bd000 4K rwx-- /lib/libc-2.5.so 003be000 12K rwx-- [ anon ] 00513000 108K r-x-- /lib/ld-2.5.so 0052e000 4K r-x-- /lib/ld-2.5.so 0052f000 4K rwx-- /lib/ld-2.5.so 00675000 4K r-x-- [ anon ] 0087c000 88K r-x-- /lib/libpthread-2.5.so 00892000 4K r-x-- /lib/libpthread-2.5.so 00893000 4K rwx-- /lib/libpthread-2.5.so 00894000 8K rwx-- [ anon ] 08048000 4K r-x-- /root/pmap_of_pthraed 08049000 4K rw--- /root/pmap_of_pthraed 08a21000 132K rw--- [ anon ] b7eb1000 8K ----- [ anon ] b7eb3000 92K rw--- [ anon ] b7eca000 8K ----- [ anon ] b7ecc000 92K rw--- [ anon ] b7ee3000 8K ----- [ anon ] b7ee5000 92K rw--- [ anon ] b7efc000 8K ----- [ anon ] b7efe000 92K rw--- [ anon ] b7f15000 8K ----- [ anon ] b7f17000 92K rw--- [ anon ] b7f2e000 8K ----- [ anon ] b7f30000 92K rw--- [ anon ] b7f47000 8K ----- [ anon ] b7f49000 92K rw--- [ anon ] b7f60000 8K ----- [ anon ] b7f62000 92K rw--- [ anon ] b7f79000 8K ----- [ anon ] b7f7b000 92K rw--- [ anon ] b7f92000 8K ----- [ anon ] b7f94000 100K rw--- [ anon ] b7fb4000 4K rw--- [ anon ] bf94f000 84K rw--- [ stack ] total 2856K
ã¹ã¿ãã¯ãµã¤ãºã 92KB, ã¬ã¼ãé åã 8KB ã«ãªã£ã¦ãã¾ããã
ã¹ã¿ãã¯ãµã¤ãºã 100KB , ã¬ã¼ãé åã 0KB ã«ããå ´å
./pmap_of_pthraed 25 0 stack_size: 102400 guard_size: 0 4468: ./pmap_of_pthraed 25 0 00157000 1372K r-x-- /lib/libc-2.5.so 002ae000 8K r-x-- /lib/libc-2.5.so 002b0000 4K rwx-- /lib/libc-2.5.so 002b1000 12K rwx-- [ anon ] 002d0000 108K r-x-- /lib/ld-2.5.so 002eb000 4K r-x-- /lib/ld-2.5.so 002ec000 4K rwx-- /lib/ld-2.5.so 005f8000 4K r-x-- [ anon ] 00cb6000 88K r-x-- /lib/libpthread-2.5.so 00ccc000 4K r-x-- /lib/libpthread-2.5.so 00ccd000 4K rwx-- /lib/libpthread-2.5.so 00cce000 8K rwx-- [ anon ] 08048000 4K r-x-- /root/pmap_of_pthraed 08049000 4K rw--- /root/pmap_of_pthraed 09996000 132K rw--- [ anon ] b7ef2000 1008K rw--- [ anon ] # å ¨ä½ãã¹ã¿ã㯠b7ff5000 4K rw--- [ anon ] bfb8d000 84K rw--- [ stack ] total 2856K
ã¬ã¼ãé åããªãå ´åã¯ãã¹ã¿ãã¯ã®ãªã¼ã¸ã§ã³ã1åã ã確ä¿ãããããã«ãªãã¾ããã
ã¬ã¼ãé åã¯ã©ã®ããã«ä½æãããã®ã
ã¬ã¼ãé åãã©ã®ããã«ç¢ºä¿ããã¦ããã®ã glibc ã®ã½ã¼ã¹ãè¦ã¦ã¿ã¾ããã
- glibc-2.5/nptl/allocatestack.c
static int allocate_stack (const struct pthread_attr *attr, struct pthread **pdp, ALLOCATE_STACK_PARMS) { /* ç¥ */ mem = mmap (NULL, size, prot, MAP_PRIVATE | MAP_ANONYMOUS | ARCH_MAP_FLAGS, -1, 0); /* ç¥ */ if (mprotect (guard, guardsize, PROT_NONE) != 0) {
mmap(2) ã§ç¢ºä¿ãããªã¼ã¸ã§ã³ã mprotect(2) 㧠PROT_NONE å±æ§ãæå®ããäºã§ èªã¿/æ¸ã/å®è¡ä¸å¯è½ãªãªã¼ã¸ã§ã³ = ã¬ã¼ãé åã¨ããããã§ããã¬ã¼ãé åã¯ã«ã¼ãã«ã管çãããã®ã§ã¯ãªãã¦ãã¹ã¬ããã©ã¤ãã©ãªãèªåã§ç¨æãã¦ç®¡çãããã®ã¨åããã¾ããã
Apache ã®è©±ã«æ»ãã¾ã
æå¾ã« Apache ã® ThreadStackSize ã®è¨å®ã¨ pthread API ãç¹ãã¦ããé¨åã®ã½ã¼ã¹ãããã¦ããã¾ã
- httpd-2.2.24/server/core.c
#ifdef AP_MPM_WANT_SET_STACKSIZE AP_INIT_TAKE1("ThreadStackSize", ap_mpm_set_thread_stacksize, NULL, RSRC_CONF, "Size in bytes of stack used by threads handling client connections"), #endif
- httpd-2.2.24/server/mpm_common.c
apr_size_t ap_thread_stacksize = 0; /* use system default */ const char *ap_mpm_set_thread_stacksize(cmd_parms *cmd, void *dummy, const char *arg) { long value; const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY); if (err != NULL) { return err; } value = strtol(arg, NULL, 0); if (value < 0 || errno == ERANGE) return apr_pstrcat(cmd->pool, "Invalid ThreadStackSize value: ", arg, NULL); ap_thread_stacksize = (apr_size_t)value; return NULL; }
ããã¯è¨å®ãã¡ã¤ã«ããå¤èªã¿åã£ã¦å é¨ã®å½¢å¼ã«å¤æããé¨åã
- httpd-2.2.24/srclib/apr/threadproc/unix/thread.c
APR_DECLARE(apr_status_t) apr_threadattr_stacksize_set(apr_threadattr_t *attr, apr_size_t stacksize) { int stat; stat = pthread_attr_setstacksize(&attr->attr, stacksize); if (stat == 0) { return APR_SUCCESS; } #ifdef HAVE_ZOS_PTHREADS stat = errno; #endif return stat; } APR_DECLARE(apr_status_t) apr_threadattr_guardsize_set(apr_threadattr_t *attr, apr_size_t size) { #ifdef HAVE_PTHREAD_ATTR_SETGUARDSIZE apr_status_t rv; rv = pthread_attr_setguardsize(&attr->attr, size); if (rv == 0) { return APR_SUCCESS; } #ifdef HAVE_ZOS_PTHREADS rv = errno; #endif return rv; #else return APR_ENOTIMPL; #endif }
pthread_attr_setstacksize, pthread_attr_setguardsize ããã ã©ãããã¦ããå®è£
ã§ãããããã¾ã§èªãã ã調ã¹ããã¨ãå
¨é¨ç¹ãã£ã¦ãã£ããã§ãã
ã¾ã¨ã
ã¹ã¬ããã«é¢ä¿ãã詳ããæåã追ãã«ã¯ä½ãã¬ã¤ã¤ã®ã©ã¤ãã©ãªãã·ã¹ãã ã³ã¼ã«ãã«ã¼ãã«ã®ç解ãå¿
è¦ã§LLè³ã«ã¯ã ãã¶å¤§å¤ã§ããã