/**************************************************/ Á¦¸ñ: ÇÁ·Î±×·¥ ½ÇÇà ½Ã ¸Þ¸ð¸® ±¸µµ ¿øÁ¦: Memory Layout in Program Execution ÀúÀÚ: Fr??ick Giasson(fred@decatomb.com) ¹ø¿ª ¹× ÆíÁý: vangelis(vangelis@wowhacker.org) ¹ßÇ¥ÀÏ: October 2001 /*************************************************/ # ¿À´ÃºÎÅÍ ½Ã°£ ³ª´Â´ë·Î ÀÌ ±Û ¿Ã¸³´Ï´Ù. ÀϺκÐÀº Àú°¡ ÆíÁýÇϱ⵵ Çϴµ¥ Ȥ½Ã¶óµµ ¹®Á¦°¡ ÀÖ´Ù¸é ¿ø¹®À» Âü°íÇϽñ⠹ٶø´Ï´Ù. ## À̹ø °Ô½Ã¹°Àº Â÷·Ê¿Í º»¹®¿¡¼­ ³ª¿À´Â ¼Ò½º ÄÚµåµéÀÔ´Ï´Ù. :: ¸ñ Â÷ :: ¼­¹® µµÀÔ 1Àå 1. ÇÁ·Î±×·¥ ½ÇÇà: route map 1.1. pseudo-shell ½© ÄÚµå 1.2. ÀÚ½Ä ÇÁ·Î¼¼½º ¸¸µé±â 1.2.1. FORKS ½Ã½ºÅÛ È£Ãâ: 9 ´Ü°è 1.3. ÇÁ·Î±×·¥ ½ÇÇà 1.3.1. C ½Ç½Ã°£, ½ÃÀÛ(start-off) ÀýÂ÷ 1.3.2. EXEC ½Ã½ºÅÛ È£Ãâ, 9 ´Ü°è 2Àå 2. ½ÇÇàµÈ ÇÁ·Î±×·¥ÀÇ ¸Þ¸ð¸® ¹èÄ¡ 2.1. ELF ½ÇÇà ÆÄÀÏ ÇغΠ3Àå 3. ½ºÅðú Èü 3.1. À§Ä¡ 3.2. ÄÄÆÄÀϽà »ç¿ëÀÚ ½ºÅà ÇÁ·¹ÀÓÀÇ Å©±â´Â ¾î¶»°Ô ¾Ë ¼ö Àִ°¡? 3.3. ·¹Áö½ºÅÍ 3.3.1. ÀÏ¹Ý ·¹Áö½ºÅÍ 3.3.2. ¼¼±×¸ÕÆ® ·¹Áö½ºÅÍ 3.3.3. ¿ÀÇÁ¼Â ·¹Áö½ºÅÍ 3.4. ½ºÅà 3.4.2. ÇÁ·Î½ÃÀú È£Ãâ µ¿¾È ½ºÅà °ü¸® 3.4.2.1. È£Ãâ 3.4.2.2. ÇÁ·Ñ·Î±× 3.4.2.3. ¸®ÅÏ 3.5. Èü °á·Ð Annex 1 Annex 2 Annex 3 Âü°í¹®Çå Annex 1 : --------- do_fork() - Function Code - src/mm/forkexit.c --------------------------------------------- /*===========================================================================* * do_fork * *===========================================================================*/ 01 PUBLIC int do_fork() 02 { 03 /* The process pointed to by 'mp' has forked. Create a child process. */ 04 05 register struct mproc *rmp; /* pointer to parent */ 06 register struct mproc *rmc; /* pointer to child */ 07 int i, child_nr, t; 08 phys_clicks prog_clicks, child_base = 0; 09 phys_bytes prog_bytes, parent_abs, child_abs; /* Intel only */ 10 11 /* If tables might fill up during FORK, don't even start since recovery half 12 * way through is such a nuisance. 13 */ 14 rmp = mp; 15 if (procs_in_use == NR_PROCS) return(EAGAIN); 16 if (procs_in_use >= NR_PROCS-LAST_FEW && rmp->mp_effuid != 0)return(EAGAIN); 17 18 /* Determine how much memory to allocate. Only the data and stack need to 19 * be copied, because the text segment is either shared or of zero length. 20 */ 21 prog_clicks = (phys_clicks) rmp->mp_seg[S].mem_len; 22 prog_clicks += (rmp->mp_seg[S].mem_vir - rmp->mp_seg[D].mem_vir); 23 #if (SHADOWING == 0) 24 prog_bytes = (phys_bytes) prog_clicks << CLICK_SHIFT; 25 #endif 26 if ( (child_base = alloc_mem(prog_clicks)) == NO_MEM) return(ENOMEM); 27 28 #if (SHADOWING == 0) 29 /* Create a copy of the parent's core image for the child. */ 30 child_abs = (phys_bytes) child_base << CLICK_SHIFT; 31 parent_abs = (phys_bytes) rmp->mp_seg[D].mem_phys << CLICK_SHIFT; 32 i = sys_copy(ABS, 0, parent_abs, ABS, 0, child_abs, prog_bytes); 33 if (i < 0) panic("do_fork can't copy", i); 34 #endif 35 36 /* Find a slot in 'mproc' for the child process. A slot must exist. */ 37 for (rmc = &mproc[0]; rmc < &mproc[NR_PROCS]; rmc++) 38 if ( (rmc->mp_flags & IN_USE) == 0) break; 39 40 /* Set up the child and its memory map; copy its 'mproc' slot from parent. */ 41 child_nr = (int)(rmc - mproc); /* slot number of the child */ 42 procs_in_use++; 43 *rmc = *rmp; /* copy parent's process slot to child's */ 44 45 rmc->mp_parent = who; /* record child's parent */ 46 rmc->mp_flags &= ~TRACED; /* child does not inherit trace status */ 47 #if (SHADOWING == 0) 48 /* A separate I&D child keeps the parents text segment. The data and stack 49 * segments must refer to the new copy. 50 */ 51 if (!(rmc->mp_flags & SEPARATE)) rmc->mp_seg[T].mem_phys = child_base; 52 rmc->mp_seg[D].mem_phys = child_base; 53 rmc->mp_seg[S].mem_phys = rmc->mp_seg[D].mem_phys + 54 (rmp->mp_seg[S].mem_vir - rmp->mp_seg[D].mem_vir); 55 #endif 56 rmc->mp_exitstatus = 0; 57 rmc->mp_sigstatus = 0; 58 59 /* Find a free pid for the child and put it in the table. */ 60 do { 61 t = 0; /* 't' = 0 means pid still free */ 62 next_pid = (next_pid < 30000 ? next_pid + 1 : INIT_PID + 1); 63 for (rmp = &mproc[0]; rmp < &mproc[NR_PROCS]; rmp++) 64 if (rmp->mp_pid == next_pid || rmp->mp_procgrp == next_pid) { 65 t = 1; 66 break; 67 } 68 rmc->mp_pid = next_pid; /* assign pid to child */ 69 } while (t); 70 /* Tell kernel and file system about the (now successful) FORK. */ 71 sys_fork(who, child_nr, rmc->mp_pid, child_base); /* child_base is 68K only*/ 72 tell_fs(FORK, who, child_nr, rmc->mp_pid); 73 74 #if (SHADOWING == 0) 75 /* Report child's memory map to kernel. */ 76 sys_newmap(child_nr, rmc->mp_seg); 77 #endif 78 79 /* Reply to child to wake it up. */ 80 reply(child_nr, 0, 0, NIL_PTR); 81 return(next_pid); /* child's pid */ 82 } ------ Annex 2 : --------- Process Table definition - src/kernel/proc.h -------------------------------------------- struct proc { struct stackframe_s p_reg; /* process' registers saved in stack frame */ #if (CHIP == INTEL) reg_t p_ldt_sel; /* selector in gdt giving ldt base and limit*/ struct segdesc_s p_ldt[2]; /* local descriptors for code and data */ /* 2 is LDT_SIZE - avoid include protect.h */ #endif /* (CHIP == INTEL) */ #if (CHIP == M68000) reg_t p_splow; /* lowest observed stack value */ int p_trap; /* trap type (only low byte) */ #if (SHADOWING == 0) char *p_crp; /* mmu table pointer (really struct _rpr *) */ #else phys_clicks p_shadow; /* set if shadowed process image */ int align; /* make the struct size a multiple of 4 */ #endif int p_nflips; /* statistics */ char p_physio; /* cannot be (un)shadowed now if set */ #if defined(FPP) struct fsave p_fsave; /* FPP state frame and registers */ int align2; /* make the struct size a multiple of 4 */ #endif #endif /* (CHIP == M68000) */ reg_t *p_stguard; /* stack guard word */ int p_nr; /* number of this process (for fast access) */ int p_int_blocked; /* nonzero if int msg blocked by busy task */ int p_int_held; /* nonzero if int msg held by busy syscall */ struct proc *p_nextheld; /* next in chain of held-up int processes */ int p_flags; /* P_SLOT_FREE, SENDING, RECEIVING, etc. */ struct mem_map p_map[NR_SEGS];/* memory map */ pid_t p_pid; /* process id passed in from MM */ clock_t user_time; /* user time in ticks */ clock_t sys_time; /* sys time in ticks */ clock_t child_utime; /* cumulative user time of children */ clock_t child_stime; /* cumulative sys time of children */ clock_t p_alarm; /* time of next alarm in ticks, or 0 */ struct proc *p_callerq; /* head of list of procs wishing to send */ struct proc *p_sendlink; /* link to next proc wishing to send */ message *p_messbuf; /* pointer to message buffer */ int p_getfrom; /* from whom does process want to receive? */ int p_sendto; struct proc *p_nextready; /* pointer to next ready process */ sigset_t p_pending; /* bit map for pending signals */ unsigned p_pendcount; /* count of pending and unfinished signals */ char p_name[16]; /* name of the process */ }; ------ Annex 3: -------- 001 /*===========================================================================* 002 * do_exec * 003 *===========================================================================*/ 004 PUBLIC int do_exec() 005 { 006 /* Perform the execve(name, argv, envp) call. The user library builds a 007 * complete stack image, including pointers, args, environ, etc. The stack 008 * is copied to a buffer inside MM, and then to the new core image. 009 */ 010 011 register struct mproc *rmp; 012 struct mproc *sh_mp; 013 int m, r, fd, ft, sn; 014 static char mbuf[ARG_MAX]; /* buffer for stack and zeroes */ 015 static char name_buf[PATH_MAX]; /* the name of the file to exec */ 016 char *new_sp, *basename; 017 vir_bytes src, dst, text_bytes, data_bytes, bss_bytes, stk_bytes, vsp; 018 phys_bytes tot_bytes; /* total space for program, including gap */ 019 long sym_bytes; 020 vir_clicks sc; 021 struct stat s_buf; 022 vir_bytes pc; 023 /* Do some validity checks. */ 024 rmp = mp; 025 stk_bytes = (vir_bytes) stack_bytes; 026 if (stk_bytes > ARG_MAX) return(ENOMEM); /* stack too big */ 027 if (exec_len <= 0 || exec_len > PATH_MAX) return(EINVAL); 028 029 /* Get the exec file name and see if the file is executable. */ 030 src = (vir_bytes) exec_name; 031 dst = (vir_bytes) name_buf; 032 r = sys_copy(who, D, (phys_bytes) src, 033 MM_PROC_NR, D, (phys_bytes) dst, (phys_bytes) exec_len); 034 if (r != OK) return(r); /* file name not in user data segment */ 035 tell_fs(CHDIR, who, FALSE, 0); /* switch to the user's FS environ. */ 036 fd = allowed(name_buf, &s_buf, X_BIT); /* is file executable? */ 037 if (fd < 0) return(fd); /* file was not executable */ 038 039 /* Read the file header and extract the segment sizes. */ 040 sc = (stk_bytes + CLICK_SIZE - 1) >> CLICK_SHIFT; 041 m = read_header(fd, &ft, &text_bytes, &data_bytes, &bss_bytes, 042 &tot_bytes, &sym_bytes, sc, &pc); 043 if (m < 0) { 044 close(fd); /* something wrong with header */ 045 return(ENOEXEC); 046 } 047 048 /* Fetch the stack from the user before destroying the old core image. */ 049 src = (vir_bytes) stack_ptr; 050 dst = (vir_bytes) mbuf; 051 r = sys_copy(who, D, (phys_bytes) src, 052 MM_PROC_NR, D, (phys_bytes) dst, (phys_bytes)stk_bytes); 053 if (r != OK) { 054 close(fd); /* can't fetch stack (e.g. bad virtual addr) */ 055 return(EACCES); 056 } 057 058 /* Can the process' text be shared with that of one already running? */ 059 sh_mp = find_share(rmp, s_buf.st_ino, s_buf.st_dev, s_buf.st_ctime); 060 061 /* Allocate new memory and release old memory. Fix map and tell kernel. */ 062 r = new_mem(sh_mp, text_bytes, data_bytes, bss_bytes, stk_bytes, tot_bytes); 063 if (r != OK) { 064 close(fd); /* insufficient core or program too big */ 065 return(r); 066 } 067 068 /* Save file identification to allow it to be shared. */ 069 rmp->mp_ino = s_buf.st_ino; 070 rmp->mp_dev = s_buf.st_dev; 071 rmp->mp_ctime = s_buf.st_ctime; 072 073 /* Patch up stack and copy it from MM to new core image. */ 074 vsp = (vir_bytes) rmp->mp_seg[S].mem_vir << CLICK_SHIFT; 075 vsp += (vir_bytes) rmp->mp_seg[S].mem_len << CLICK_SHIFT; 076 vsp -= stk_bytes; 077 patch_ptr(mbuf, vsp); 078 src = (vir_bytes) mbuf; 079 r = sys_copy(MM_PROC_NR, D, (phys_bytes) src, 080 who, D, (phys_bytes) vsp, (phys_bytes)stk_bytes); 081 if (r != OK) panic("do_exec stack copy err", NO_NUM); 082 083 /* Read in text and data segments. */ 084 if (sh_mp != NULL) { 085 lseek(fd, (off_t) text_bytes, SEEK_CUR); /* shared: skip text */ 086 } else { 087 load_seg(fd, T, text_bytes); 088 } 089 load_seg(fd, D, data_bytes); 090 091 #if (SHADOWING == 1) 092 if (lseek(fd, (off_t)sym_bytes, SEEK_CUR) == (off_t) -1) ; /* error */ 093 if (relocate(fd, (unsigned char *)mbuf) < 0) ; /* error */ 094 pc += (vir_bytes) rp->mp_seg[T].mem_vir << CLICK_SHIFT; 095 #endif 096 097 close(fd); /* don't need exec file any more */ 098 099 /* Take care of setuid/setgid bits. */ 100 if ((rmp->mp_flags & TRACED) == 0) { /* suppress if tracing */ 101 if (s_buf.st_mode & I_SET_UID_BIT) { 102 rmp->mp_effuid = s_buf.st_uid; 103 tell_fs(SETUID,who, (int)rmp->mp_realuid, (int)rmp->mp_effuid); 104 } 105 if (s_buf.st_mode & I_SET_GID_BIT) { 106 rmp->mp_effgid = s_buf.st_gid; 107 tell_fs(SETGID,who, (int)rmp->mp_realgid, (int)rmp->mp_effgid); 108 } 109 } 110 111 * Save offset to initial argc (for ps) */ 112 rmp->mp_procargs = vsp; 113 114 /* Fix 'mproc' fields, tell kernel that exec is done, reset caught sigs. */ 115 for (sn = 1; sn <= _NSIG; sn++) { 116 if (sigismember(&rmp->mp_catch, sn)) { 117 sigdelset(&rmp->mp_catch, sn); 118 rmp->mp_sigact[sn].sa_handler = SIG_DFL; 119 sigemptyset(&rmp->mp_sigact[sn].sa_mask); 120 } 121 } 122 123 rmp->mp_flags &= ~SEPARATE; /* turn off SEPARATE bit */ 124 rmp->mp_flags |= ft; /* turn it on for separate I & D files */ 125 new_sp = (char *) vsp; 126 127 tell_fs(EXEC, who, 0, 0); /* allow FS to handle FD_CLOEXEC files */ 128 129 /* System will save command line for debugging, ps(1) output, etc. */ 130 basename = strrchr(name_buf, '/'); 131 if (basename == NULL) basename = name_buf; else basename++; 132 sys_exec(who, new_sp, rmp->mp_flags & TRACED, basename, pc); 133 return(OK); 134 } /**************************************************/ Á¦¸ñ: ÇÁ·Î±×·¥ ½ÇÇà ½Ã ¸Þ¸ð¸® ±¸µµ ¿øÁ¦: Memory Layout in Program Execution ÀúÀÚ: Fr??ick Giasson(fred@decatomb.com) ¹ø¿ª ¹× ÆíÁý: vangelis(vangelis@wowhacker.org) ¹ßÇ¥ÀÏ: October 2001 /*************************************************/ ¼­ ¹® ÀÌ ±ÛÀº À¥ »ó¿¡ ¹ßÇ¥ÇÑ ³ªÀÇ Ã¹ ¹ø° ±ÛÀÌ´Ù. ÀÌ ±ÛÀº Ãʺ¸ÀÚ, ½Ã½ºÅÛ °ü¸®ÀÚ, ÇÁ·Î±×·¡¸Ó, Ä¿³Î °³¹ßÀÚ, Ãë¹Ì·Î °øºÎÇÏ´Â »ç¶÷, ¶Ç´Â ´Ù¸¥ ÄÄÇ»Å͸¦ ÁÁ¾ÆÇÏ´Â »ç¶÷µéÀ» À§ÇÑ °ÍÀÌ´Ù. ¿µ¾î°¡ ¸¹ÀÌ ºÎÁ·ÇÏ´Ï ¸¸ÀÏ ¹®¹ý»ó ¹®Á¦°¡ ÀÖ´Ù¸é ÁöÀûÇØÁÖ±æ ¹Ù¶õ´Ù. ±â²¨ÀÌ °íÄ¡µµ·Ï ÇÏ°Ú´Ù. ¸¸¾à ¿©·¯ºÐµéÀÌ ÀÌ ±Û¿¡ ´ëÇؼ­ ³ª¿Í ±×¸®°í ´Ù¸¥ »ç¶÷µé°ú Åä·ÐÇϱ⸦ ¿øÇÑ´Ù¸é ´ÙÀ½À» ÀÌ¿ëÇÏ±æ ¹Ù¶õ´Ù. - http://www.decatomb.com/forums/viewforum.php?forum=29 µµ ÀÔ ¸Þ¸ð¸® °ü¸®´Â ¿î¿µÃ¼Á¦ °³¹ß¿¡¼­ ¶ß°Å¿î ÁÖÁ¦ÀÌ´Ù. ÀÌ°ÍÀº ½Ã½ºÅÛÀÇ Áß¿äÇÑ ÀÚ¿øÀ̸ç, ÁÖÀÇ ±í°Ô °ü¸®µÉ ÇÊ¿ä°¡ ÀÖ´Ù. ÀÌ ±ÛÀº ¸Þ¸ð¸® °ü¸® ½Ã½ºÅÛ Àüü °úÁ¤À» ´Ù·çÁö´Â ¾ÊÀ» °ÍÀÌ´Ù. ¾Æ´Ï, ¿ì¸®´Â ÀÌ ¸Þ¸ð¸® °ü¸® ½Ã½ºÅÛ¿¡¼­ »ç¿ëÀÚÀÇ °üÁ¡À» ¾Ë¾Æº¼ °ÍÀÌ´Ù. ¿ì¸®´Â ¾î¶»°Ô ¾î¶² ÇÁ·Î±×·¥ ÆÄÀÏÀÌ ½ÇÇàµÇ°í, ¸Þ¸ð¸® ¼ÓÀ¸·Î ¸ÊÇεǴÂÁö ¾Ë¾Æº¼ °ÍÀÌ´Ù. ¸Þ¸ð¸® °ü¸® ½Ã½ºÅÛ¿¡´Â ½º¿ÍÇÎ(swapping), °¡»ó ¸Þ¸ð¸®(virtual memory), ÆäÀÌÁö ´ëü ¾Ë°í¸®Áò(page replacement algorithm), ¼¼±×¸àÅ×À̼Ç(segmentation) µîµîÀÇ ¸¹Àº ´Ù¸¥ ºÎºÐµéÀÌ ÀÖ´Ù. ±×·¡¼­ ¸¸¾à ¿î¿©Ã¼Á¦¿¡¼­ ¸Þ¸ð¸® °ü¸® ½Ã½ºÅÛÀÇ Àü ÇÁ·Î¼¼½º¸¦ ÀÌÇØÇÏ°íÀÚ ¿øÇÑ´Ù¸é ÀÌ ¹®¼­ µÞºÎºÐ¿¡ ³ª¿À´Â Âü°í¹®ÇåµéÀ» º¸¾Æ¶ó. Linux/Unix ±×¸®°í MinixÀÇ ¸Þ¸ð¸® °ü¸® ½Ã½ºÅÛ¿¡ ´ëÇÑ ¸¹Àº À¯¿ëÇÑ ÀÚ·áµéÀÌ ÀÖ´Ù. ³ª´Â ÀÌ ÇÁ·Î¼¼½º°¡ ¾î¶»°Ô ÀÛµ¿ÇÏ´ÂÁö ¼³¸íÇϱâ À§ÇØ Minix/Linux ¸Þ¸ð¸® °ü¸® ½Ã½ºÅÛÀ» »ç¿ëÇÒ °ÍÀÌ´Ù. ÀÌ°ÍÀº ½ÇÁ¦ NetBSD, FreeBSD µîÀÇ ´Ù¸¥ ELF ±â¹ÝÀÇ A-32 ¿î¿µÃ¼Á¦¿Í °°Àº ½ºÅ°¸¶ÀÌ´Ù. ÀÌ ¹®¼­¿¡¼­ Á¦½ÃµÇ´Â ¿¹Á¦ ÇÁ·Î±×·¥µéÀº LInux¿¡¼­ gcc·Î ÄÄÆÄÀϵǸç, ¾î¼Àºí¸® Äڵ带 µð¹ö±× Çϱâ À§ÇØ GDB¸¦ »ç¿ëÇÒ °ÍÀÌ´Ù. 1Àå ? ÇÁ·Î±×·¥ ½ÇÇà: ¶ó¿ìÅÍ ¸Ê(route map) ¾î¶»°Ô ½ÇÇàµÈ ÇÁ·Î±×·¥ÀÌ ¸Þ¸ð¸®¿¡ ¸ÊÇÎ µÇ´ÂÁö ¾Æ´Â °ÍÀº Èï¹Ì·Ó´Ù. ±×·±µ¥ ¾î¶»°Ô ½ÇÇàµÇ´Â °ÍÀϱî? ÀÌ ±ÛÀÇ Ã¹ ºÎºÐ¿¡¼­ ³ª´Â ¾î¶² ÇÁ·Î±×·¥ÀÇ Àüü ½ÇÇà °úÁ¤ÀÌ ÀÛ¿ëÇÏ´ÂÁö ¶ó¿ìÅÍ ¸ÊÀ» ÃßÀûÇÔÀ¸·Î¼­ À̾߱âÇÒ °ÍÀÌ´Ù. Ãâ¹ßÁ¡Àº »ç¿ëÀÚ°¡ ÇÁ·Î±×·¥ÀÇ À̸§À» ½©¿¡ ŸÀÌÇÎÇÑ ÈÄ ¸¦ Ä¡¸é¼­ºÎÅÍÀÌ´Ù. ¶ó¿ìÅÍÀÇ ¸¶Áö¸· ´Ü°è´Â ÇÁ·Î±×·¥ÀÌ ¸Þ¸ð¸®¿¡ ÀûÀçµÇ°í ½ÃÀÛµÉ Áغñ°¡ µÇ¾úÀ» ¶§ÀÌ´Ù. [Root@Seldon prog]# helloworld < Enter > Hello World! ³ª´Â ½ÇÇàÇÏ°íÀÚ ÇÏ´Â ÇÁ·Î±×·¥ ¡®helloworld¡¯ÀÇ À̸§À» ŸÀÌÇÎÇÏ¿© ¿£ÅÍ Å°¸¦ ´­·¶´Ù. ³»°¡ ¿£ÅÍ Å°¸¦ ´­·¶À» ¶§¿Í ¡°Hello World!¡¯¶ó´Â ¹®ÀÚ¿­ÀÌ ÄÜ¼Ö È­¸é¿¡ ³ª¿ÔÀ» ¶§ »çÀÌ¿¡ ¹«¾ùÀÌ Ãß°¡µÇ¾ú´Â°¡? ÀÌ°ÍÀº ¸¶¼úÀΰ¡? ºÐ¸í ¾Æ´Ï´Ù. 1.1. pseudo-shell ÄÚµå ´ÙÀ½Àº ¾ÆÁÖ ±âº»ÀûÀÎ ½© ÇÁ·Î±×·¥ÀÇ pseudo-shell ÄÚµåÀÌ´Ù. #define TRUE 1 ARRAY command ARRAY parameters while(TRUE) { read_command_line(command,parameters); /* Å͹̳ηκÎÅÍ ÀÔ·ÂµÈ °ÍÀ» Àбâ À§ÇØ ±â´Ù¸² */ /* ¿ì¸®ÀÇ ¿¹¿¡¼­´Â, command = "helloworld" */ /* parameters = "" */ pid_t = fork(); /* pid_t´Â ÀÚ½Ä ÇÁ·Î¼¼½ºÀÇ ÇÁ·Î¼¼½º ID¸¦ Æ÷ÇÔÇÏ°í ÀÖÀ½ */ if( pid_t != 0 ) /* ¸¸¾à PID°¡ 0ÀÌ ¾Æ´Ï¶ó¸é ±×¶§´Â... */ { /* Note: PID°¡ ½ÇÇàÀÇ ÀÚ½Ä ¾²·¹µåÀÏ ¶§ PID == 0 */ /* Parent code. */ waitpid(-1,&status,0); /* ÇÁ·Î±×·¥Àº ºÎ¸ð ÇÁ·Î¼¼½º¸¦ Áö¼ÓÇϱâ À§ÇØ */ /* ÀÚ½Ä ÇÁ·Î¼¼½ºÀÇ ½ÇÇà(-1)ÀÇ ³¡À» ±â´Ù¸®°í ÀÖÀ½ */ }else{ /* Child Code. */ execve(command,parameters,0); /* ¸¶Áö¸·À¸·Î, helloworld ÇÁ·Î±×·¥À» ½ÇÇà */ } } Note 1: execve() ÇÔ¼ö´Â ÀÚ½Ä ÇÁ·Î¼¼½º(fork() == 0ÀÏ ¶§)¿¡¼­ È£ÃâµÇ¸ç, waitpid() ¸í·ÉÀº ºÎ¸ð ÇÁ·Î¼¼½º(fork() == pid_t ÀÏ ¶§)¿¡¼­ È£ÃâµÈ´Ù. ÀÌÇØ°¡ µÇÁö ¾Ê´Â°¡? °ÆÁ¤ÇÏÁö ¸¶¶ó. ³ª´Â ÀÌ °¡Â¥ ½© ÄÚµåÀÇ ¸ðµç ºÎºÐÀ» ¾Æ·¡¿¡¼­ ¼³¸íÇÒ °ÍÀÌ´Ù. 1.2. ÀÚ½Ä ÇÁ·Î¼¼½º ¸¸µé±â ¸ÕÀú, ÇÁ·Î±×·¥Àº ¿ì¸®ÀÇ ÇÁ·Î±×·¥ÀÇ ½ÇÇàÀ» ÅëÁ¦Çϱâ À§ÇØ »õ·Î¿î ÇÁ·Î¼¼½º¸¦ ¸¸µé ÇÊ¿ä°¡ ÀÖ´Ù. ÀÌ°ÍÀ» Minix ±×¸®°í Linux¿¡¼­ ÇÏ´Â ¹æ¹ýµéÀÌ ÀÖ´Ù. Minix: ------ do_fork() Linux: ------ fork() vfork() clone() Linux¿¡¼­ vfork()¿Í clone()Àº fork()¿Í °°Àº ±â´ÉÀ» °¡Áö°í ÀÖÁö¸¸ ÇÁ·Î¼¼½º¸¦ °ü¸®Çϴµ¥ À־´Â ¸î °¡Áö Â÷ÀÌÁ¡ÀÌ ÀÖ´Ù. ÀÌ µÎ ÇÔ¼ö¿¡ ´ëÇÑ ´õ ¸¹Àº Á¤º¸´Â linux ¸ÇÆäÀÌÁö¸¦ Âü°íÇضó. ¿ì¸®´Â fork() ÇÔ¼ö¿¡ ³ë·ÂÀÇ ÃÊÁ¡À» ¸ÂÃâ °ÍÀÌ´Ù. fork() ÇÔ¼ö´Â Minix¿Í linux¿¡¼­ °°Àº ÀÏÀ» ÇÑ´Ù. ÀÌ ÇÔ¼ö´Â ¸ðµç ÆÄÀÏ ±â¼ú, º¯¼ö, ·¹Áö½ºÅÍ µîÀ» Æ÷ÇÔÇÏ¿© ºÎ¸ð ÇÁ·Î¼¼½º¸¦ Á¤È®ÇÏ°Ô º¹»çÇÑ´Ù. fork()°¡ È£ÃâµÈ ÈÄ ÀÚ½Ä ¹× ºÎ¸ð ÇÁ·Î¼¼½º´Â ºÐ¸®µÈ ¹æ½ÄÀ» ÃëÇÑ´Ù. ¸ðµç º¯¼öµéÀÇ °ªÀº fork() È£Ã⠽ÿ¡´Â °°À¸³ª, ÀÌÈÄ´Â ºÎ¸ð ¹× ÀÚ½Ä º¯¼öÀÇ °ªÀº º¯ÇÒ °ÍÀÌ°í, ºÎ¸ð ÇÁ·Î¼¼½º¿¡¼­ ½ÇÇàµÈ °ÍµéÀº ÀÚ½Ä ÇÁ·Î¼¼½º¿¡¼­ ½ÇÇàµÈ °Í¿¡ ¿µÇâÀ» ÁÖÁö ¾ÊÀ» °ÍÀÌ´Ù. ºÎ¸ð ¹× ÀÚ½Ä ÇÁ·Î¼¼½º »çÀÌ¿¡ °øÀ¯µÇ´Â À¯ÀÏÇÑ °ÍÀº º¯°æµÉ ¼ö ¾ø´Â ÅؽºÆ® ¼½¼ÇÀÌ´Ù. FORK ½Ã½ºÅÛ È£ÃâÀÌ º¸³»Áö¸é ÀÚ½Ä ÇÁ·Î¼¼½º°¡ ¸¸µé¾îÁø´Ù. ÀÌÁ¦ fork() ÇÔ¼ö°¡ ³¡³ª±â Àü¿¡ ½Ã½ºÅÛ È£ÃâÀº ÇÁ·Î±×·¥¿¡ ÀÚ½Ä ÇÁ·Î¼¼½º È®ÀÎ(PID) °ªÀ» ¸®ÅÏÇÒ °ÍÀÌ´Ù. PID´Â types.h¿¡ ´ÙÀ½°ú °°ÀÌ Á¤ÀÇµÈ Á¤¼ö º¯¼öÀÌ´Ù. Note 1: fork() ÇÁ·Î½ÃÀú´Â FORK ½Ã½ºÅÛ È£ÃâÀ» º¸³¾ °ÍÀÌ´Ù. ÀÌ µÎ °³³ä¿¡ ´ëÇØ È¥µ¿ÇÏÁö ¸»±â¸¦ ¹Ù¶õ´Ù. ------ Minix:Source: minix/include/sys/types.h -- typedef int pid_t; Linux:Source: /posix/sys/types.h -- ifndef __pid_t_defined typedef int __pid_t pid_t; ------ 1.2.1. FORK ½Ã½ºÅÛ È£Ãâ: 9 ´Ü°è FORK ½Ã½ºÅÛ È£ÃâÀÌ ÇÏ´Â 9´Ü°è°¡ ÀÖ´Ù. Note 1: Annex 1¿¡ ³ª¿Í ÀÖ´Â do_fork() ¼Ò½º Äڵ忡 ÀÌ 9 ´Ü°èÀÇ ¸ðµç °ÍÀ» º¼ ¼ö ÀÖ´Ù. Note 2: ¸®´ª½º fork() ÇÔ¼ö ÄÚµå´Â fork.c ÆÄÀÏÀÇ glibc¿¡ ÀÖ´Ù. Note 3: ´ÙÀ½¿¡ ±â¼úµÈ ´Ü°è´Â Minix¿¡¸¸ Àû¿ë °¡´ÉÇϸç, ¸®´ª½ºÀÇ °æ¿ì ±âº»ÀûÀÎ °ÍÀº °°´Ù. ½ÇÁ¦ ´Ù¸¥ °ÍÀº ÇÁ·Î¼¼½º°¡ Ä¿³Î¿¡ ÀÇÇØ ¾î¶»°Ô ¸¸µé¾îÁö´Â°¡ÀÌ´Ù. 1- ÇÁ·Î¼¼½º Å×À̺íÀÌ °¡µæ Â÷ ÀÖ´ÂÁö È®ÀÎ(Annex 1¿¡¼­ 14~16 ¶óÀÎ) ÇÁ·Î¼¼½º Å×À̺íÀ̶õ ¹«¾ùÀΰ¡? ÇÁ·Î¼¼½º Å×À̺íÀº Ä¿³ÎÀÇ ÀϺÎÀÌ´Ù. Å×À̺íÀÇ ¼±¾ðÀº Annex2¿¡ ÀÖ´Ù. ÀÌ Å×À̺íÀº ¸ðµç ÇÁ·Î¼¼½ºÀÇ ·¹Áö½ºÅÍ, ¸Þ¸ð¸® ¸Ê, °è»ê, ¹Þ°í º¸³½ ¸Þ½ÃÁö µîÀ» Æ÷ÇÔÇÏ°í ÀÖ´Ù. Note 1: ÇÁ·Î¼¼½º Å×ÀÌºí¿¡¼­ ½½·ÔÀÇ ¼ö´Â " /include/minix/config.h "¿¡ ÀÖ´Â NR_PROCS¿¡ ÀÇÇØ Á¤ÀǵǾî ÀÖ´Ù. ------ #define NR_PROCS 32 ------ Note 2: Linux¿¡¼­ ÇÁ·Î¼¼½ºÀÇ ÃÖ´ë ¼ö´Â ŽºÅ© º¤ÅÍÀÇ Å©±âÀ̸ç, µðÆúÆ®·Î 512°³ÀÇ Ç׸ñÀ» °¡Áö°í ÀÖ´Ù. 2- ÀÚ½Ä ÇÁ·Î¼¼½ºÀÇ µ¥ÀÌÅÍ¿Í ½ºÅÃÀ» À§ÇØ ¸Þ¸ð¸® ÇÒ´ç (Annex 1¿¡¼­ 21 ~ 26 ¶óÀÎ) 3- ºÎ¸ð ÇÁ·Î¼¼½ºÀÇ µ¥ÀÌÅÍ¿Í ½ºÅÃÀ» ÀÚ½Ä ÇÁ·Î¼¼½ºÀÇ ¸Þ¸ð¸®¿¡ º¹»ç (28 ~34 ¶óÀÎ) 4- ¿©À¯ ÀÖ´Â ÇÁ·Î¼¼½ºÀÇ ½½·ÔÀ» ã¾Æ ±×°Í¿¡ ºÎ¸ð ÇÁ·Î¼¼½ºÀÇ ½½·ÔÀ» º¹»ç (36 ~38 ¶óÀÎ) 5- ÇÁ·Î¼¼½º Å×ÀÌºí¿¡ ÀÚ½Ä ÇÁ·Î¼¼½ºÀÇ ¸Þ¸ð¸® ¸ÊÀ» ÀÔ·Â (41~57 ¶óÀÎ) 6- ÀÚ½Ä ÇÁ·Î¼¼½º¸¦ À§ÇÑ pid ¼±Åà (60 ~69 ¶óÀÎ) Note 1: pid_t´Â signed Á¤¼ö¶ó´Â °ÍÀ» ±â¾ïÇÒ °Í. 7- ÀÚ½Ä ÇÁ·Î¼¼½º¿¡ ´ëÇØ Ä¿³Î°ú ÆÄÀÏ ½Ã½ºÅÛ¿¡ À̾߱â (71~72 ¶óÀÎ) ¿Ö fork ½Ã½ºÅÛ È£ÃâÀº Ä¿³Î°ú ÆÄÀÏ ½Ã½ºÅÛ¿¡ »õ·Î ¸¸µé¾îÁø ÇÁ·Î¼¼½º¿¡ ´ëÇØ ¡®À̾߱⡯ Çϴ°¡? ÀÌÀ¯´Â Minix¿¡¼­ ÇÁ·Î¼¼½º °ü¸®, ¸Þ¸ð¸® °ü¸®, ±×¸®°í ÆÄÀÏ °ü¸®´Â °¢°¢ ºÐ¸®µÈ ¸ðµâ¿¡ ÀÇÇØ Á¶À۵DZ⠶§¹®ÀÌ´Ù. ±×·¡¼­ ÇÁ·Î¼¼½º Å×À̺íÀº 3 ºÎºÐÀ¸·Î ³ª´©¾îÁ® ÀÖÀ¸¸ç, ±×¸®°í ÀÌ ºÎºÐÀÇ °¢°¢Àº ±×°ÍÀÌ ÇÊ¿ä·Î ÇÏ´Â ÇÊ´õ¸¦ °¡Áö°í ÀÖ´Ù. ¸Þ¸ð¸® °ü¸®¿¡¼­ Æ÷ÇÔµÈ ÇÁ·Î¼¼½º Å×À̺íÀÇ ºÎºÐÀº ¡°/src/mm/mproc.h¡± ÆÄÀÏ¿¡ Á¤ÀǵǾî ÀÖ´Ù. ÆÄÀÏ ½Ã½ºÅÛ¿¡ Æ÷ÇÔµÈ ºÎºÐÀº ¡°/src/fs/frpoc.h¡± ÆÄÀÏ¿¡ Á¤ÀǵǾî ÀÖ´Ù. ¸¶Áö¸·À¸·Î Ä¿³Î¿¡ Æ÷ÇÔµÈ °ÍÀº Annex 2¿¡ Á¤ÀǵǾî ÀÖ´Ù. 8- ÀÚ½Ä ÇÁ·Î¼¼½ºÀÇ ¸Þ¸ð¸® ¸ÊÀ» Ä¿³Î¿¡ º¸°íÇÑ´Ù. (Annex 1¿¡¼­ ¶óÀÎ 74~77) 9- ÀÀ´ä ¸Þ½ÃÁö¸¦ ºÎ¸ð ¹× ÀÚ½Ä ÇÁ·Î¼¼½º¿¡ º¸³½´Ù. (Annex 1¿¡¼­ ¶óÀÎ 80~81) Note 1: ÀÚ½Ä ÇÁ·Î¼¼½º¿¡ ´ëÇÑ ¸®ÅÏ °ªÀº 0À̸ç, ºÎ¸ð ÇÁ·Î¼¼½º¿¡ ´ëÇÑ ¸®ÅÏ °ªÀº ±× ÀÚ½Ä ÇÁ·Î¼¼½ºÀÇ PIDÀÌ´Ù. ¿ì¸®°¡ º¼ ¼ö ÀÖµíÀÌ, ½©·ÎºÎÅÍ È£ÃâµÈ ¾î¶² ÇÁ·Î±×·¥ ½ÇÇàÀÇ Ã¹ ºÎºÐÀº ±×·¸°Ô °£´ÜÇÏÁö ¾Ê´Ù. Fork ½Ã½ºÅÛ È£ÃâÀº execve() ¸í·É¿¡ ÀÇÇØ ½ÃÀÛµÈ »õ·Î¿î ÇÁ·Î±×·¥ÀÇ ½ÇÇàÀ» ÅëÁ¦Çϱâ À§ÇØ »õ·Î¿î ÇÁ·Î¼¼½º¸¦ ´ÜÁö ¸¸µé »ÓÀÌ´Ù.±×·¡¼­, ÇÁ·Î¼¼½º °ü¸®ÀÇ Àüü ÇÁ·ÎÅäÄÝÀº ¿ì¸®°¡ do_fork() ÇÁ·Î½ÃÀú¸¦ È£ÃâÇÒ ¶§ Æ÷ÇԵȴÙ. ÀÌ ±Û¿¡¼­´Â ÀÌ ÇÁ·ÎÅäÄÝ¿¡ ´ëÇؼ­´Â ´Ù·çÁö ¾Ê´Â´Ù. ¿Ö³ÄÇϸé ÀÌ ±ÛÀÇ ¸ñÀûÀÌ ¾Æ´Ï±â ¶§¹®ÀÌ´Ù. 1.3: ÇÁ·Î±×·¥ ½ÇÇà ¿ì¸®´Â »õ·Î¿î ÇÁ·Î¼¼½º¸¦ ¸¸µé¾ú°í, ÇÁ·Î±×·¥À» ½ÇÇàÇϱâ À§ÇØ ÀÌ ÇÁ·Î¼¼½º¸¦ »ç¿ëÇÒ °ÍÀÌ´Ù. execve() ÇÔ¼ö´Â "EXEC system call"·Î ¾Ë·ÁÁø »õ·Î¿î ½Ã½ºÅÛ È£ÃâÀ» È£ÃâÇÒ °ÍÀÌ´Ù. ÀÌ ½Ã½ºÅÛ È£ÃâÀº ¹«¾ùÀ» Çϴ°¡? ÀÌ°ÍÀº ÇöÀçÀÇ ¸Þ¸ð¸® À̹ÌÁö¸¦ »õ·Î¿î °ÍÀ¸·Î ´ëüÇÏ°í, ÀÌ »õ·Î¿î ¸Þ¸ð¸® À̹ÌÁö¸¦ À§ÇØ »õ·Î¿î ½ºÅÃÀ» ¼³Á¤ÇÑ´Ù. ¾Æ·¡´Â Minix¿Í ¸®´ª½º¿¡¼­ ÇÁ·Î±×·¥À» ½ÇÇàÇÏ´Â ¹æ¹ýÀÌ´Ù. Minix: ------ do_exec() Note 1: /src/mm/exec.c ¶óÀ̺귯¸®¿¡¼­. /src/fs/misc.c ¿Í /src/kernel/system.c ¶óÀ̺귯¸®¿¡´Â ´Ù¸¥ do_exec() ÇÔ¼öµéÀÌ ÀÖÁö¸¸ À̰͵鿡 ´ëÇؼ­´Â ³ªÁß¿¡ À̾߱â ÇÏ°Ú´Ù. Linux: ------ execve() exec °è¿­ ÇÁ·Î½ÃÀúµéÀÇ ´Ù¸¥ º¯Á¾µéµµ Àִµ¥, ´õ ¸¹Àº Á¤º¸´Â ¸Ç ÆäÀÌÁö¸¦ Âü°íÇضó: execl() execlp() execle() execv() execvp() ÀÚ, ¿ì¸®´Â ¸Þ¸ð¸®¿¡ ¿ì¸®ÀÇ »õ·Î¿î À̹ÌÁöÀÇ Å©±âÀÇ È¦ÀÌ ÀÖ´Ù´Â °ÍÀ» °í·ÁÇÒ °ÍÀÌ´Ù. ³ª´Â ¸ÕÀú ¾î¶»°Ô ÀÌ ÇÁ·Î±×·¥ÀÌ exec ½Ã½ºÅÛ È£Ãâ¿¡ ÀÇÇØ ÅëÁ¦µÇ°í, ÈÄ¿¡ do_exec() ÇÔ¼ö°¡ ¼öÇàÇÏ´Â ¸ðµç ´Ü°è¸¦ º¸¿©ÁÙ °ÍÀÌ´Ù. Fork ½Ã½ºÅÛ È£Ãâ°ú ¸¶Âù°¡Áö·Î ´ÙÀ½ ¼³¸íÀº Minix ¿î¿µÃ¼Á¦¿¡ ´ëÇؼ­µµ ¿ÏÀüÈ÷ ȣȯµÇ¸ç, ÇÏÁö¸¸ ±âº»ÀûÀÎ °ÍÀº Linux¿¡¼­µµ ¸¶Âù°¡Áö´Ù. exec ½Ã½ºÅÛ È£ÃâÀÇ ÅëÁ¦´Â °°À¸¸ç, ¸®´ª½º ÇÏ¿¡¼­´Â Ä¿³Î, MM, FS´Â ¸®´ª½º ½Ã½ºÅÛ¿¡¸¸ Àû¿ëµÇ´Â ¸¹Àº ´Ù¸¥ ±â´ÉÀ¸·Î ´Ù¸¥ ¹æ½ÄÀ¸·Î ±× ¹®Á¦¸¦ ÅëÁ¦ÇÒ ¼ö ÀÖÀ¸¸ç, ÇÏÁö¸¸ ÇÁ·Î¼¼½º´Â °°´Ù. ¿ì¸®°¡ ¡°mv hw pg¡± ¸í·ÉÀ» ½©¿¡ °Ç³×ÁÙ ¶§ execÀÇ Àüü ÇÁ·Î¼¼½º¸¦ ÀÌÇØÇϱâ À§ÇØ »ç¿ëÇÒ ¸Þ¸ð¸® ±¸Á¶°¡ ÀÖ´Ù. Note 1: ¹Ì ¸í·ÉÀº ¡°hw¡± ÆÄÀÏÀ» ¡°pr¡±·Î À̸§À» º¯°æÇÒ °ÍÀÌ´Ù. execve()¿¡ °Ç³×Áø ¹è¿­ ------------------ ÀÎÀÚ ¹è¿­ --------------- | 0 | |---------------| | pr | |---------------| | hw | |---------------| | mv | --------------- Ç¥1.0 ȯ°æ º¯¼ö ¹è¿­ --------------- | 0 | |---------------| | HOME=/root | --------------- Ç¥1.1 execve()¿¡ ÀÇÇÑ ½ºÅà ºôµå: ------------------------- 3 2 1 0 --------------- 40 | \0| t | o | o | |---------------| 36 | r | / | = | E | |---------------| 32 | M | O | H | \0| |---------------| 28 | r | p | \0| w | |---------------| 24 | h | \0| v | m | |---------------| 20 | 0 | |---------------| 16 | 33 | |---------------| 12 | 0 | |---------------| 8 | 30 | |---------------| 4 | 27 | |---------------| 0 | 24 | --------------- Ç¥ 1.2 ¸Þ¸ð¸® °ü¸®ÀÚ¿¡ ÀÇÇØ Àç ÇÒ´ç ÈÄ ½ºÅÃ: ------------------------------------ 3 2 1 0 --------------- 6532 | \0| t | o | o | |---------------| 6528 | r | / | = | E | |---------------| 6524 | M | O | H | \0| |---------------| 6520 | r | p | \0| w | |---------------| 6516 | h | \0| v | m | |---------------| 6512 | 0 | |---------------| 6508 | 6525 | |---------------| 6504 | 0 | |---------------| 6500 | 6522 | |---------------| 6496 | 6519 | |---------------| 6492 | 6516 | --------------- Ç¥1.3 ½ÇÇà ½Ã main()¿¡ ³ªÅ¸³­ ½ºÅÃ: ----------------------------- 3 2 1 0 --------------- 6532 | \0| t | o | o | |---------------| 6528 | r | / | = | E | |---------------| 6524 | M | O | H | \0| |---------------| 6520 | r | p | \0| w | |---------------| 6516 | h | \0| v | m | |---------------| 6512 | 0 | |---------------| 6508 | 6525 | |---------------| 6504 | 0 | |---------------| 6500 | 6522 | |---------------| 6496 | 6519 | |---------------| 6492 | 6516 | |---------------| 6488 | 6508 | <-- envp |---------------| 6484 | 6492 | <-- argv |---------------| 6480 | 3 | <-- argc |---------------| 6476 | return | --------------- Ç¥1.4 ³ª´Â ÀÌ ½ºÅà ±¸ÇöµéÀÌ ¾î¶»°Ô ÀÛ¿ëÇÏ´ÂÁö, ±×·± ÈÄ ¸Þ¸ð¸®¿¡ ÇÁ·Î±×·¥ÀÌ ÀûÀç½ÃÅ°±â À§ÇØ exec ½Ã½ºÅÛ È£Ã⠴ܰ踦 Á¦½ÃÇÒ °ÍÀÌ´Ù. Exec ÇÁ·Î¼¼½º¿¡´Â µÎ °¡Áö Áß¿äÇÑ ¹è¿­ÀÌ ÀÖ´Ù. ±×°ÍÀº environment array(Ç¥1.0)¿Í argument array(Ç¥ 1.1)ÀÌ´Ù. environment arrayÀº ¹®ÀÚ¿­ ¹è¿­À̸ç, ±×°ÍÀº environment·Î½á »õ·Î¿î ÇÁ·Î±×·¥À¸·Î Àü´ÞµÈ´Ù. argument array´Â »õ·Î¿î ÇÁ·Î±×·¥À¸·Î °Ç³×Áø ÀÎÀÚ ¹®ÀÚ¿­ÀÇ ¹è¿­ÀÌ´Ù. ÀÌ µÎ ¹è¿­Àº NULL ¹®ÀÚ(¡°\0¡±)·Î ³¡³¯ ÇÊ¿ä°¡ ÀÖ´Ù. do_exec() ÇÁ·Î½ÃÀú´Â ÀÌÁ¦ ½©ÀÇ ÁÖ¼Ò °ø°£ ³»¿¡ Ãʱ⠽ºÅÃÀ» ¸¶·ÃÇÒ °ÍÀÌ´Ù.(Ç¥ 1.2, Annex 3ÀÇ ¶óÀÎ 049-059). ´ÙÀ½À¸·Î, ±× ÇÁ·Î½ÃÀú´Â MMÀ» È£ÃâÇÏ°í, ÀÌ°ÍÀº »õ·Î ¸¸µé¾îÁø ½ºÅÃÀ» À§ÇØ »õ·Î ¸Þ¸ð¸®¸¦ ÇÒ´çÇÏ°í, ÀÌÀü °ÍÀ» ³»³õ´Â´Ù.(Annex 3¿¡¼­ ¶óÀÎ 062-066) ±× ÇÁ·Î½ÃÀú°¡ Æ÷ÀÎÅ͵é(Annex ¶óÀÎ 077)À» ¼öÁ¤ÇÏ¸é ¸Þ¸ð¸®´Â ÀÌÁ¦ Ç¥ 1.2·ÎºÎÅÍ Ç¥ 1.3ÀÇ ¸Þ¸ð¸® ¸ð¾çÀ» °¡Áö°Ô µÈ´Ù. ¸¶Áö¸·À¸·Î, ¿ì¸®´Â Ãʱâ argc(Annex 3¿¡¼­ ¶óÀÎ 113)¿¡ offsetÀ» ÀúÀåÇÒ °ÍÀÌ´Ù. ÀÌ Ãʱ⠽ºÅà ÀÎÀÚ´Â ¸Þ¸ð¸® °ü¸® ½Ã½ºÅÛ¿¡ ÀÖ´Â ÇÁ·Î½ÃÀú Å×À̺íÀÇ ÀϺÎÀÌ´Ù. "/src/mm/mproc.h" ÆÄÀÏ¿¡ MPROC ±¸Á¶ÀÇ Ãʱ⠽ºÅà À§¿¡ Æ÷ÀÎÅÍ°¡ ÀÖ´Ù. ¸Þ¸ð¸®´Â ÃÖÁ¾ÀûÀ¸·Î Ç¥ 1.4¿Í °°°Ô µÈ´Ù. ÀÌ°ÍÀº ½ÇÇàÀÇ ½ÃÀÛ ½Ã main() ÇÁ·Î½ÃÀú¿¡ ³ªÅ¸³ª´Â ½ºÅà ¸ð½ÀÀÌ´Ù. 1.3.1: C run-time, start-off procedure: --------------------------------------- ÀÌÁ¦ ÇÁ·Î±×·¥ÀÌ ¸ÊÇÎµÇ¾î ½ÇÇàµÇ¾ú´Ù. ÇÏÁö¸¸ ¹®Á¦°¡ ÀÖ´Ù. C ÄÄÆÄÀÏ·¯¿¡ ´ëÇØ main()Àº ´ÜÁö ´Ù¸¥ ÇϳªÀÇ ÇÔ¼öÀÌ´Ù. ÄÄÆÄÀÏ·¯´Â ÀÌ ÇÔ¼ö°¡ ½ÇÇàÇϱâ À§ÇÑ ÇÔ¼öÀÇ ¿£Æ®¸® Æ÷ÀÎÅÍÀÎÁö ¾ËÁö ¸øÇÑ´Ù. ±×·¡¼­ ÄÄÆÄÀÏ·¯´Â Ç¥ÁØ C È£Ãâ ÀåÄ¡¸¦ °í·ÁÇØ(¸¶Áö¸· ÀÎÀÚ¸¦ ¸ÕÀú) 3°³ÀÇ ÀÎÀÚ¿¡ Á¢±ÙÇϱâ À§ÇØ main() ÇÔ¼ö Äڵ带 ÄÄÆÄÀÏ ÇÑ´Ù. ÀÌ °æ¿ì, ¸®ÅÏ ¾îµå·¹½º ¾Õ¿¡ ¼¼ °³ÀÇ ÀÎÀÚ(Çϳª´Â Á¤¼ö, 2°³´Â Æ÷ÀÎÅÍ)¸¦ °¡Áú °ÍÀ¸·Î ÃßÁ¤µÇÁö¸¸ ÀÌ°ÍÀº Ç¥ 3.1ÀÇ °æ¿ì´Â ¾Æ´Ï´Ù. ÀÌ °æ¿ì, ¾î¶»°Ô ¿ì¸®´Â 3°³ÀÇ ÀÎÀÚ¸¦ main() ÇÔ¼ö¿¡ Àü´Þ ÇÒ ¼ö Àִ°¡? ¿ì¸®´Â ÀÛÀº ¾î¼Àºí¸®¾î Äڵ带 ¸¸µé °ÍÀÌ°í, ±×°ÍÀº ÇÁ·Î±×·¥ÀÇ ¾Õ Çì´õ¿¡ »ðÀ﵃ °ÍÀÌ´Ù. ÀÌ ÄÚµå´Â C run-time, start-off procedure, CRTSO¶ó°í ºÒ¸®¸ç, ÀϹÝÀûÀÎ ¸ñÀûÀº ½ºÅÿ¡ 3°³ÀÇ dword¸¦ ´õ Ãß°¡ÇÏ°í, Ç¥ÁØ È£Ãâ ¸í·ÉÀ¸·Î main() ÇÔ¼ö¸¦ È£ÃâÇÏ´Â °ÍÀÌ´Ù. -DWord 1: ARGC: ÇÔ¼ö¿¡ °Ç³×Áö´Â ÀÎÀÚÀÇ ¼ö ŸÀÔ: Á¤¼ö Note 1: Ç¥ 1.4¿¡¼­ ÁÖ¼Ò 0x6476 -DWord 2: ARGV: ÀÎÀÚ ¹è¿­ ¹®ÀÚ¿­¿¡¼­ÀÇ Æ÷ÀÎÅÍ Å¸ÀÔ: Æ÷ÀÎÅÍ Note 1: Ç¥ 1.4¿¡¼­ ÁÖ¼Ò 0x6484¿Í 0x6492¿¡¼­ÀÇ Æ÷ÀÎÅÍ -DWord 3: ENVP: environment ¹è¿­ ¹®ÀÚ¿­¿¡¼­ Æ÷ÀÎÅÍ Å¸ÀÔ: Æ÷ÀÎÅÍ Note 1: Ç¥ 1.4¿¡¼­ ÁÖ¼Ò 0x6488 ¹× 0x6508¿¡¼­ Æ÷ÀÎÅÍ These three dwords are represented in the Figure 1.4. Okay, there is an assembly procedure called CRTSO, but what look like this procedure? Let the hunt begin! The GDB hunting ground is now open! Let us first import our test program ("crtso") in GDB. ----- (gdb) file crtso Reading symbols from crtso...done. ----- Okay, now, we don't have any ideas of where to start to find this legend in the ground. In this case, let us start a point 0, this is the only point that we know his existence. ----- (gdb) disassemble main Dump of assembler code for function main: 0x80481e0
: push %ebp ... 0x80481eb : call 0x8048498 End of assembler dump. ----- There is no information about the CRTSO location. I have an idea. We'll track him in the program by following each function addresses -1 dword, in this case, we'll have the address of the previous function. If we do this to each functions, we'll probably find the root procedure, the CRTSO! Let's begin the tracking with this new method. ----- (gdb) disassemble main-1 Dump of assembler code for function init_dummy: 0x80481d0 : push %ebp ... 0x80481da : lea 0x0(%esi),%esi End of assembler dump. ----- We found the frame_dummy function at adress 0x80481d0 -1. ----- (gdb) disassemble init_dummy-1 Dump of assembler code for function frame_dummy: 0x80481a0 : push %ebp ... 0x80481c9 : lea 0x0(%esi,1),%esi End of assembler dump. ----- We found the fini_dummy fonction at 0x80481a0 -1. ----- (gdb) disassemble frame_dummy-1 Dump of assembler code for function fini_dummy: 0x8048190 : push %ebp ... 0x804819a : lea 0x0(%esi),%esi End of assembler dump. ----- We found the __do_global_dtors_aux fonction at 0x8048190 -1 ----- (gdb) disassemble fini_dummy-1 Dump of assembler code for function __do_global_dtors_aux: 0x8048130 <__do_global_dtors_aux>: push %ebp ... 0x804818d <__do_global_dtors_aux+93>: lea 0x0(%esi),%esi End of assembler dump. ----- We found the call_gmon_start fonction at 0x8048130 -1 ----- (gdb) disassemble __do_global_dtors_aux-1 Dump of assembler code for function call_gmon_start: 0x8048104 : push %ebp ... 0x804812f : nop End of assembler dump. ----- We found the _start fonction at 0x8048104 -1 Hummm, that's an interesting function, that's not? We found it! ----- (gdb) disassemble call_gmon_start-1 Dump of assembler code for function _start: 0x80480e0 <_start>: xor %ebp,%ebp 0x80480e2 <_start+2>: pop %esi 0x80480e3 <_start+3>: mov %esp,%ecx 0x80480e5 <_start+5>: and $0xfffffff0,%esp 0x80480e8 <_start+8>: push %eax 0x80480e9 <_start+9>: push %esp 0x80480ea <_start+10>: push %edx 0x80480eb <_start+11>: push $0x808e220 0x80480f0 <_start+16>: push $0x80480b4 0x80480f5 <_start+21>: push %ecx 0x80480f6 <_start+22>: push %esi 0x80480f7 <_start+23>: push $0x80481e0 0x80480fc <_start+28>: call 0x80481f0 <__libc_start_main> 0x8048101 <_start+33>: hlt 0x8048102 <_start+34>: mov %esi,%esi End of assembler dump. ----- The CRTSO will put the three parameters on the stack by performing three push commands: 0x80480e8 <_start+8>: push %eax ! push argc ( integer ) 0x80480ea <_start+10>: push %edx ! push argv ( pointer ) 0x80480f5 <_start+21>: push %ecx ! push envp ( pointer ) after, the CRTSO will execute the __libc_start_main function (visible in the libc.so.6 library). Than, the __libc_start_main will call the __libc_init_first function and this function will call _init. Then it arrange _fini to be called when the program exit. finally, 0x8048101 <_start+33>: hlt, is called to force a trap if exit fails. After this, all parameters will be on the stack and the main() function of our program will have access to these parameters as shown in the Figure 1.4.