Linux ã®ããã»ã¹ã Copy on Write ã§å ±æãã¦ããã¡ã¢ãªã®ãµã¤ãºã調ã¹ã
Linux 㯠fork ã§åããã»ã¹ãä½æããå ´åã親ã®ä»®æ³ã¡ã¢ãªç©ºéã®å 容ãåã¸ã³ãã¼ããå¿ è¦ãããã¾ãããããã¾ã¨ãã«å ¨ç©ºéãã³ãã¼ãã¦ããã®ã§ã¯ fork ã®ã³ã¹ããé«ããªã£ã¦ãã¾ãã¾ãããåã親ã¨åããããªããã»ã¹ã¨ãã¦åä½ãç¶ããå ´åã¯ãå 容ã®éè¤ãããã¼ã¸ãå¤æ°ã§ãã¦ãã¾ããå¹çãããããã¾ããã
ããã§ãLinux ã®ä»®æ³ã¡ã¢ãªã¯ãã¡ã¢ãªç©ºéãèãã¦ã³ãã¼ããã®ã§ã¯ãªããã¯ããã¯è¦ªåã§ã¡ã¢ãªé åãå ±æãã¦ããã¦ãæ¸ãè¾¼ã¿ããã£ãæç¹ã§ããã®æ¸ãè¾¼ã¿ã®ãã£ããã¼ã¸ã ãã親åã§åå¥ã«æã¤ã¨ããä»çµã¿ã§ãã®åé¡ãåé¿ãã¾ããCopy-On-Write (CoW) ã¨å¼ã°ããæ¦ç¥ã§ããå ±æã¡ã¢ãªãã¼ã¸ã¯ã親åããããã®ä»®æ³ã¡ã¢ãªç©ºéãåä¸ã®ç©çã¡ã¢ãªã«ãããã³ã°ãããã¨ã§å®ç¾ããã¾ãããã詳ãã㯠コピーオンライト - Wikipedia ãªã©ãåç §ãã¦ãã ããã
ãã® CoW ã«ãã親åã§ã®ã¡ã¢ãªã®å ±æã¯ã¡ã¢ãªãå¤ãå¿ è¦ã¨ããããã»ã¹ãå¤æ°çæãããããªããã°ã©ã ãåããå ´åã«ç¹ã«éè¦ã§ããmod_perl 㧠Perl ã¦ã§ãã¢ããªã±ã¼ã·ã§ã³ãåããå ´åãããã㯠FastCGI ã§ã¹ã¯ãªããè¨èªã§æ¸ãããã¢ããªã±ã¼ã·ã§ã³ã常é§ãããå ´åãªã©ãé¡èãªä¾ã§ãã
ä¾ãã° mod_perl ã®å ´åãMaxClients ã®è¨å®ã«å ±æé åã®ãµã¤ãºãèæ ®ããå¿ è¦ãããã¾ãããã®è¾ºãã¯ç«¹è¿«ããã«ãã 2003 å¹´ã® Shibuya.pm ã®çºè¡¨è³æã詳ããã§ãã
- mod_perl ã«ããã C10K Problem
- http://shibuya.pm.org/slides/200310/takesako.ppt (ppt)
4å¹´ã¨ã¡ãã£ã¨åã® Shibuya.pm ã§ãã4å¹´åã«èãã話ãä»ã«ãªã£ã¦æãèµ·ããã¦ããã¨ã¯ãæãªããé²æ©ãããã®ããªãã®ãã
ãã¨ããä»æ¥ãã¾ãã¾ããã»ã¹ã®ã¡ã¢ãªç©ºéä¸ã® CoW ã§å ±æããã¦ããé åãã©ã®ç¨åº¦ããããè¨æ¸¬ããæ¹æ³ã調ã¹ã¦ã¿ãã®ã§ãããäºæ³ã«åãã¦ãps ãªã©ã®ã¦ã¼ãã£ãªãã£ã§ç°¡åã«èª¿ã¹ãæ¹æ³ãè¦ã¤ãããã¾ããã§ããã(ããã°ã©ã ãç´æ¥å¤æ´ã§ããã®ã§ããã° libgtop ã Perl ã® GTop ã使ãæãããã¾ãã) çµå± Google ãã調ã¹ã¦ /proc/PID/smaps ã調ã¹ãã°è¯ãã¨ãããã¨ããããã¾ãããhttp://www.typemiss.net/blog/kounoike/20060202-61 ã大å¤åèã«ãªãã¾ããã
/proc/PID/smaps ã§ã¯ä»®æ³ã¡ã¢ãªç©ºéã®åã¢ãã¬ã¹ã«ãããã³ã°ãããé åã®ç¶æ ä¸è¦§ãåç §ãããã¨ãã§ãã¾ãã
% cat /proc/12225/smaps| head 08048000-080bb000 r-xp 00000000 75:00 65545 /bin/zsh4 Size: 460 kB Rss: 460 kB Shared_Clean: 460 kB Shared_Dirty: 0 kB Private_Clean: 0 kB Private_Dirty: 0 kB Referenced: 460 kB 080bb000-080be000 rw-p 00073000 75:00 65545 /bin/zsh4 Size: 12 kB
ãã® smaps ã«ããåé åã®ãµã¤ãºã®ãã¡ãShared_Clean 㨠Shared_Dirty ã®ãµã¤ãºãéãã¦åè¨ããã°ããã®ããã»ã¹ãä»ããã»ã¹ã¨å ±æãã¦ããã¡ã¢ãªã®ãµã¤ãºããããã¾ããsmaps 㯠man proc ã«ããã¨ãVanilla ã«ã¼ãã« 2.6.14 ããå©ç¨å¯è½ã ããã§ãã
Perl ã«ã¯ Linux::Smaps ã¨ãã /proc/PID/smaps ã®ãã¼ã¿ãããã°ã©ããã«ã«æ±ããã¢ã¸ã¥ã¼ã«ãããã¾ããããã使ã£ã¦ãå ±æé åã®ãµã¤ãºã調ã¹ãç°¡åãªã¹ã¯ãªãããä½ãã¾ããã
#!/usr/bin/env perl use strict; use warnings; use Linux::Smaps; @ARGV or die "usage: %0 [pid ...]"; printf "PID\tRSS\tSHARED\n"; for my $pid (@ARGV) { my $map = Linux::Smaps->new($pid); unless ($map) { warn $!; next; } printf "%d\t%d\t%d (%d%%)\n", $pid, $map->rss, $map->shared_dirty + $map->shared_clean, int((($map->shared_dirty + $map->shared_clean) / $map->rss) * 100) }
å¼æ°ã«ä¸ãããã PID ã®ããã»ã¹ã®ãå ±æé åãµã¤ãºã調ã¹ã¦è¡¨ç¤ºãã¾ããä¾ãã° mod_perl çµã¿è¾¼ã¿ã® httpd ã§å®è¡ããã¨
% shared_memory_size.pl `pgrep httpd` PID RSS SHARED 6615 79160 44424 (56%) 6656 78832 43268 (54%) 6657 75680 43436 (57%) 6658 77480 43332 (55%) 6661 77600 43952 (56%) 6665 78452 43952 (56%) ...
ã¨ããçµæãå¾ããã¾ãã50% å¼·ãå ±æé åã§ãã¾ãã¾ãã®çµæã§ã¯ãªããã¨æãã¾ãã
ãã¹ãããã°ã©ã ãåãã㦠/proc/PID/smaps ã®æ§åãè¦ã
ãã¦ã/proc/PID/smaps ã§å ±æã¡ã¢ãªã®ãµã¤ãºãåãã£ãã®ã¯ããã¨ãã¦ãå®é /proc/PID/smaps ã®ãã¼ã¿ã¯ã©ã®ãããªãã¼ã¿ã«ãªã£ã¦ããã®ã§ãããããã«ã¼ãã«ã®å¦çã追ã£ã¦ã¿ããã¨æãã¾ãã
ã¾ãã¯ã試ãã«ãã¹ãç¨ã®ããã°ã©ã ãä½ã£ã¦ããã¼ã¿ã®å¤åãè¦ã¦ã¿ã¾ããã
#include <stdio.h> #include <stdlib.h> #include <unistd.h> enum { BUFSIZE = 1024 * 1000 * 100, // 100MB }; char buf[BUFSIZE]; int main (int argc, char **argv) { for (int i = 0; i < BUFSIZE; i++) buf[i] = 'a'; fprintf(stderr, "PID: %d\n", getpid()); while (1) sleep(100); return 0; }
100MB åã®ãã¼ã¿é å(ãããã¡)ã確ä¿ãã¦ãsleep ããããã°ã©ã ã§ãããªãããããã¡ã®é åã確ä¿ããã ãã 㨠bss ã«å²ãå½ã¦ããã¦ãã¾ãå®ã¡ã¢ãªãæ¶è²»ããªãã®ã§ãèµ·åç´å¾ã«ããã« 100MB åãã¼ã¿ã®æ¸ãè¾¼ã¿ãè¡ã£ã¦ãã¾ãã
ãã®ããã°ã©ã ãåããã¦ããã»ã¹ã® smaps ãè¦ã¦ã¿ã¾ãã
0804a000-0e1f2000 rw-p 0804a000 00:00 0 [heap] Size: 100000 kB Rss: 100000 kB Shared_Clean: 0 kB Shared_Dirty: 0 kB Private_Clean: 0 kB Private_Dirty: 100000 kB Referenced: 100000 kB
調度 100000kB (100MB) ã®é åãããã¾ããããããããã°ã©ã ä¸ã® buf é åã«ç¸å½ããä»®æ³ã¡ã¢ãªé åã§ãã100MB ã®ç©çã¡ã¢ãªé åã¨ãããã³ã°ããã¦ããã®ã§ãRss ã 100000 kB ã§ããPrivate_Dirty ã 100000 kB ã«ãªã£ã¦ããç¹ãé常ã«æ°ã«ãªãã¾ãã
次ã«ããã®ããã°ã©ã å ã§ããã»ã¹ã fork ãã㦠CoW ã§å ±æããé åãã©ããªã£ã¦ãããã確èªãã¾ãã(ã³ã¡ã³ãã¢ã¦ãããç®æã¯ãã¨ã§æå¹ã«ãã¾ãã)
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/types.h> #include <sys/wait.h> enum { BUFSIZE = 1024 * 1000 * 100, // 100MB }; char buf[BUFSIZE]; int main (void) { for (int i = 0; i < BUFSIZE; i++) buf[i] = 'a'; pid_t pid = fork(); if (pid == 0) { /* for (int i = 0; i < BUFSIZE / 2; i++) buf[i] = 'b'; // creating private pages */ while (1) sleep(100); } fprintf(stderr, "parent: %d, child: %d\n", getpid(), (int)pid); wait(NULL); return 0; }
親åã§äºã¤ã®ããã»ã¹ãç«ã¡ä¸ãã£ãå¾ã親㮠smaps ã確èªãã¦ã¿ã¾ãã
0804a000-0e1f2000 rw-p 0804a000 00:00 0 [heap] Size: 100000 kB Rss: 100000 kB Shared_Clean: 0 kB Shared_Dirty: 100000 kB Private_Clean: 0 kB Private_Dirty: 0 kB Referenced: 100000 kB
å ã»ã©ã¯ Private_Dirty ã ã£ã 100000 kB ã®é åããShared_Dirty ã«ãªã£ã¦ããã®ãåããã¾ããããã CoW ã§å ±æãã¦ããé åã§ãããã¨ãæ¨æ¸¬ããã¾ãã
次ã«ãããã°ã©ã ä¸ã®ã³ã¡ã³ãã¢ã¦ãé¨åãæå¹ã«ãã¾ãããã®é¨åãæå¹ã«ããã¨ã親ã¨åã§å ±æããé åã®åå 50MB ã«åãæ¸ãè¾¼ã¿å¦çãè¡ãã¾ããçµæãé åã®ãã¡åå 50MB ã¯è¦ªåã§å¥ã ã®é åã«ãããã³ã°ãå¾å 50MB ã¯ããããå ±æé åã¨ãã¦ãããã³ã°ãããããã«ãªãã¯ãã§ãã
smaps ãè¦ã¦ã¿ã¾ãã
0804a000-0e1f2000 rw-p 0804a000 00:00 0 [heap] Size: 100000 kB Rss: 100000 kB Shared_Clean: 0 kB Shared_Dirty: 50000 kB Private_Clean: 0 kB Private_Dirty: 50000 kB Referenced: 100000 kB
50000 kB (50MB) ã Shared_Dirtyã50000 kB (50MB) ã Private_Dirty ã«ãªãã¾ãããäºæ³éãã§ãã以ä¸ãã
- CoW ã§å ±æãããé å㯠Shared_Dirty
- å ±æããã¦ããªããã©ã¤ãã¼ããã¼ã¿ã¯ Private_Dirty
ã¨ãã¦ããããã®ãµã¤ãºãå ±åããã¦ããã®ã ããã¨äºæ³ãã¤ãã¾ãã
/proc/PID/smaps ã®ã«ã¼ãã«ã®ã³ã¼ãã追ã
ããå ·ä½çã«ãShared ã Private ãä¸ä½ã©ã®ãããªåºå¥ãªã®ãã調ã¹ãããã«ã¼ãã«ã® proc ãã¡ã¤ã«ã·ã¹ãã ã®ã³ã¼ãã追ã£ã¦ã¿ã¾ãããã½ã¼ã¹ã¯ 2.6.23 ã® i386 ã§ãã
proc ãã¡ã¤ã«ã·ã¹ãã ã®ã³ã¼ããè¦ã¦ããã¨ã/proc/PID/smaps ã read ããã㨠fs/proc/task_mmu.c ã® show_smap() é¢æ°ãå¼ã°ããããã«ãªã£ã¦ããã®ããããã¾ããshow_smap() å ã§ã¯ãä»®æ³ã¡ã¢ãªç©ºéã®å ¨ãã¼ã¸ã渡ãæ©ãã¦åãã¼ã¸ã«å¯¾ã smaps_pte_range() é¢æ°ãå®è¡ããå¦çãè¡ããã¦ãã¾ããwalk_page_range() ã¯ãã¼ã¿æ§é ãå帰çã«æ¸¡ãæ©ãããã®ãã¼ã¿ã«å¯¾ãã¦ä¸ããããé¢æ°ãå®è¡ãã¦ããã¨ãããVisitor ãã¿ã¼ã³ã®ãããªé¢æ°ã§ãã
static int show_smap(struct seq_file *m, void *v) { struct vm_area_struct *vma = v; /* æ°ãã mem_size_stats æ§é ä½ãç¨æ */ struct mem_size_stats mss; /* ã¼ãã¯ãªã¢ */ memset(&mss, 0, sizeof mss); /* ä»®æ³ã¡ã¢ãªç©ºéã®å ¨ãã¼ã¸ã渡ãæ©ã㦠smap_pte_range() ãå®è¡ */ if (vma->vm_mm && !is_vm_hugetlb_page(vma)) walk_page_range(vma, smaps_pte_range, &mss); return show_map_internal(m, v, &mss); }
mem_size_stats 㯠smaps ã®åã¨ã³ããªã«ç¸å½ããæ§é ä½ã®ããã§ã以ä¸ã®ãããªã¡ã³ããããã¾ãã
struct mem_size_stats { unsigned long resident; unsigned long shared_clean; unsigned long shared_dirty; unsigned long private_clean; unsigned long private_dirty; unsigned long referenced; };
smaps ã®åºåã¨åã¡ã³ããä¸å¯¾ä¸ã§å¯¾å¿ãã¦ããã®ãåããã¾ãã
walk_page_range() ã«ä¸ããããé¢æ° smaps_pte_range() ããåãã¼ã¸ãã¼ãã«ã¨ã³ããªã®å±æ§çããããã®ãã¼ã¸ãã¼ãã«ã«æ ¼ç´ããã¦ãããã¼ã¸ãå®éã©ã®ãããªç¨®é¡ã®ãã¼ã¸ã¨ãã¦ãããã³ã°ããã¦ããããå¤å®ãã¦ãmem_size_stats (mss) ã«éè¨çµæãæ ¼ç´ããå¦çãè¡ã£ã¦ãã¾ãããå¦çå 容ã«ã³ã¡ã³ããã¤ãã¦ã¿ã¾ããã
static void smaps_pte_range(struct vm_area_struct *vma, pmd_t *pmd, unsigned long addr, unsigned long end, void *private) { struct mem_size_stats *mss = private; pte_t *pte, ptent; spinlock_t *ptl; struct page *page; /* PTE ã«ããã¯ãããã */ pte = pte_offset_map_lock(vma->vm_mm, pmd, addr, &ptl); /* å¼æ°ã«ä¸ããããã¢ãã¬ã¹ç©ºéãçµç«¯ã¾ã§èãã */ for (; addr != end; pte++, addr += PAGE_SIZE) { ptent = *pte; /* PTE ã«ãã¼ã¸ãå²ãå½ã¦ããã¦ããªããã°ä½ãããã次㸠*/ if (!pte_present(ptent)) continue; /* RSS ã«ãã¼ã¸ä¸ã¤åã®ãµã¤ãº (åºæ¬ 4kB) ã足ããã */ mss->resident += PAGE_SIZE; /* ãã¼ã¸ãåãåºãã¦é常ã®ãã¼ã¸ã§ãªããã°æ¬¡ã¸ */ page = vm_normal_page(vma, addr, ptent); if (!page) continue; /* Accumulate the size in pages that have been accessed. */ if (pte_young(ptent) || PageReferenced(page)) mss->referenced += PAGE_SIZE; /* ãããéè¦: ãã¼ã¸ã®åç §ã«ã¦ã³ãã 2 以ä¸ãªã sharedã1 ãªã private */ if (page_mapcount(page) >= 2) { /* PTE ã«ãã¼ãã£ãã©ã°ãç«ã£ã¦ããã shared_dirty */ /* ããã§ãªããã° shared_clean ã¨ãã¦éè¨ */ if (pte_dirty(ptent)) mss->shared_dirty += PAGE_SIZE; else mss->shared_clean += PAGE_SIZE; } else { ãããããã/* PTE ã®ãã¼ãã£ãã©ã°ãè¦ããshared ã®å ´åã¨åã */ if (pte_dirty(ptent)) mss->private_dirty += PAGE_SIZE; else mss->private_clean += PAGE_SIZE; } } /* ããã¯è§£é¤ */ pte_unmap_unlock(pte - 1, ptl); cond_resched(); }
smaps ã§å ±åããã¦ãã Shared_Clean / Shared_Dirty ã¯è¤æ°ä»¥ä¸ã®ä»®æ³ã¡ã¢ãªé åãããããã³ã°ããã¦ãããã¼ã¸ã®åè¨æ°ãæ°ãã¦ãããã¨ããããã¾ãã
親ã¨åã®ä»®æ³é åããåããã¼ã¸ããããããã¨è¢«ãããæ°ã¯ 2 ã«ãªãã¾ãããããã®é å㯠Shared ã«åé¡ããã¾ãããã®ãã¼ã¸ã«ãã¼ãã£ãã©ã°ãç«ã£ã¦ããã°ãShared_Dirty ã«ãªãã¾ãããã¼ãã£ãã©ã°ãç«ã£ã¦ãããã¼ã¸ã¯ãããã¤ã¹ã«ãããã³ã°ããã¦ããã°å®æçã«ååããã¾ãããããã§ãªããã°ãã®ã¾ã¾ã¡ã¢ãªé åã«æ®ãã¯ãã§ãã åæãåããæç¹ã§ãã©ã°ãè½ã¡ããã¤ã¾ã Clean ã«ãªãã¾ãããããã§ãªããã°ãã¼ã¸ã¯ Dirty ã®ã¾ã¾æ®ãã¯ãã§ãã
å ã®ãã¹ãã§ãããã»ã¹ãä¸ã¤ã®ã¨ãã¯ãã¹ã¦ Private_Dirty ã«ãããã»ã¹ãäºã¤ã«ãªã㨠Shared_Dirty ã«ãååã®é åã«æ¸ãè¾¼ã㨠Shared / Private ã«åã ã«ãªãã®ã確èªã§ãã¾ãããããã¹ã¦ããã§èª¬æãã¤ãã¾ãã
- ããã»ã¹ãä¸ã¤ã®å ´åã¯ããããã¡é åã®è¢«ãããæ°ã¯ 1 ã§ããã¾ããã¼ã¸ç¢ºä¿å¾ã«æ¸ãè¾¼ã¿ãè¡ã£ã¦ãã (bss ã¸ã®å²ãå½ã¦åé¿ã®ããã« 'a' ã§åæåãã¦ãã¾ã) ã®ã§è©²å½é åã®ãã¼ã¸ãã¼ãã«ç¾¤ã¯ãã¼ãã£ãã©ã°ãç«ã¡ã¾ãã â Private_Dirty 100MB ã¨ãªãã¾ãã
- fork ã§åããã»ã¹ãä½ãã¨ããããã¡é åã®è¢«ãããæ°ã¯è¦ªã¨åããã§åè¨ 2 ã«ãªããåãã¼ã¸ã¯ Shared ã¨å¤å®ããã¾ããããã»ã¹ä¸ã¤ã®å ´ååæ§ããããã¡é åã«ã¯æ¸ãè¾¼ã¿ãè¡ã£ã¦ãããããã¼ãã£ãã©ã°ãç«ã£ã¦ãã¾ãã â Shared_Dirty 100MB ã¨ãªãã¾ãã
- åããã»ã¹ã§ãããã¡ã®ååã«æ¸ãè¾¼ã¿ãè¡ãã¨ãCoW ã«ããååé¨åã¯è¦ªã¨åã§å¥ã ã®é åãããããããã¨ã«ãªãã¾ããå¾ã£ã¦ååé¨åã®ãã¼ã¸ç¾¤ã®è¢«ãããæ°ã¯ 1 ã«ãªãã¾ããæ®ã£ãå¾åã¯å¤ããã被ãããæ°ã¯ 2 ã§ã â Private_Dirty 50MB / Shared_Dirty 50MB ã«ãªãã¾ãã
top ãåéããã¦ãã
ã¨ãã㧠top ã«ã¯ SHR ã¨ããé ç®ãããã¾ãããã£ã¨ãã®ã«ã©ã ãã親åã§ã®å ±æã¡ã¢ãªã®ãµã¤ãºãªãã ã¨åéãããã¦ãã¾ããã(ãããããã°èªåã®åéãã§ã¯ãªããã«ã¼ãã«ãæ´æ°ãããéç¨ã§ SHR ã®æå³ããå 容ãå¤æ´ã«ãªã£ãã¨ãããã¨ãããããããã¾ããããããã¾ã§ã¯åããã¾ããã)
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 6676 apache 15 0 171m 79m 6552 S 0 2.1 2:09.07 httpd 6865 apache 15 0 169m 77m 6172 S 8 2.0 1:59.57 httpd 6665 apache 16 0 170m 77m 6520 S 0 2.0 2:12.29 httpd 6873 apache 15 0 169m 77m 6508 S 0 2.0 1:52.46 httpd 6678 apache 16 0 169m 77m 6548 S 0 2.0 2:07.98 httpd
Practical mod_perl ã® 9 ç« http://modperlbook.org/html/9-3-Process-Memory-Measurements.html ã
t: SHR -- å ±æã¡ã¢ãªãµã¤ãº (kb) ã¿ã¹ã¯ãå©ç¨ãã¦ããå ±æã¡ã¢ãªã®ç·éãä»ã®ããã»ã¹ã¨å ±æãããå¯è½æ§ã®ããã¡ã¢ãªãåç´ã«åæ ãã¦ããã
ã¨ãã man top ã®è©²å½ã«ã©ã ã®è§£èª¬ãè¦ãã¨ä¸è¦ééããªãããã«æãã¾ããããã®ã«ã©ã 㯠/proc/PID/statm ããå¤ãåå¾ãã¦ãã¦ãæ¤è¨¼ããã°ã©ã ãåãããªããè¨ç®ãã¦ããã®é ç®ãå ±æé ååã®ãµã¤ãºã«ã¯ãªãã¾ããã§ããã
man proc ã® statm ã«ãã
/proc/[number]/statm Provides information about memory status in pages. The columns are: size total program size resident resident set size share shared pages text text (code) lib library data data/stack dt dirty pages (unused in Linux 2.6)
share ã top ã§ä½¿ããã¦ããå¤ã§ããstatm ã®å¤ã¯ãã¼ã¸æ°ãªã®ã§ã4kB ãæãããã®ã top ã® SHR ã«ã©ã ã®å¤ã«ãªã£ã¦ãã¾ãã
ãã® share å¤ãã©ãããæ¥ããã®ãªã®ããã«ã¼ãã«ã追ã£ã¦è¦ã¾ããstatm ã® read ã«å¯¾ããã³ã¼ã«ããã¯ã¯ fs/proc/array.c ã® proc_pid_statm() ã§ãã
int proc_pid_statm(struct task_struct *task, char *buffer) { int size = 0, resident = 0, shared = 0, text = 0, lib = 0, data = 0; struct mm_struct *mm = get_task_mm(task); if (mm) { ããã /* task_statm() ã§è¨ç® */ size = task_statm(mm, &shared, &text, &data, &resident); mmput(mm); } return sprintf(buffer, "%d %d %d %d %d %d %d\n", size, resident, shared, text, lib, data, 0); }
task_statm() ã追ã£ã¦ã¿ã¾ããfs/proc/task_mmu.c ã«ããã¾ãã
int task_statm(struct mm_struct *mm, int *shared, int *text, int *data, int *resident) { /* shared 㯠mm_struct.file_rss ã®å¤ */ *shared = get_mm_counter(mm, file_rss); *text = (PAGE_ALIGN(mm->end_code) - (mm->start_code & PAGE_MASK)) >> PAGE_SHIFT; *data = mm->total_vm - mm->shared_vm; *resident = *shared + get_mm_counter(mm, anon_rss); return mm->total_vm; }
shared é 㯠mm_struct æ§é ä½ã® file_rss ã¡ã³ãã®å¤ã§ãããã¨ããããã¾ããfile_rss ã¨ããååããããã¡ã¤ã«é åã«ããããããã¡ã¢ãªãµã¤ãºã§ã¯ãªããã¨äºæ³ããã¾ãããã® file_rss ã¯å®éã©ããããã®ãªã®ãã¯ãã«ã¼ãã« 2.6.11.1 ã®å¤ãå®è£ ãè¦ãã¨ããã¯ã£ããåããã¾ãã
int task_statm(struct mm_struct *mm, int *shared, int *text, int *data, int *resident) { ãã/* shared 㯠rss - anon_rss */ *shared = mm->rss - mm->anon_rss; *text = (PAGE_ALIGN(mm->end_code) - (mm->start_code & PAGE_MASK)) >> PAGE_SHIFT; *data = mm->total_vm - mm->shared_vm; *resident = mm->rss; return mm->total_vm; }
ç©çã¡ã¢ãªã«ç¢ºä¿ããé åãããç¡åãããã³ã°ã«ããå²ãå½ã¦ããããµã¤ãºã®å·®åã§ããç¡åãããã³ã°ä»¥å¤ã¨ãããã¨ã¯ããã¯ãæ示çã«ãã¡ã¤ã«ãããã³ã°ãããé å (mmap ãããå ±æã©ã¤ãã©ãªé åãªã©ãä¸ä¾) ã®ãã¼ã¸æ°ã§ããã¨è¦ã¦ééããªãããã§ãã
ã¾ã¨ã
- /proc/PID/smaps ãè¦ã㨠CoW ã§è¦ªåãå ±æãã¦ããã¡ã¢ãªã®ã ãããã®ãµã¤ãºããããã¾ãã
- Perl ã§ã¯ Linux::Smaps 㧠smaps ãããã°ã©ããã«ã«æ±ããã¨ãã§ãã¾ãã
- smaps ã§ã¯å ±æé åã®ãµã¤ãºã¯ Sharedãããã§ãªãé åã®ãµã¤ãºã¯ Private ã¨ãã¦å ±åããã¾ã
- ã«ã¼ãã«ã®ã³ã¼ãã追ãã¨ãShared ã¯ä»®æ³ã¡ã¢ãªç©ºéããã®è¢«ãããæ°ã 2 以ä¸ã®ãã¼ã¸ã®åè¨ãPrivate ã¯è¢«ãããæ°ã 1 ã®ãã¼ã¸ã®åè¨ã§ãããã¨ããããã¾ããã
- ã¾ã Shared_Dirty / Shared_Clean ã® Dirty 㨠Clean ã®éãã¯ãã¼ã¸ãã¼ãã«ã¨ã³ããªã®ãã¼ãã£ãã©ã°ã®æç¡ã§ãããã¨ããããã¾ãã
以ä¸ããã/proc/PID/smaps ã®å¤ãããªã CoW ã®å ±æé åã®ãµã¤ãºãæ±ããããããã¯ã£ãããã¾ãããã¾ããtop ã® SHR é ç®ã¯æã£ã¦ãããã® (CoW ã®å ±æé åã®ãµã¤ãºã ã¨æãè¾¼ãã§ãã) ã¨ã¯éã£ã¦ãããã¨ããããã¾ããã