{{{#!jade
Kernel Analysis-HOWTO Roberto Arcomano
berto (at) bertolinux.com
±è³²Çü
pastime (at) ece.uos.ac.kr
0.7 2003-03-26 ÀÌ ¹®¼­¿¡¼­´Â ¸®´ª½º Ä¿³Î¿¡ °üÇÑ ³»¿ë - Áß¿äÇÑ ÄÄÆ÷³ÍÆ®°¡ ¹«¾ùÀ̸ç, ±×µéÀÌ ¾î¶»°Ô µ¿ÀÛÇÏ´ÂÁö - À» ¼³¸íÇÏ°íÀÚ ÇÑ´Ù. ÀÌ HOWTO ¹®¼­´Â Ä¿³Î ¼Ò½º¿¡¼­ 'ƯÁ¤ ÇÔ¼ö' °¡ ¾î¶»°Ô ¼±¾ðµÇ¾ú°í, Á¤ÀǵǾúÀ¸¸ç ´Ù¸¥ ÇÔ¼öµé°ú ¿¬°áµÇ´ÂÁö¸¦ ã°íÀÚ ÇÏ´Â µ¶Àڵ鿡°Ô µµ¿òÀÌ µÉ °ÍÀÌ´Ù. ÀÌ ¹®¼­ÀÇ ÃֽŠ¹öÀüÀº http://www.bertolinux.com ¿¡¼­ ã¾Æº¼ ¼ö ÀÖ´Ù. ÀÌ ¹®¼­¿¡ ´ëÇÑ °³¼±Á¡À̳ª Á¦¾È »çÇ×ÀÌ ÀÖ´Ù¸é ´ç½ÅÀÇ ¾ÆÀ̵ð¾î¸¦ ´ÙÀ½ÀÇ ¸ÞÀÏ ÁÖ¼Ò¸¦ ÅëÇØ º¸³»Áֱ⠹ٶõ´Ù: berto (at) bertolinux.com
¼­¹® ¼­¹® ÀÌ ¹®¼­¿¡¼­´Â ¸®´ª½º Ä¿³ÎÀ» ±¸¼ºÇÏ´Â °¢ ºÎºÐÀ» Á¤ÀÇÇÏ°í ±× ºÎºÐÀ» ¼öÇàÇÏ´Â ÁÖµÈ ÇÔ¼ö¿Í ÀÚ·á ±¸Á¶, ±×¸®°í À̵éÀÌ ¾î¶»°Ô µ¿ÀÛÇÏ´ÂÁö (how the "wheel spins") ¸¦ ¼³¸íÇÏ·Á°í ÇÑ´Ù. ÀÌ ¹®¼­ÀÇ ÃֽŠ¹öÀüÀº http://www.bertolinux.com ¿¡¼­ ã¾Æº¼ ¼ö ÀÖ´Ù. ÀÌ ¹®¼­¿¡ ´ëÇÑ °³¼±Á¡À̳ª Á¦¾È »çÇ×ÀÌ ÀÖ´Ù¸é ´ç½ÅÀÇ ¾ÆÀ̵ð¾î¸¦ ´ÙÀ½ÀÇ ¸ÞÀÏ ÁÖ¼Ò¸¦ ÅëÇØ º¸³»Áֱ⠹ٶõ´Ù: berto (at) bertolinux.com. ÀÌ ¹®¼­¿¡ »ç¿ëµÈ ÄÚµåµéÀº ÀÌ HOWTO ¹®¼­°¡ ¾²¿©Áö°í ÀÖ´Â ½ÃÁ¡¿¡¼­ ÃֽŠ¾ÈÁ¤ ¹öÀüÀÎ ¸®´ª½º Ä¿³Î ¹öÀü 2.4.x ¸¦ ÂüÁ¶ÇÏ¿´´Ù. ÀúÀÛ±Ç Á¤º¸ Copyright (C) 2000,2001,2002 Roberto Arcomano. Copyright (C) 2003 ±è³²Çü (Çѱ¹¾îÆÇ). º» ¹®¼­´Â ¿©·¯ºÐÀÌ ÀÚÀ¯ ¼ÒÇÁÆ®¿þ¾î Àç´Ü(Free Software Foundation)¿¡¼­ ¹ßÇàÇÑ GNU ¶óÀ̺귯¸® ÀÏ¹Ý °ø°³ »ç¿ë±Ç(GNU Library General Public License)ÀÇ ±ÔÁ¤(Áï »ç¿ë±Ç 2ÆÇÀ̳ª ȤÀº ¿©·¯ºÐÀÇ ¼±Åÿ¡ µû¶ó ´õ ÀÌÈÄÀÇ »ç¿ë±Ç)À» ÁؼöÇÏ´Â ÇÑ ÀçÀ¯Æ÷Çϰųª ¼öÁ¤ÇÒ ¼ö ÀÖ´Â ÀÚÀ¯ ¹®¼­ÀÌ´Ù. º» ¹®¼­´Â ÀÌ°ÍÀÌ À¯¿ëÇÏ°Ô »ç¿ëµÇ±â¸¦ ¹Ù¶ó´Â ¸¶À½À¸·Î ¹èÆ÷ÇÏ´Â °ÍÀÌÁö¸¸, ±×¿¡ ´ëÇÑ ¾î¶°ÇÑ º¸Áõµµ ÇÏÁö ¾Ê´Â´Ù: »ó¾÷ÀûÀÎ ¿ëµµ³ª ƯÁ¤ÇÑ ¸ñÀû¿¡ ¸Â°Ô »ç¿ë ÇßÀ»¶§ Àǹ«ÀûÀ¸·Î µû¶ó ºÙ´Â º¸Áõµµ ¾ø´Ù. ´õ ÀÚ¼¼ÇÑ ³»¿ëÀº GNU ¶óÀ̺귯¸® ÀÏ¹Ý ´ëÁß »ç¿ë±Ç (GPL) ¿¡ ´ëÇØ º¸±â ¹Ù¶õ´Ù. GNU GPL ÀÇ º¹»çº»Àº ¿©±â ¿¡¼­ ¾òÀ» ¼ö ÀÖ´Ù. ¹ø¿ª¿¡ °üÇÏ¿© ´ç½ÅÀÌ ÀÌ ¹®¼­¸¦ ¹ø¿ªÇÏ´Â °ÍÀº ÀÚÀ¯ÀÌ´Ù. ÇÏÁö¸¸ ±×Àü¿¡ ´ÙÀ½°ú °°Àº »çÇ×µéÀ» Âü°íÇØ¾ß ÇÒ ÇÊ¿ä°¡ ÀÖ´Ù: ´ç½ÅÀÌ ¹ø¿ªÇؼ­ ¿Ã¸®°íÀÚ ÇÏ´Â LDP ¿¡ ÀÌ¹Ì ÀÌ ¹®¼­ÀÇ ¹ø¿ªº»ÀÌ ÀÖ´ÂÁö üũÇÑ´Ù.   ÀýÀ» À¯ÁöÇÑ´Ù. ( ,  ,  ,   À» Æ÷ÇÔ) TXT ÆÄÀÏÀ̳ª HTML ÆÄÀÏÀ» Á÷Á¢ ¹ø¿ªÇؼ­´Â ¾ÈµÇ°í LYX ÆÄÀÏÀ» ¼öÁ¤ÇØ¾ß ÇÑ´Ù. ±×·¡¾ß¸¸ À̸¦ ÀÌ¿ëÇØ ´Ù¸¥ ÆÄÀÏ Çü½Ä (TXT, HTML, RIFF µî) À¸·Î º¯È¯ÇÒ ¼ö ÀÖ´Ù. "LyX" ÇÁ·Î±×·¥À» »ç¿ëÇϱâ À§Çؼ­ http://www.lyx.org ¿¡¼­ ´Ù¿î·Îµå ¹ÞÀ» ¼ö ÀÖ´Ù. ¹ø¿ªÀ» À§Çؼ­ ³ª¿¡°Ô Áú¹®À» ÇÒ ÇÊ¿ä´Â ¾ø´Ù. ±×Àú ´ç½ÅÀÇ ¹ø¿ª¹°¿¡ °üÇØ (´ç½ÅÀÌ ¿øÇÑ´Ù¸é) ³»°¡ ¾Ë ¼ö ÀÖ°Ô¸¸ ÇØÁÖ¸é µÈ´Ù. ´ç½ÅÀÇ ¹ø¿ª¿¡ °¨»çÇÑ´Ù! °¨»çÀÇ ±Û ÀÌ ¹®¼­¸¦ »¡¸® ¿Ã·ÁÁÖ°í ¹ßÇ¥ÇØ ÁØ The Linux Documentation Project ¿¡ °¨»çÇÑ´Ù. Klaas de Waal ÀÇ Á¦¾È¿¡ °¨»çÇÑ´Ù. »ç¿ëµÈ ¹®¹ý ÇÔ¼öÀÇ ¹®¹ý ÇÔ¼ö¿¡ ´ëÇؼ­ ¼³¸íÇÒ ¶§´Â ´ÙÀ½°ú °°Àº ÇüÅ·Πǥ±âÇÑ´Ù: "ÇÔ¼ö À̸§ [ ÆÄÀÏ À§Ä¡ . È®ÀåÀÚ ]" ¿¹¸¦ µé¾î: "schedule [ kernel/sched.c ]" ¶ó´Â Ç¥ÇöÀÌ ÀÖÀ» ¶§ ÀÌ°ÍÀº ¿ì¸®°¡ Áö±Ý "schedule" À̶ó´Â ÇÔ¼ö¿¡ °üÇؼ­ ¼³¸íÇÏ°í ÀÖÀ½À» ³ªÅ¸³»¸ç, ÀÌ ÇÔ¼ö´Â [ kernel/sched.c ] ¶ó´Â ÆÄÀÏ¿¡¼­ ã¾Æº¼ ¼ö ÀÖÀ½À» ¶æÇÑ´Ù. ¿©±â¼­´Â ½ÃÀÛ µð·ºÅ丮°¡ /usr/src/linux ¶ó°í °¡Á¤ÇÏ°í ÀÖ´Â °ÍÀÌ´Ù. µé¿©¾²±â ¼Ò½º ÄÚµå ¾È¿¡¼­ÀÇ µé¿©¾²±â¿¡´Â 3°³ÀÇ °ø¹é¹®ÀÚ°¡ »ç¿ëµÇ¾ú´Ù. ÇÔ¼ö°£ È£Ã⠺м® (InterCalling Analysis) °³¿ä ÀÌ ¹®¼­¿¡¼­´Â Ä¿³Î ÇÔ¼öµéÀÇ È£Ãâ °ü°è¸¦ Ç¥ÇöÇϱâ À§ÇØ (µé¿©¾²±âÀÇ ¹æ½ÄÀ¸·Î) "ÇÔ¼ö°£ È£Ã⠺м® (InterCalling Analysis : ICA)" À» »ç¿ëÇÑ´Ù. ¿¹¸¦ µé¾î sleep_on À̶ó´Â ÇÔ¼ö¸¦ ÇÔ¼ö°£ È£Ã⠺м®À» ÅëÇØ Ç¥ÇöÇÏ¸é ¾Æ·¡¿Í °°´Ù: |sleep_on |init_waitqueue_entry -- |__add_wait_queue | enqueuing request |list_add | |__list_add -- |schedule --- waiting for request to be executed |__remove_wait_queue -- |list_del | dequeuing request |__list_del -- sleep_on ICA µé¿©¾²±â·Î Ç¥ÇöµÈ ÇÔ¼ö°£ È£Ã⠺м® µÚ¿¡´Â ÇÔ¼öÀÇ À§Ä¡°¡ ³ª¿Â´Ù: sleep_on [kernel/sched.c] init_waitqueue_entry [include/linux/wait.h] __add_wait_queue list_add [include/linux/list.h] __list_add schedule [kernel/sched.c] __remove_wait_queue [include/linux/wait.h] list_del [include/linux/list.h] __list_del ÇÔ¼öÀÇ À§Ä¡°¡ ¹Ù·Î ¾Õ¿¡ Ç¥½ÃÇÑ ÇÔ¼öÀÇ À§Ä¡¿Í °°Àº °æ¿ì¿¡´Â ¸í½ÃÇÏÁö ¾Ê¾Ò´Ù. ¼¼ºÎ»çÇ× ÇÔ¼ö°£ È£Ã⠺м®¿¡¼­ ´ÙÀ½°ú °°Àº ÇüÅ°¡ ÀÖÀ» °ÍÀÌ´Ù: function1 -> function2 ÀÌ°ÍÀº function1 Àº ´Ù¸¥ ÇÔ¼ö¸¦ °¡¸®Å°´Â ÀϹÝÀûÀÎ Æ÷ÀÎÅͶó´Â °ÍÀ» ¶æÇÑ´Ù. À§ÀÇ °æ¿ì¿¡¼­ function1 Àº function2 ¸¦ °¡¸®Å²´Ù. ¶Ç ´ÙÀ½°ú °°Àº ÇüÅ¿¡¼­´Â: function: function Àº ÇÔ¼ö°¡ ¾Æ´ÔÀ» ¶æÇÑ´Ù. ÀÌ°ÍÀº ·¹À̺íÀÌ´Ù (ÀϹÝÀûÀ¸·Î ¾î¼Àºí·¯ ·¹À̺íÀÏ °ÍÀÌ´Ù). ÀÌ ¹®¼­¿¡¼­´Â ¸¹Àº Àý¿¡¼­ C ÄÚµåÀÇ Çüųª ½´µµ-ÄÚµå ÀÇ ÇüÅ·ΠǥÇöÇÏ¿´´Ù. ½ÇÁ¦ÀÇ ¼Ò½º ÆÄÀÏ¿¡´Â À̰͵éÀÌ ¾î¼Àºí·¯ Äڵ峪 ±¸Á¶È­ µÇÁö ¾ÊÀº ÄÚµåÀÇ ÇüÅ·Πµé¾îÀÖÀ» ¼öµµ ÀÖ´Ù. ÀÌ·¯ÇÑ Â÷ÀÌÁ¡Àº ÇнÀÀ» À§ÇÑ °ÍÀÌ´Ù. ÇÔ¼ö°£ È£Ã⠺м®ÀÇ ÀåÁ¡ ÇÔ¼ö°£ È£Ã⠺м® (ICA) ¸¦ »ç¿ëÇϴµ¥ À־ ´ÙÀ½°ú °°Àº ¸¹Àº ÀåÁ¡µéÀÌ ÀÖ´Ù: Ä¿³Î ÇÔ¼ö¸¦ È£ÃâÇÏ¿´À» ¶§ ¾î¶² ÀÏÀÌ ÀϾ´Â °¡¸¦ ÀüüÀûÀ¸·Î ¾Ë ¼ö ÀÖ´Ù. ÇÔ¼öÀÇ µÚ¿¡ ÇÔ¼öÀÇ À§Ä¡°¡ ³ª¿À¹Ç·Î, ÇÔ¼ö°£ È£Ã⠺м®À» ÇϳªÀÇ ÇÔ¼öÀÇ ·¹ÆÛ·±½º ·Îµµ »ç¿ëÇÒ ¼ö ÀÖ´Ù. ÇÔ¼ö°£ È£Ã⠺м®Àº sleep/awake ¸ÞÄ«´ÏÁò¿¡¼­ À¯¿ëÇÏ´Ù. À̸¦ ÀÌ¿ëÇØ ÇÁ·Î¼¼½º°¡ sleep µÇ±â Àü¿¡ ¾î¶² ÀÏÀ» ÇÏ´ÂÁö¿Í (½ºÄÉÁÙ ÀÌÈÄ¿¡) wake up ÀÌÈÄ¿¡ ¹«½¼ ÀÏÀ» ÇÒ °ÍÀÎÁö¸¦ º¼ ¼ö ÀÖ´Ù. ÇÔ¼ö°£ È£Ã⠺м®ÀÇ ´ÜÁ¡ ÇÔ¼ö°£ È£Ã⠺м® (ICA) ¸¦ »ç¿ëÇϴµ¥ À־ ´ÙÀ½°ú °°Àº ´ÜÁ¡µéÀÌ ÀÖ´Ù: ¸ðµç ÀÌ·ÐÀûÀÎ ¸ðµ¨¿¡ À־, ½ÇÁ¦ ¼Ò½ºÄÚµå¿Í ƯÁ¤ÇÑ Á¶°Çµé°ú °°Àº ÀÚ¼¼ÇÑ »çÇ×µéÀ» Á¦¿ÜÇÏ°í ´Ü¼øÈ­ ½ÃÄ×´Ù. ½ºÅÃÀÇ »óÅÂ, µ¥ÀÌŸÀÇ °ª µîÀ» Ç¥ÇöÇϱâ À§Çؼ­´Â Ãß°¡ÀûÀΠǥÇöÀÌ Ãß°¡µÇ¾î¾ß ÇÑ´Ù. ±âÃÊÀûÀÎ ³»¿ë Ä¿³ÎÀ̶õ ¹«¾ùÀΰ¡? Ä¿³ÎÀ̶õ ÄÄÇ»ÅÍ ½Ã½ºÅÛÀÇ ÇÙ½É(core) ºÎºÐÀ» ¸»ÇÑ´Ù. Áï, ÄÄÇ»ÅÍÀÇ ÀÚ¿øµéÀ» »ç¿ëÀÚ°¡ °øÀ¯ÇÒ ¼ö ÀÖµµ·Ï ÇØÁÖ´Â ¼ÒÇÁÆ®¿þ¾î ÀÌ´Ù. Ä¿³ÎÀº (±×·¡ÇÈÀ» ÀÌ¿ëÇÑ °ü¸® ÇÁ·Î±×·¥µµ Æ÷ÇÔÇÒ ¼ö ÀÖ´Â) ¿î¿µÃ¼Á¦ÀÇ ÁÖ¿ä ¼ÒÇÁÆ®¿þ¾î¶ó°í »ý°¢ÇÒ ¼ö ÀÖÀ» °ÍÀÌ´Ù. ¿¹¸¦ µé¾î, (´Ù¸¥ Unix ±â¹ÝÀÇ ¿î¿µÃ¼Á¦¿Í °°ÀÌ) ¸®´ª½º¿¡¼­´Â X À©µµ¿ì ȯ°æÀº Ä¿³Î¿¡ ¼ÓÇØÀÖÁö ¾Ê´Ù. ¿Ö³ÄÇϸé X À©µµ¿ì ȯ°æÀº ¿ÀÁ÷ ±×·¡ÇÈ ¿¬»ê ¸¸À» °ü¸®Çϱ⠶§¹®ÀÌ´Ù. (ºñµð¿À Ä«µå ÀåÄ¡¿¡ Á¢±ÙÇϱâ À§Çؼ­ »ç¿ëÀÚ ¸ðµåÀÇ I/O ¸¦ »ç¿ëÇÑ´Ù.) ´ëÁ¶ÀûÀ¸·Î À©µµ¿ìÁî ȯ°æ (Win9x, WinME, WinNT, Win2K, WinXP µî) ¿¡¼­´Â Ä¿³Î°ú ±×·¡ÇÈ È¯°æÀÌ È¥ÇյǾî ÀÖ´Ù. »ç¿ëÀÚ ¸ðµå¿Í Ä¿³Î ¸ðµå °³¿ä (ÄÄÇ»ÅÍ°¡ ¹æ ÇÑ°³¸¦ Â÷ÁöÇÒ ¸¸Å­ÀÇ Å©±â¿´´ø) ¿¹Àü¿¡´Â »ç¿ëÀÚµéÀÌ ÀÀ¿ë ÇÁ·Î±×·¥À» ½ÇÇà½ÃÅ°´Â °Íµµ ¹«Ã´ Èûµç ÀÏÀ̾ú°í, ¶§¶§·Î ÀÀ¿ë ÇÁ·Î±×·¥ÀÌ ÄÄÇ»Å͸¦ ¸Á°¡¶ß¸®±âµµ ÇÏ¿´´Ù. µ¿ÀÛ ¸ðµå À§¿Í °°ÀÌ ÀÀ¿ë ÇÁ·Î±×·¥ÀÌ ½Ã½ºÅÛÀ» ¸Á°¡¶ß¸®´Â °ÍÀ» ¹æÁöÇϱâ À§ÇØ, ÀÌÈÄÀÇ ¿î¿µÃ¼Á¦µéÀº 2 °¡ÁöÀÇ ´Ù¸¥ µ¿ÀÛ ¸ðµå¸¦ °®µµ·Ï µðÀÚÀεǾú´Ù. Ä¿³Î ¸ðµå: Áß¿äÇÑ ÀڷᱸÁ¶³ª Á÷Á¢ÀûÀÎ Çϵå¿þ¾î Á¢±Ù (I/O ȤÀº memory mapped), Á÷Á¢ÀûÀÎ ¸Þ¸ð¸® Á¢±Ù, IRQ, DMA µîÀÇ Ã³¸® »ç¿ëÀÚ ¸ðµå: »ç¿ëÀÚ°¡ ÀÀ¿ë ÇÁ·Î±×·¥À» ½ÇÇàÇÒ ¼ö ÀÖÀ½ | Applications /|\ | ______________ | | | User Mode | | | ______________ | | | | Implementation | _______ _______ | Abstraction Detail | | Kernel Mode | | | _______________ | | | | | | | | | | \|/ Hardware | Ä¿³Î ¸ðµå¿¡¼­´Â »ç¿ëÀÚ ¸ðµåÀÇ ÀÀ¿ë ÇÁ·Î±×·¥ÀÌ ½Ã½ºÅÛ ÀÚü³ª ½Ã½ºÅÛÀÇ ±â´É¿¡ ¼Õ»óÀ» ÀÔÈ÷´Â °ÍÀ» ¹æÁö ÇÑ´Ù. ±Ù·¡ÀÇ ¸¶ÀÌÅ©·Î ÇÁ·Î¼¼½ºµéÀº Çϵå¿þ¾î ÀûÀ¸·Î ÃÖ¼ÒÇÑ 2 °¡Áö ÀÌ»óÀÇ »óŸ¦ ±¸ÇöÇÏ°í ÀÖ´Ù. ¿¹¸¦ µé¾î ÀÎÅÚ¿¡¼­´Â, 4 °¡Áö »óÅ·ΠPL (Privilege Level: Ư±Ç ·¹º§) °áÁ¤ÇÑ´Ù. Áï, 0, 1, 2, 3 ÀÇ 4 °¡Áö »óŸ¦ »ç¿ëÇÒ ¼ö ÀÖÀ¸¸ç ÀÌ Áß¿¡¼­ Ä¿³Î ¸ðµå´Â 0 À» »ç¿ëÇÑ´Ù. À¯´Ð½º ±â¹ÝÀÇ ¿î¿µÃ¼Á¦´Â ¿ÀÁ÷ 2 ´Ü°èÀÇ Æ¯±Ç ·¹º§À» ÇÊ¿ä·Î Çϸç, ¾ÕÀ¸·Î ÀÌ·¯ÇÑ °³³äÀÌ ÄÚµå »ó¿¡¼­ ¾î¶»°Ô ÀÌ¿ëµÇ´ÂÁö º¸°Ô µÉ °ÍÀÌ´Ù. »ç¿ëÀÚ ¸ðµå¿¡¼­ Ä¿³Î ¸ðµå·Î Àüȯ ¾ðÁ¦ ÀÌ·¯ÇÑ ÀüȯÀÌ ÀϾ´Â°¡? À§ÀÇ 2 °¡Áö ¸ðµå¸¦ ÀÌÇØÇß´Ù¸é, ´ÙÀ½À¸·Î ÀÌ·¯ÇÑ 2 °¡Áö ¸ðµå »çÀÌÀÇ ÀüȯÀÌ ¾ðÁ¦ ÀϾ´ÂÁö¸¦ ¾Ë¾Æ¾ß ÇÑ´Ù. ÀϹÝÀûÀ¸·Î ÀÌ·¯ÇÑ ÀüȯÀÌ ÀϾ´Â °æ¿ì´Â ´ÙÀ½ÀÇ 2 °¡Áö °æ¿ìÀÌ´Ù: ½Ã½ºÅÛ ÄÝÀ» È£ÃâÇßÀ» ¶§: ½Ã½ºÅÛ ÄÝÀ» È£ÃâÇÑ ÀÌÈÄ¿¡, ÇÁ·Î¼¼½º´Â ÀÚµ¿ÀûÀ¸·Î Ä¿³Î ¸ðµå¿¡ ÀÖ´Â Äڵ带 È£ÃâÇÑ´Ù. IRQ (ȤÀº ¿¹¿Ü) °¡ ¹ß»ýÇßÀ» ¶§: ÀÎÅÍ·´Æ® ¿äû (InterRupt reQuest: IRQ) ÀÌ ¹ß»ýÇÑ ÈÄ¿¡, ÀÎÅÍ·´Æ® Çڵ鷯 (ȤÀº ¿¹¿Ü Çڵ鷯) °¡ È£ÃâµÇ°í, (ÀÎÅÍ·´Æ® 󸮰¡ ³¡³ª¸é) Á¦¾î°æ·Î´Â ¾Æ¹« Àϵµ ¾ø¾ú´ø µíÀÌ (»ç¿ëÀÚ ¸ðµåÀÇ) ÇÁ·Î¼¼½º·Î µ¹¾Æ°£´Ù. ½Ã½ºÅÛ ÄÝ ½Ã½ºÅÛ ÄÝÀº Ä¿³Î ¸ðµå ³»¿¡ ÀÖ´Â ¿î¿µÃ¼Á¦ ·çƾµéÀ» °ü¸®Çϴ Ưº°ÇÑ ÇÔ¼ö¶ó°í ÇÒ ¼ö ÀÖ´Ù. ½Ã½ºÅÛ ÄÝÀº ´ÙÀ½°ú °°Àº °æ¿ì¿¡ È£ÃâµÈ´Ù: I/O ÀåÄ¡³ª ÆÄÀÏ¿¡ Á¢±ÙÇÒ ¶§ (read/write) Ư±ÇÀÌ ÀÖ´Â Á¤º¸¿¡ Á¢±ÙÇÒ ÇÊ¿ä°¡ ÀÖÀ» ¶§ (pid, ½ºÄÉÁÙ¸µ Á¤Ã¥ µî) ½ÇÇà ȯ°æÀ» ¹Ù²ã¾ß ÇÒ ¶§ (fork, exec) ƯÁ¤ÇÑ ¸í·ÉÀ» ¼öÇàÇØ¾ß ÇÒ ¶§ (chdir, kill, brk, signal µî) | | ------->| System Call i | (Accessing Devices) | | | | [sys_read()] | | ... | | | | | system_call(i) |-------- | | | [read()] | | | | ... | | | | system_call(j) |-------- | | | [get_pid()] | | | | | ... | ------->| System Call j | (Accessing kernel data structures) | | | [sys_getpid()]| | | USER MODE KERNEL MODE Unix System Calls Working ½Ã½ºÅÛ ÄÝÀº »ç¿ëÀÚ ¸ðµå¿¡¼­ ·Î¿ì ·¹º§ÀÇ ÀÚ¿ø (Çϵå¿þ¾î) °ú Åë½ÅÀ» À§ÇØ »ç¿ëÇÒ ¼ö ÀÖ´Â °ÅÀÇ À¯ÀÏÇÑ ÀÎÅÍÆäÀ̽ºÀÌ´Ù. ÀÌ¿¡ ´ëÇÑ ´Ü ÇϳªÀÇ ¿¹¿Ü »çÇ×À¸·Î´Â ÇÁ·Î¼¼½º¿¡¼­ ioperm À» È£ÃâÇÑ °æ¿ìÀÌ´Ù. ÀÌ °æ¿ì¿¡´Â »ç¿ëÀÚ ¸ðµå¿¡¼­ ÀåÄ¡¿¡ Á÷Á¢ Á¢±ÙÇÒ ¼ö ÀÖ´Ù. (IRQ ´Â »ç¿ëµÇÁö ¾Ê´Â´Ù.) ¸ðµç C ¾ð¾î ÇÔ¼ö°¡ ½Ã½ºÅÛ ÄÝÀÎ °ÍÀÌ ¾Æ´Ï¶ó ±×Áß ÀϺΠ¸¸ÀÌ ½Ã½ºÅÛ ÄÝÀÌ´Ù. ´ÙÀ½ÀÇ ¸®½ºÆ®´Â ¸®´ª½º Ä¿³Î 2.4.17 ÀÇ ½Ã½ºÅÛ ÄÝÀÇ ¸ñ·ÏÀ» º¸¿©ÁØ´Ù. [ arch/i386/kernel/entry.S ] ¿ªÀÚÁÖ: ÇöÀç ÃֽŠĿ³Î ¹öÀüÀÎ 2.4.21 ¿¡´Â À̺¸´Ù ´õ ¸¹Àº ½Ã½ºÅÛ ÄÝÀÇ ¸ñ·ÏÀÌ ÀÖÁö¸¸ Áö±Ý ´Ü°è¿¡¼­´Â ±× Â÷ÀÌÁ¡¿¡ Å« Àǹ̰¡ ¾øÀ» °Í °°¾Æ ±×³É ¿ø¹®¿¡ ÀÖ´Â ´ë·Î¸¸ ¸ñ·ÏÀ» ÀÛ¼ºÇÏ¿´´Ù. °ü½ÉÀÌ ÀÖ´Â »ç¶÷Àº ÇØ´ç ÆÄÀÏÀ» Á÷Á¢ È®ÀÎÇØ º¸±â ¹Ù¶õ´Ù. .long SYMBOL_NAME(sys_ni_syscall) /* 0 - old "setup()" system call*/ .long SYMBOL_NAME(sys_exit) .long SYMBOL_NAME(sys_fork) .long SYMBOL_NAME(sys_read) .long SYMBOL_NAME(sys_write) .long SYMBOL_NAME(sys_open) /* 5 */ .long SYMBOL_NAME(sys_close) .long SYMBOL_NAME(sys_waitpid) .long SYMBOL_NAME(sys_creat) .long SYMBOL_NAME(sys_link) .long SYMBOL_NAME(sys_unlink) /* 10 */ .long SYMBOL_NAME(sys_execve) .long SYMBOL_NAME(sys_chdir) .long SYMBOL_NAME(sys_time) .long SYMBOL_NAME(sys_mknod) .long SYMBOL_NAME(sys_chmod) /* 15 */ .long SYMBOL_NAME(sys_lchown16) .long SYMBOL_NAME(sys_ni_syscall) /* old break syscall holder */ .long SYMBOL_NAME(sys_stat) .long SYMBOL_NAME(sys_lseek) .long SYMBOL_NAME(sys_getpid) /* 20 */ .long SYMBOL_NAME(sys_mount) .long SYMBOL_NAME(sys_oldumount) .long SYMBOL_NAME(sys_setuid16) .long SYMBOL_NAME(sys_getuid16) .long SYMBOL_NAME(sys_stime) /* 25 */ .long SYMBOL_NAME(sys_ptrace) .long SYMBOL_NAME(sys_alarm) .long SYMBOL_NAME(sys_fstat) .long SYMBOL_NAME(sys_pause) .long SYMBOL_NAME(sys_utime) /* 30 */ .long SYMBOL_NAME(sys_ni_syscall) /* old stty syscall holder */ .long SYMBOL_NAME(sys_ni_syscall) /* old gtty syscall holder */ .long SYMBOL_NAME(sys_access) .long SYMBOL_NAME(sys_nice) .long SYMBOL_NAME(sys_ni_syscall) /* 35 */ /* old ftime syscall holder */ .long SYMBOL_NAME(sys_sync) .long SYMBOL_NAME(sys_kill) .long SYMBOL_NAME(sys_rename) .long SYMBOL_NAME(sys_mkdir) .long SYMBOL_NAME(sys_rmdir) /* 40 */ .long SYMBOL_NAME(sys_dup) .long SYMBOL_NAME(sys_pipe) .long SYMBOL_NAME(sys_times) .long SYMBOL_NAME(sys_ni_syscall) /* old prof syscall holder */ .long SYMBOL_NAME(sys_brk) /* 45 */ .long SYMBOL_NAME(sys_setgid16) .long SYMBOL_NAME(sys_getgid16) .long SYMBOL_NAME(sys_signal) .long SYMBOL_NAME(sys_geteuid16) .long SYMBOL_NAME(sys_getegid16) /* 50 */ .long SYMBOL_NAME(sys_acct) .long SYMBOL_NAME(sys_umount) /* recycled never used phys() */ .long SYMBOL_NAME(sys_ni_syscall) /* old lock syscall holder */ .long SYMBOL_NAME(sys_ioctl) .long SYMBOL_NAME(sys_fcntl) /* 55 */ .long SYMBOL_NAME(sys_ni_syscall) /* old mpx syscall holder */ .long SYMBOL_NAME(sys_setpgid) .long SYMBOL_NAME(sys_ni_syscall) /* old ulimit syscall holder */ .long SYMBOL_NAME(sys_olduname) .long SYMBOL_NAME(sys_umask) /* 60 */ .long SYMBOL_NAME(sys_chroot) .long SYMBOL_NAME(sys_ustat) .long SYMBOL_NAME(sys_dup2) .long SYMBOL_NAME(sys_getppid) .long SYMBOL_NAME(sys_getpgrp) /* 65 */ .long SYMBOL_NAME(sys_setsid) .long SYMBOL_NAME(sys_sigaction) .long SYMBOL_NAME(sys_sgetmask) .long SYMBOL_NAME(sys_ssetmask) .long SYMBOL_NAME(sys_setreuid16) /* 70 */ .long SYMBOL_NAME(sys_setregid16) .long SYMBOL_NAME(sys_sigsuspend) .long SYMBOL_NAME(sys_sigpending) .long SYMBOL_NAME(sys_sethostname) .long SYMBOL_NAME(sys_setrlimit) /* 75 */ .long SYMBOL_NAME(sys_old_getrlimit) .long SYMBOL_NAME(sys_getrusage) .long SYMBOL_NAME(sys_gettimeofday) .long SYMBOL_NAME(sys_settimeofday) .long SYMBOL_NAME(sys_getgroups16) /* 80 */ .long SYMBOL_NAME(sys_setgroups16) .long SYMBOL_NAME(old_select) .long SYMBOL_NAME(sys_symlink) .long SYMBOL_NAME(sys_lstat) .long SYMBOL_NAME(sys_readlink) /* 85 */ .long SYMBOL_NAME(sys_uselib) .long SYMBOL_NAME(sys_swapon) .long SYMBOL_NAME(sys_reboot) .long SYMBOL_NAME(old_readdir) .long SYMBOL_NAME(old_mmap) /* 90 */ .long SYMBOL_NAME(sys_munmap) .long SYMBOL_NAME(sys_truncate) .lng SYMBOL_NAME(sys_ftruncate) .long SYMBOL_NAME(sys_fchmod) .long SYMBOL_NAME(sys_fchown16) /* 95 */ .long SYMBOL_NAME(sys_getpriority) .long SYMBOL_NAME(sys_setpriority) .long SYMBOL_NAME(sys_ni_syscall) /* old profil syscall holder */ .long SYMBOL_NAME(sys_statfs) .long SYMBOL_NAME(sys_fstatfs) /* 100 */ .long SYMBOL_NAME(sys_ioperm) .long SYMBOL_NAME(sys_socketcall) .long SYMBOL_NAME(sys_syslog) .long SYMBOL_NAME(sys_setitimer) .long SYMBOL_NAME(sys_getitimer) /* 105 */ .long SYMBOL_NAME(sys_newstat) .long SYMBOL_NAME(sys_newlstat) .long SYMBOL_NAME(sys_newfstat) .long SYMBOL_NAME(sys_uname) .long SYMBOL_NAME(sys_iopl) /* 110 */ .long SYMBOL_NAME(sys_vhangup) .long SYMBOL_NAME(sys_ni_syscall) /* old "idle" system call */ .long SYMBOL_NAME(sys_vm86old) .long SYMBOL_NAME(sys_wait4) .long SYMBOL_NAME(sys_swapoff) /* 115 */ .long SYMBOL_NAME(sys_sysinfo) .long SYMBOL_NAME(sys_ipc) .long SYMBOL_NAME(sys_fsync) .long SYMBOL_NAME(sys_sigreturn) .long SYMBOL_NAME(sys_clone) /* 120 */ .long SYMBOL_NAME(sys_setdomainname) .long SYMBOL_NAME(sys_newuname) .long SYMBOL_NAME(sys_modify_ldt) .long SYMBOL_NAME(sys_adjtimex) .long SYMBOL_NAME(sys_mprotect) /* 125 */ .long SYMBOL_NAME(sys_sigprocmask) .long SYMBOL_NAME(sys_create_module) .long SYMBOL_NAME(sys_init_module) .long SYMBOL_NAME(sys_delete_module) .long SYMBOL_NAME(sys_get_kernel_syms) /* 130 */ .long SYMBOL_NAME(sys_quotactl) .long SYMBOL_NAME(sys_getpgid) .long SYMBOL_NAME(sys_fchdir) .long SYMBOL_NAME(sys_bdflush) .long SYMBOL_NAME(sys_sysfs) /* 135 */ .long SYMBOL_NAME(sys_personality) .long SYMBOL_NAME(sys_ni_syscall) /* for afs_syscall */ .long SYMBOL_NAME(sys_setfsuid16) .long SYMBOL_NAME(sys_setfsgid16) .long SYMBOL_NAME(sys_llseek) /* 140 */ .long SYMBOL_NAME(sys_getdents) .long SYMBOL_NAME(sys_select) .long SYMBOL_NAME(sys_flock) .long SYMBOL_NAME(sys_msync) .long SYMBOL_NAME(sys_readv) /* 145 */ .long SYMBOL_NAME(sys_writev) .long SYMBOL_NAME(sys_getsid) .long SYMBOL_NAME(sys_fdatasync) .long SYMBOL_NAME(sys_sysctl) .long SYMBOL_NAME(sys_mlock) /* 150 */ .long SYMBOL_NAME(sys_munlock) .long SYMBOL_NAME(sys_mlockall) .long SYMBOL_NAME(sys_munlockall) .long SYMBOL_NAME(sys_sched_setparam) .long SYMBOL_NAME(sys_sched_getparam) /* 155 */ .long SYMBOL_NAME(sys_sched_setscheduler) .long SYMBOL_NAME(sys_sched_getscheduler) .long SYMBOL_NAME(sys_sched_yield) .long SYMBOL_NAME(sys_sched_get_priority_max) .long SYMBOL_NAME(sys_sched_get_priority_min) /* 160 */ .long SYMBOL_NAME(sys_sched_rr_get_interval) .long SYMBOL_NAME(sys_nanosleep) .long SYMBOL_NAME(sys_mremap) .long SYMBOL_NAME(sys_setresuid16) .long SYMBOL_NAME(sys_getresuid16) /* 165 */ .long SYMBOL_NAME(sys_vm86) .long SYMBOL_NAME(sys_query_module) .long SYMBOL_NAME(sys_poll) .long SYMBOL_NAME(sys_nfsservctl) .long SYMBOL_NAME(sys_setresgid16) /* 170 */ .long SYMBOL_NAME(sys_getresgid16) .long SYMBOL_NAME(sys_prctl) .long SYMBOL_NAME(sys_rt_sigreturn) .long SYMBOL_NAME(sys_rt_sigaction) .long SYMBOL_NAME(sys_rt_sigprocmask) /* 175 */ .long SYMBOL_NAME(sys_rt_sigpending) .long SYMBOL_NAME(sys_rt_sigtimedwait) .long SYMBOL_NAME(sys_rt_sigqueueinfo) .long SYMBOL_NAME(sys_rt_sigsuspend) .long SYMBOL_NAME(sys_pread) /* 180 */ .long SYMBOL_NAME(sys_pwrite) .long SYMBOL_NAME(sys_chown16) .long SYMBOL_NAME(sys_getcwd) .long SYMBOL_NAME(sys_capget) .long SYMBOL_NAME(sys_capset) /* 185 */ .long SYMBOL_NAME(sys_sigaltstack) .long SYMBOL_NAME(sys_sendfile) .long SYMBOL_NAME(sys_ni_syscall) /* streams1 */ .long SYMBOL_NAME(sys_ni_syscall) /* streams2 */ .long SYMBOL_NAME(sys_vfork) /* 190 */ .long SYMBOL_NAME(sys_getrlimit) .long SYMBOL_NAME(sys_mmap2) .long SYMBOL_NAME(sys_truncate64) .long SYMBOL_NAME(sys_ftruncate64) .long SYMBOL_NAME(sys_stat64) /* 195 */ .long SYMBOL_NAME(sys_lstat64) .long SYMBOL_NAME(sys_fstat64) .long SYMBOL_NAME(sys_lchown) .long SYMBOL_NAME(sys_getuid) .long SYMBOL_NAME(sys_getgid) /* 200 */ .long SYMBOL_NAME(sys_geteuid) .long SYMBOL_NAME(sys_getegid) .long SYMBOL_NAME(sys_setreuid) .long SYMBOL_NAME(sys_setregid) .long SYMBOL_NAME(sys_getgroups) /* 205 */ .long SYMBOL_NAME(sys_setgroups) .long SYMBOL_NAME(sys_fchown) .long SYMBOL_NAME(sys_setresuid) .long SYMBOL_NAME(sys_getresuid) .long SYMBOL_NAME(sys_setresgid) /* 210 */ .long SYMBOL_NAME(sys_getresgid) .long SYMBOL_NAME(sys_chown) .long SYMBOL_NAME(sys_setuid) .long SYMBOL_NAME(sys_setgid) .long SYMBOL_NAME(sys_setfsuid) /* 215 */ .long SYMBOL_NAME(sys_setfsgid) .long SYMBOL_NAME(sys_pivot_root) .long SYMBOL_NAME(sys_mincore) .long SYMBOL_NAME(sys_madvise) .long SYMBOL_NAME(sys_getdents64) /* 220 */ .long SYMBOL_NAME(sys_fcntl64) .long SYMBOL_NAME(sys_ni_syscall) /* reserved for TUX */ .long SYMBOL_NAME(sys_ni_syscall) /* Reserved for Security */ .long SYMBOL_NAME(sys_gettid) .long SYMBOL_NAME(sys_readahead) /* 225 */ IRQ À̺¥Æ® IRQ °¡ ¹ß»ýÇϸé ÇöÀç ½ÇÇàÁßÀÎ ÇÁ·Î¼¼½º´Â IRQ Çڵ鷯¸¦ ½ÇÇàÇϱâ À§ÇØ ÀÎÅÍ·´Æ® µÈ´Ù. IRQ °¡ ó¸®µÈ ÈÄ, Á¦¾î °æ·Î´Â ¸¶Ä¡ ¾Æ¹« Àϵµ ¾ø´ø °Íó·³ ÀÎÅÍ·´Æ®°¡ °É¸° ÁöÁ¡À¸·Î µÇµ¹¾Æ °£´Ù. Running Task |-----------| (3) NORMAL | | | [break execution] IRQ Handler EXECUTION (1)| | | ------------->|---------| | \|/ | | | does | IRQ (2)---->| .. |-----> | some | | | |<----- | work | BACK TO | | | | | ..(4). | NORMAL (6)| \|/ | <-------------|_________| EXECUTION |___________| [return to code] (5) USER MODE KERNEL MODE User->Kernel Mode Transition caused by IRQ event ¾Æ·¡ÀÇ ¼ø¼­°¡ ¸Å°ÜÁø ´Ü°è´Â À§ÀÇ ±×¸²¿¡¼­ ³ªÅ¸³ª´Â À̺¥Æ®ÀÇ ¹øÈ£¿¡ ÇØ´çÇÑ´Ù: ÇÁ·Î¼¼½º°¡ ½ÇÇàµÇ°í ÀÖÀ½ ½ÇÇà µµÁß IRQ ¹ß»ý ÇÁ·Î¼¼½º´Â ÀÎÅÍ·´Æ® µÇ°í ÀÎÅÍ·´Æ® Çڵ鷯 È£Ãâ ÀÎÅÍ·´Æ® Çڵ鷯 ÄÚµå ¼öÇà Á¦¾î °æ·Î´Â (¾Æ¹« Àϵµ ¾ø´ø °Íó·³) »ç¿ëÀÚ ¸ðµåÀÇ ÇÁ·Î¼¼½º·Î µ¹¾Æ°¨ ÇÁ·Î¼¼½º°¡ ´Ù½Ã ½ÇÇà ƯÈ÷ °ü½ÉÀÖ°Ô ÁöÄѺ¸¾Æ¾ß ÇÒ °ÍÀº Timer IRQ ÀÌ´Ù. Timer IRQ ´Â ŸÀ̸Ӱ¡ ¼³Á¤µÈ ¸Å ½Ã°£ °£°Ý (ms ´ÜÀ§) ¸¶´Ù ¹ß»ýÇÏ¸ç ´ÙÀ½°ú °°Àº °ÍµéÀ» °ü¸®ÇÑ´Ù: ¾Ë¶÷ (ÇÁ·Î¼¼½º ½ºÄÉÁÙ¸µ À̳ª Åë°è µî¿¡¼­ »ç¿ëµÇ´Â) ½Ã½ºÅÛ Ä«¿îÅÍ¿Í Å½ºÅ© Ä«¿îÅÍ Å¸ÀÓ ½½¶óÀ̽º ¿ªÀÚÁÖ: ÇÁ·Î¼¼½º°¡ Çѹø¿¡ ¿¬¼ÓÀûÀ¸·Î ¼öÇàµÉ ¼ö ÀÖ´Â ½Ã°£ °£°ÝÀ» ¸»ÇÑ´Ù. ¿¡ ±â¹ÝÀ» µÐ ¸ÖƼ ŽºÅ· ¸ÖƼŽºÅ· ¸ÞÄ«´ÏÁò ÃÖ±ÙÀÇ ¿î¿µÃ¼Á¦¿¡¼­ÀÇ ÇÙ½ÉÀº ŽºÅ© (task, ÀÛ¾÷) ¿ªÀÚÁÖ: ¹ø¿ª°úÁ¤¿¡¼­ ŽºÅ© ¿Í 'ÇÁ·Î¼¼½º' °¡ °°Àº Àǹ̷Π»ç¿ëµÈ °æ¿ì°¡ ¸¹´Ù. ÀÌ´Ù. ŽºÅ©´Â ¸Þ¸ð¸® »ó¿¡¼­ µ¿ÀÛÇÏ´Â ÀÀ¿ë ÇÁ·Î±×·¥À¸·Î¼­ ´Ù¸¥ ŽºÅ© µé°ú ¸ðµç ÀÚ¿øµéÀ» (CPU ¿Í ¸Þ¸ð¸® µîÀ» Æ÷ÇÔ) °øÀ¯ÇÑ´Ù. ÀÌ·¯ÇÑ ÀÚ¿øÀÇ °øÀ¯ ´Â ¸ÖƼŽºÅ· ¸ÞÄ«´ÏÁò ¿¡ ÀÇÇؼ­ °ü¸®µÈ´Ù. ¸ÖƼŽºÅ· ¸ÞÄ«´ÏÁòÀº ŸÀÓ ½½¶óÀ̽º ·Î Á¤ÇØÁø ½Ã°£ÀÌ È帣¸é ÇöÀçÀÇ Å½ºÅ©¸¦ ´Ù¸¥ ŽºÅ©·Î ±³Ã¼ÇÑ´Ù. »ç¿ëÀÚ´Â ¸ðµç ÀÚ¿øÀ» Á¡À¯ÇÏ°í ÀÖ´Â °Í °°Àº ȯ»ó ¿¡ ºüÁö°Ô µÈ´Ù. ¶ÇÇÑ ÇѸíÀÇ »ç¿ëÀÚ°¡ ½Ã½ºÅÛÀ» »ç¿ëÇÏ°í ÀÖ´Â ½Ã³ª¸®¿À¸¦ »ý°¢ÇØ º¸¸é, ¸¶Âù°¡Áö·Î »ç¿ëÀÚ´Â ¸¹Àº ŽºÅ©µéÀÌ µ¿½Ã¿¡ ¼öÇàµÇ°í ÀÖ´Â °Í°ú °°Àº ȯ»ó ¿¡ ºüÁö°Ô µÈ´Ù. ÀÌ·¯ÇÑ ¸ÖƼŽºÅ·À» ±¸ÇöÇϱâ À§Çؼ­ ŽºÅ©´Â ´ÙÀ½°ú °°Àº »óÅ º¯¼ö¸¦ °¡Áø´Ù: READY, ½ÇÇàÇÒ Áغñ°¡ µÇ¾î ÀÖ´Ù. BLOCKED, ÀÚ¿øÀ» ±â´Ù¸®°í ÀÖ´Ù. ŽºÅ©ÀÇ »óÅ´ ±×¿¡ °ü·ÃµÈ ¸®½ºÆ® (READY ¸®½ºÆ®¿Í BLOCKED ¸®½ºÆ®) ³»¿¡ ŽºÅ©°¡ ¼ÓÇØ ÀÖ´ÂÁö¿¡ ÀÇÇؼ­ °ü¸®µÈ´Ù. ŽºÅ© ±³È¯ (task switching) (½ÇÇàÁßÀÎ) ÇÑ Å½ºÅ©¿¡¼­ ´Ù¸¥ ŽºÅ©·Î À̵¿ÇÏ´Â °ÍÀ» ŽºÅ© ±³È¯ (context switching (¹®¸Æ ±³È¯) À̶ó°í ºÎ¸£±âµµ ÇÑ´Ù) À̶ó°í ÇÑ´Ù. ¸¹Àº ÄÄÇ»ÅÍ´Â ÀÌ·¯ÇÑ ÀÛ¾÷À» ÀÚµ¿À¸·Î ¼öÇàÇØ ÁÖ´Â Çϵå¿þ¾îÀûÀÎ ¸í·ÉÀ» °¡Áö°í ÀÖ´Ù. ŽºÅ© ±³È¯Àº ´ÙÀ½°ú °°Àº °æ¿ì¿¡ ÀϾ´Ù: ŸÀÓ ½½¶óÀ̽º Á¾·á ÈÄ: ½ÇÇàÇÒ Áغñ°¡ µÈ ŽºÅ©¸¦ ½ºÄÉÁÙ¸µÇÏ¿© ½ÇÇàÇÑ´Ù. ŽºÅ©°¡ ¾î¶² ÀåÄ¡¸¦ ±â´Ù¸®´Â °æ¿ì: »õ·Î¿î ŽºÅ©¸¦ ½ºÄÉÁÙ¸µÇÏ¿© ±³È¯ÇÑ´Ù. ŽºÅ©°¡ ´Ù¸¥ ¿¬»êÀ» ¼öÇàÇÏÁö ¾Ê°í ÀåÄ¡¸¦ ±â´Ù¸®´Â °æ¿ì (Busy Form Waiting) À» ¹æÁöÇϱâ À§ÇØ ´Ù¸¥ ŽºÅ©¸¦ ½ºÄÉÁÙ¸µÇÑ´Ù. ŽºÅ© ±³È¯Àº Schedule °³Ã¼¿¡ ÀÇÇؼ­ °ü¸®µÈ´Ù. Timer | | IRQ | | Schedule | | | ________________________ |----->| Task 1 |<------------------>|(1)Chooses a Ready Task | | | | |(2)Task Switching | | |___________| |________________________| | | | /|\ | | | | | | | | | | | | | | | | |----->| Task 2 |<-------------------------------| | | | | | |___________| | . . . . . . . . . . . . . . . | | | | | | | | ------>| Task N |<-------------------------------- | | |___________| Task Switching based on TimeSlice ¸®´ª½º¿¡¼­ ŸÀÓ ½½¶óÀ̽º´Â ÀϹÝÀûÀ¸·Î 10 ms ÀÌ´Ù. | | | | Resource _____________________________ | Task 1 |----------->|(1) Enqueue Resource request | | | Access |(2) Mark Task as blocked | | | |(3) Choose a Ready Task | |___________| |(4) Task Switching | |_____________________________| | | | | | | | | | Task 2 |<------------------------- | | | | |___________| Task Switching based on Waiting for a Resource ¸¶ÀÌÅ©·ÎÄ¿³Î OS ¿Í ¸ð³î¸®Æ½ OS °³¿ä Áö±Ý±îÁö ¿ì¸®°¡ »ìÆ캻 °ÍÀº ¸ð³î¸®Æ½ OS ¶ó ºÒ¸®´Â °Íµé À̾úÁö¸¸, ¸¶ÀÌÅ©·ÎÄ¿³Î À̶ó°í ÇÏ´Â ¹æ½ÄÀÇ ¿î¿µÃ¼Á¦µµ ÀÖ´Ù. ¸¶ÀÌÅ©·ÎÄ¿³Î ¹æ½ÄÀÇ ¿î¿µÃ¼Á¦´Â »ç¿ëÀÚ ¸ðµåÀÇ ÇÁ·Î¼¼½º´Â ¹°·Ð Ç÷ÎÇÇ µð½ºÅ© °ü·Ã ŽºÅ©, ÇÏµå µð½ºÅ© °ü·Ã ŽºÅ©, ³×Æ®¿öÅ© °ü·Ã ÀÛ¾÷ µî Ä¿³ÎÀÌ Ã³¸®ÇÏ´Â ÀÛ¾÷ µéµµ ŽºÅ© ¹æ½ÄÀ¸·Î ó¸®ÇÑ´Ù. ÀÌ·¯ÇÑ ¹æ½ÄÀÇ ¿î¿µÃ¼Á¦·Î´Â Amoeba, Mach µîÀÌ ÀÖ´Ù. ¸¶ÀÌÅ©·Î Ä¿³Î ¹æ½ÄÀÇ Àå´ÜÁ¡ ÀåÁ¡: °¢°¢ÀÇ Å½ºÅ©´Â ÇÑ°¡Áö Á¾·ùÀÇ ¿¬»ê ¸¸À» ¼öÇàÇϹǷΠ¿î¿µÃ¼Á¦ÀÇ ÀÔÀå¿¡¼­´Â À̸¦ °ü¸®ÇϱⰡ ½¬¿öÁø´Ù. ±×·¡¼­ ¸¸¾à ³×Æ®¿öÅ© ºÎºÐÀ» ¼öÁ¤ÇÏ°í ½Í´Ù¸é À̸¦ ´ã´çÇϴ ŽºÅ© ¸¸À» ¼öÁ¤ÇÏ¸é µÉ °ÍÀÌ´Ù. (´Ù¸¥ ºÎºÐÀÇ ±¸Á¶ÀûÀÎ º¯È­°¡ ¾ø´Â ÀÌ»óÀûÀÎ °æ¿ì¶ó¸é) ´ÜÁ¡: ƯÁ¤ÇÑ Å½ºÅ©·Î ÁøÀÔÇÏ´Â ½Ã°£°ú ±× ŽºÅ©¿¡¼­ º¹±ÍÇÏ´Â ½Ã°£¸¸Å­ÀÇ 2 ¹èÀÇ Å½ºÅ© Àüȯ ½Ã°£ÀÌ Ãß°¡µÇ¾î¾ß ÇϹǷΠ¸ð³î¸®Æ½ ¹æ½ÄÀÇ ¿î¿µÃ¼Á¦º¸´Ù ¼º´ÉÀ» ¶³¾îÁö°Ô µÈ´Ù. °³ÀÎÀûÀÎ ÀÇ°ßÀ¸·Î´Â ¸¶ÀÌÅ©·ÎÄ¿³Î ¹æ½ÄÀº ±³À°¿ë ¿¹Á¦·Î´Â ÀûÀýÇÏÁö¸¸ (Minix ó·³) ½ÇÁ¦·Î Àû¿ëµÉ ¼ö ÀÖÀ» ¸¸Å­ ÃÖÀûÀÇ ¿î¿µÃ¼Á¦´Â ¾Æ´Ï¶ó°í »ý°¢ÇÑ´Ù. ¸®´ª½º¿¡¼­´Â ¸¶ÀÌÅ©·ÎÄ¿³ÎÀÇ ±¸Á¶¸¦ ¾à°£ ±¸ÇöÇÏ¿© Ä¿³Î ½º·¹µå ¶ó°í ºÒ¸®´Â ¸î°¡Áö ŽºÅ©¸¦ »ç¿ëÇÑ´Ù. (ÇÏµå µð½ºÅ©¿Í °°Àº ÀúÀå ÀåÄ¡¿¡¼­ (½º¿Ò¾Æ¿ôµÈ) ÆäÀÌÁö¸¦ ´Ù½Ã ¹Þ¾Æ¿À´Â kswapd ¿Í °°Àº ŽºÅ©°¡ ÀÖ´Ù.) ÀÌ °æ¿ì ½º¿ÍÇÎÀº ¸Å¿ì ´À¸° ÀÛ¾÷À̱⠶§¹®¿¡ ¼º´É¸é¿¡¼­ ¹®Á¦µÉ °ÍÀº ¾ø´Ù. ³×Æ®¿öÅ· ISO ÀÇ OSI °èÃþ ISO-OSI Ç¥ÁØÀº ´ÙÀ½°ú °°Àº °èÃþµé·Î ÀÌ·ç¾îÁø ³×Æ®¿öÅ© ±¸Á¶¸¦ ¼³¸íÇÏ°í ÀÖ´Ù: ¹°¸®ÀûÀÎ °èÃþ (¿¹: PPP, Ethernet) µ¥ÀÌŸ-¸µÅ© °èÃþ (¿¹: PPP, Ethernet) ³×Æ®¿öÅ© °èÃþ (¿¹: IP, X.25) Àü¼Û °èÃþ (¿¹: TCP, UDP) ¼¼¼Ç °èÃþ (¿¹: SSL) Ç¥Çö °èÃþ (¿¹: FTP ÀÇ binary-ascii ÄÚµù) ÀÀ¿ë °èÃþ (¿¹: ³×½ºÄÉÀÌÇÁ¿Í °°Àº ÀÀ¿ë ÇÁ·Î±×·¥) À§ÀÇ ¸®½ºÆ® Áß¿¡¼­ óÀ½ 2 °³ÀÇ °èÃþÀº ÁÖ·Î Çϵå¿þ¾î·Î ±¸ÇöµÈ´Ù. ³ª¸ÓÁö °èÃþµéÀº ¼ÒÇÁÆ®¿þ¾î¿¡ ¼ÓÇÑ´Ù. (ȤÀº Æß¿þ¾î³ª ¶ó¿ìÅÍ) ¿î¿µÃ¼Á¦´Â ¸¹Àº ÇÁ·ÎÅäÄÝÀ» »ç¿ëÇÏ°í ÀÖÀ¸¸ç ±× ÁßÀÇ Çϳª·Î´Â TCP/IP ¸¦ µé ¼ö ÀÖ´Ù. (ÀÌ°ÍÀº 3-4 °èÃþÀÇ °¡Àå ÁÖµÈ ÇÁ·ÎÅäÄÝÀÌ´Ù.) Ä¿³ÎÀº ¹«½¼ ÀÏÀ» Çϴ°¡? ISO-OSI °èÃþÀÇ Ã³À½ 2 °¡Áö¿¡ ´ëÇؼ­´Â Ä¿³ÎÀº (ÁÖ¼Ò¸¦ Á¦¿ÜÇÏ°í) ¾Æ¹« °Íµµ ¾ËÁö ¸øÇÑ´Ù. RX (¼ö½Å) ½Ã¿¡ Ä¿³ÎÀÌ ÇÏ´Â ÀÏÀº: (ÀÌ´õ³Ý Ä«µå³ª ¸ðµ©°ú °°Àº) ·Î¿ì ·¹º§ ÀåÄ¡¿ÍÀÇ ¿¬°á(handshake)À» °ü¸®ÇÏ°í ±× ÀåÄ¡µé·ÎºÎÅÍ ÇÁ·¹ÀÓ ¿ªÀÚÁÖ: ½ÇÁ¦·Î ³×Æ®¿öÅ© »óÀ¸·Î ÀüÇØÁö´Â ºñÆ®¿­ÀÇ Á¤º¸ À» ¹Þ¾Æ¿Â´Ù. ±× (ÀÌ´õ³ÝÀ̳ª PPP °°Àº) ÇÁ·¹ÀÓ À¸·ÎºÎÅÍ TCP/IP ÆÐŶ À» ±¸¼ºÇÑ´Ù. ÆÐŶ À» ¼ÒÄÏ À¸·Î º¯È¯ÇÏ¿© (Æ÷Æ® ¹øÈ£¿¡ ¸Â´Â) ÀûÀýÇÑ ÀÀ¿ëÇÁ·Î±×·¥¿¡°Ô ³Ñ°ÜÁְųª ÆÐŶ À» ÀûÀýÇÑ Å¥¿¡ º¸³»ÁØ´Ù. frames packets sockets NIC ---------> Kernel ----------> Application | packets --------------> Forward - RX - TX (¼Û½Å) ½Ã¿¡ Ä¿³ÎÀÌ ÇÏ´Â ÀÏÀº: ¼ÒÄÏ À» ÆÐŶ À¸·Î º¯È¯Çϰųª Å¥¿¡ µé¾îÀÖ´Â Á¤º¸¸¦ °¡Á®¿Í¼­ ÆÐŶ À» ±¸¼ºÇÑ´Ù. ÆÐŶ À» (ÀÌ´õ³ÝÀ̳ª PPP ¿¡¼­ »ç¿ëµÇ´Â) ÇÁ·¹ÀÓ À¸·Î ºÐ¸®ÇÑ´Ù. Çϵå¿þ¾î ÀåÄ¡¸¦ »ç¿ëÇؼ­ ÇÁ·¹ÀÓ À» Àü¼ÛÇÑ´Ù. sockets packets frames Application ---------> Kernel ----------> NIC packets /|\ Forward ------------------- - TX - °¡»ó ¸Þ¸ð¸® ¼¼±×¸ÕÅ×ÀÌ¼Ç (Segmentation) ¼¼±×¸ÕÅ×À̼ÇÀº ¸Þ¸ð¸® ÇÒ´ç ¹®Á¦¸¦ ÇØ°áÇϴ ù¹ø° ¹æ¹ýÀÌ´Ù: À̸¦ ÀÌ¿ëÇÏ¸é ¼Ò½ºÄڵ尡 ¸Þ¸ð¸® »óÀÇ ¾î´À ºÎºÐ¿¡ ³õÀÌ°Ô µÉÁö¸¦ ½Å°æ¾²Áö ¾Ê°íµµ ÇÁ·Î±×·¥À» ÄÄÆÄÀÏÇÒ ¼ö ÀÖ´Ù. ½ÇÁ¦·Î ÀÌ·¯ÇÑ ±â´ÉÀº ÀÀ¿ë ÇÁ·Î±×·¥ °³¹ßÀÚ¿¡°Ô OS ¿Í Çϵå¿þ¾î¿¡ µ¶¸³ÀûÀÎ ÇÁ·Î±×·¥À» °³¹ßÇÒ ¼ö ÀÖµµ·Ï ÇØÁØ´Ù. | Stack | | | | | \|/ | | Free | | /|\ | Segment <---> Process | | | | Heap | | Data uninitialized | | Data initialized | | Code | |____________________| Segment ¼¼±×¸ÕÆ®´Â ÇÁ·Î±×·¥ÀÇ ³í¸®ÀûÀÎ °³Ã¼, ȤÀº ¸Þ¸ð¸® »óÀÇ ÇÁ·Î±×·¥¿¡ ´ëÇÑ À̹ÌÁö¶ó°í ¸» ÇÒ ¼ö ÀÖ´Ù. ÇÁ·Î±×·¡¹Ö½Ã¿¡ ¿ì¸®´Â µ¥ÀÌŸ°¡ ¸Þ¸ð¸® »óÀÇ ¾î´À ºÎºÐ¿¡ ³õÀÌ°Ô µÉ Áö ÀüÇô °í·ÁÇÏÁö ¾Ê´Â´Ù. ¿ÀÁ÷ ¼¼±×¸ÕÆ® (ÇÁ·Î±×·¥) ³»¿¡¼­ÀÇ À§Ä¡(offset)¿¡ ´ëÇؼ­¸¸ »ý°¢ÇÒ »ÓÀÌ´Ù. º¸Åë °¢°¢ÀÇ ÇÁ·Î¼¼½º¿¡ ´ëÇؼ­ ÇϳªÀÇ ¼¼±×¸ÕÆ®¸¦ ÇÒ´çÇϰųª ȤÀº ±× ¹Ý´ëÀÌÁö¸¸ ¸®´ª½º¿¡¼­´Â ±×·¸°Ô ÇÏÁö ¾Ê´Â´Ù. ¸®´ª½º¿¡¼­´Â Ä¿³Î°ú ´Ù¸¥ ¸ðµç ÇÁ·Î¼¼½ºµé¿¡ ´ëÇØ ¿ÀÁ÷ 4 °³ÀÇ ¼¼±×¸ÕÆ® ¸¸À» »ç¿ëÇÑ´Ù. ¼¼±×¸ÕÅ×À̼ÇÀÇ ¹®Á¦Á¡ ____________________ ----->| |-----> | IN | Segment A | OUT ____________________ | |____________________| | |____| | | | Segment B | | Segment B | | |____ | | |____________________| | |____________________| | | Segment C | | |____________________| ----->| Segment D |-----> IN |____________________| OUT Segmentation problem À§ÀÇ ±×¸²¿¡¼­ A ¿Í D ¶ó´Â ÇÁ·Î¼¼½º(¼¼±×¸ÕÆ®)¸¦ ¾ø¾Ö°í »õ·Î B ¶ó´Â ÇÁ·Î¼¼½º¸¦ Áý¾î³Ö´Â °æ¿ì¸¦ »ý°¢Çغ¸ÀÚ. ÀÌ °æ¿ì B °¡ µé¾î°¥ ¸¸ÇÑ ÃæºÐÇÑ ¸Þ¸ð¸® °ø°£ÀÌ ÀÖÁö¸¸ ÇÁ·Î¼¼½º¸¦ 2 °³·Î ³ª´­ ¼ö ¾øÀ¸¹Ç·Î °á±¹ ¸Þ¸ð¸®·Î ·ÎµåÇÏÁö ¸øÇÑ´Ù. (¸Þ¸ð¸® ºÎÁ·) ÀÌ·¯ÇÑ ¹®Á¦°¡ ¹ß»ýÇÏ´Â ÀÌÀ¯´Â ¼¼±×¸ÕÆ®´Â (³í¸®ÀûÀÎ °ø°£À̱⠶§¹®¿¡) ¿¬¼ÓµÈ °ø°£ÀÌ°í ³ª´©¾î Áú ¼ö ¾ø±â ¶§¹®ÀÌ´Ù. ÆäÀÌÁö³×ÀÌ¼Ç (Pagination) ____________________ | Page 1 | |____________________| | Page 2 | |____________________| | .. | Segment <---> Process |____________________| | Page n | |____________________| | | |____________________| | | |____________________| Segment ÆäÀÌÁö³×ÀÌ¼Ç ('ÆäÀÌ¡' À̶ó°í Çϱ⵵ ÇÑ´Ù) À̶õ ¸Þ¸ð¸®¸¦ °íÁ¤µÈ ±æÀÌÀÇ n °³ÀÇ Á¶°¢À¸·Î ³ª´©´Â °ÍÀÌ´Ù. ÇÁ·Î¼¼½º´Â Çϳª ÀÌ»óÀÇ ÆäÀÌÁö·Î ·ÎµåµÉ ¼ö ÀÖ´Ù. ¸Þ¸ð¸®°¡ ÇØÁ¦µÇ¸é ¸ðµç ÆäÀÌÁö°¡ ÇØÁ¦µÈ´Ù. (¾ÕÀÇ   Âü°í) ÆäÀÌÁö³×À̼ÇÀº ½º¿ÍÇÎ (swapping) À̶ó°í ÇÏ´Â ¶ÇÇϳªÀÇ Áß¿äÇÑ ¸ñÀûÀ» À§Çؼ­µµ »ç¿ëµÈ´Ù. ¸¸¾à ÆäÀÌÁö°¡ ½ÇÁ¦ ¸Þ¸ð¸® »ó¿¡ Á¸ÀçÇÏÁö ¾Ê´Â´Ù¸é ¿¹¿Ü (Exception) ¸¦ ¹ß»ý½ÃÅ°°í, ÀÌ´Â Ä¿³ÎÀÌ ¸Þ¸ð¸® »ó¿¡ »õ·Î¿î ÆäÀÌÁö¸¦ ã°Ô ÇÑ´Ù. ÀÌ ¸ÞÄ«´ÏÁòÀº ¿î¿µÃ¼Á¦¿¡¼­ ½ÇÁ¦ ¸Þ¸ð¸®°¡ Çã¿ëÇÏ´Â °Íº¸´Ù ´õ ¸¹Àº ÀÀ¿ë ÇÁ·Î±×·¥À» ¸Þ¸ð¸® »ó¿¡ ·ÎµåÇÒ ¼ö ÀÖ°Ô ÇØÁØ´Ù. ÆäÀÌÁö³×À̼ÇÀÇ ¹®Á¦Á¡ ____________________ Page X | Process Y | |____________________| | | | WASTE | | SPACE | |____________________| Pagination Problem À§ÀÇ ±×¸²À» º¸¸é ÆäÀÌÁö³×ÀÌ¼Ç Á¤Ã¥ÀÇ ¹®Á¦Á¡À» ¾Ë ¼ö ÀÖÀ» °ÍÀÌ´Ù: ÇÁ·Î¼¼½º Y °¡ ÆäÀÌÁö X ¿¡ ·ÎµåµÇ´Â °æ¿ì, ÇϳªÀÇ ÆäÀÌÁö¿¡ ÇØ´çÇÏ´Â Àüü ¿µ¿ªÀÌ ÇÒ´çµÇ¹Ç·Î µÚÂÊÀÇ ³ª¸ÓÁö ¿µ¿ªÀº ³¶ºñµÈ´Ù. ¼¼±×¸ÕÅ×À̼ǰú ÆäÀÌÁö³×ÀÌ¼Ç ¼¼±×¸ÕÅ×À̼ǰú ÆäÀÌÁö³×À̼ÇÀÇ ¹®Á¦Á¡À» ÇØ°áÇϱâ À§Çؼ­ 2 °¡Áö Á¤Ã¥À» È¥ÇÕÇؼ­ »ç¿ëÇÑ´Ù. | .. | |____________________| ----->| Page 1 | | |____________________| | | .. | ____________________ | |____________________| | | |---->| Page 2 | | Segment X | ----| |____________________| | | | | .. | |____________________| | |____________________| | | .. | | |____________________| |---->| Page 3 | |____________________| | .. | (¼¼±×¸ÕÆ® X ·Î ±¸ºÐµÇ´Â) ÇÁ·Î¼¼½º X ´Â 3 ºÎºÐÀ¸·Î ³ª´©¾îÁö°í °¢°¢Àº ÆäÀÌÁö·Î ·ÎµåµÈ´Ù. ÀÌ·Î ÀÎÇØ ´ÙÀ½°ú °°Àº ¹®Á¦Á¡ÀÌ ÇØ°áµÈ´Ù: ¼¼±×¸ÕÅ×À̼ÇÀÇ ¹®Á¦Á¡: ¸Þ¸ð¸®¸¦ ÆäÀÌÁö ´ÜÀ§·Î ÇÒ´çÇÏ°í ÇØÁ¦Çϱ⠶§¹®¿¡ ¸Þ¸ð¸® °ü¸®¸¦ ÃÖÀûÈ­µÈ ¹æ¹ýÀ¸·Î ÇÒ ¼ö ÀÖ´Ù. ÆäÀÌÁö³×À̼ÇÀÇ ¹®Á¦Á¡: ¿ÀÁ÷ ¸¶Áö¸· ÆäÀÌÁö ¸¸ÀÌ ³¶ºñµÈ´Ù. ÇÏÁö¸¸ ¸Å¿ì ÀÛÀº Å©±âÀÇ ÆäÀÌÁö¸¦ »ç¿ëÇϵµ·Ï °áÁ¤ÇÒ ¼ö ÀÖ°í - ¿¹¸¦ µé¾î 4096 ¹ÙÀÌÆ®¸¦ ÇÑ ÆäÀÌÁö·Î ¼³Á¤ÇÑ´Ù¸é ÃÖ´ë 4096 * ŽºÅ©ÀÇ ¼ö ¸¸Å­ÀÇ ¹ÙÀÌÆ®°¡ ³¶ºñµÉ °ÍÀÌ´Ù - ÆäÀÌÁö¸¦ °èÃþÀûÀ¸·Î (2-3 ´Ü°è·Î) °ü¸®ÇÒ ¼ö ÀÖ´Ù. | | | | | | Offset2 | Value | | | /|\| | Offset1 | |----- | | | /|\ | | | | | | | | | | \|/| | | | | ------>| | \|/ | | | | Base Paging Address ---->| | | | | ....... | | ....... | | | | | Hierarchical Paging ¸®´ª½ºÀÇ ½ÃÀÛ ¿©±â¼­´Â startup_32: ¶ó°í ÇÏ´Â ·¹ÀÌºí¿¡¼­ ½ÃÀ۵Ǵ C ÄÚµåºÎÅÍ »ìÆ캻´Ù. |startup_32: |start_kernel |lock_kernel |trap_init |init_IRQ |sched_init |softirq_init |time_init |console_init |#ifdef CONFIG_MODULES |init_modules |#endif |kmem_cache_init |sti |calibrate_delay |mem_init |kmem_cache_sizes_init |pgtable_cache_init |fork_init |proc_caches_init |vfs_caches_init |buffer_init |page_cache_init |signals_init |#ifdef CONFIG_PROC_FS |proc_root_init |#endif |#if defined(CONFIG_SYSVIPC) |ipc_init |#endif |check_bugs |smp_init |rest_init |kernel_thread |unlock_kernel |cpu_idle startup_32 [arch/i386/kernel/head.S] start_kernel [init/main.c] lock_kernel [include/asm/smplock.h] trap_init [arch/i386/kernel/traps.c] init_IRQ [arch/i386/kernel/i8259.c] sched_init [kernel/sched.c] softirq_init [kernel/softirq.c] time_init [arch/i386/kernel/time.c] console_init [drivers/char/tty_io.c] init_modules [kernel/module.c] kmem_cache_init [mm/slab.c] sti [include/asm/system.h] calibrate_delay [init/main.c] mem_init [arch/i386/mm/init.c] kmem_cache_sizes_init [mm/slab.c] pgtable_cache_init [arch/i386/mm/init.c] fork_init [kernel/fork.c] proc_caches_init vfs_caches_init [fs/dcache.c] buffer_init [fs/buffer.c] page_cache_init [mm/filemap.c] signals_init [kernel/signal.c] proc_root_init [fs/proc/root.c] ipc_init [ipc/util.c] check_bugs [include/asm/bugs.h] smp_init [init/main.c] rest_init kernel_thread [arch/i386/kernel/process.c] unlock_kernel [include/asm/smplock.h] cpu_idle [arch/i386/kernel/process.c] ¸¶Áö¸· ºÎºÐÀÇ rest_init ¶ó´Â ÇÔ¼ö´Â ´ÙÀ½°ú °°Àº ÀÏÀ» ÇÑ´Ù: init ¶ó´Â Ä¿³Î ¾²·¹µå¸¦ ½ÃÀÛ½ÃŲ´Ù. kernel_unlock À» È£ÃâÇÑ´Ù. ½ÇÇàÇÒ ÇÁ·Î¼¼½º°¡ ¾Æ¹« °Íµµ ¾ø´Â °æ¿ì¿¡ ½ÇÇàµÉ ºÎºÐÀÎ cpu_idle ·çƾÀ» ½ÇÇàÇÑ´Ù. »ç½Ç start_kernel ÇÔ¼ö´Â Àý´ë ³¡³ªÁö ¾Ê´Â´Ù. ÀÌ ÇÔ¼ö´Â ³¡¾øÀÌ cpu_idle ·çƾÀ» ½ÇÇà½ÃŲ´Ù. ´ÙÀ½Àº ù¹ø° Ä¿³Î ¾²·¹µåÀÎ init ÇÔ¼ö¿¡ ´ëÇÑ ¼³¸íÀÌ´Ù: |init |lock_kernel |do_basic_setup |mtrr_init |sysctl_init |pci_init |sock_init |start_context_thread |do_init_calls |(*call())-> kswapd_init |prepare_namespace |free_initmem |unlock_kernel |execve ¸®´ª½ºÀÇ Æ¯Â¡ °³¿ä ¸®´ª½º´Â ´Ù¸¥ ¿î¿µÃ¼Á¦µé°ú ±¸ºÐµÇ´Â ´ÙÀ½°ú °°Àº Ư¡µéÀ» °¡Áö°í ÀÖ´Ù: ÆäÀÌÁö³×À̼Ǹ¸À» »ç¿ë ¼ÒÇÁÆ®¿þ¾î ÀÎÅÍ·´Æ® (softirq) Ä¿³Î ¾²·¹µå Ä¿³Î ¸ðµâ proc µð·ºÅ丮 À¯¿¬¼ºÀ» À§ÇÑ ¿ä¼Òµé À§¿¡¼­ ¿­°ÅÇÑ 4 ¹ø°¿Í 5 ¹ø° Ư¡Àº Ä¡¸íÀûÀÎ Ä¿³Î ¹ö±×³ª ƯÁ¤ÇÑ ¹®Á¦°¡ ¹ß»ýÇÏ¿´À» ¶§ ½Ã½ºÅÛÀ» ¸®ºÎÆÃÇÏÁö ¾Ê°í (½Ã½ºÅÛ °ü¸®ÀÚ°¡) »ç¿ëÀÚ ¸ðµå¿¡¼­ ¹®Á¦¸¦ ÇØ°áÇϰųª ½Ã½ºÅÛÀ» °ü¸®ÇÒ ¼ö ÀÖ´Â ¸·´ëÇÑ À¯¿¬¼ºÀ» Á¦°øÇÑ´Ù. ¿¹¸¦ µé¾î ´ëÇü ¼­¹ö¿¡¼­ ƯÁ¤ ºÎºÐÀ» ¼öÁ¤ÇÒ ÇÊ¿ä°¡ ÀÖÀ» ¶§ ¸®ºÎÆÃÀ» ÇÏÁö ¾Ê°í ÇØ°áÇϱâ À§Çؼ­ Ä¿³Î ¸ðµâÀ» ÀÌ¿ëÇÒ ¼ö ÀÖ´Ù. ÆäÀÌÁö³×À̼Ǹ¸À» »ç¿ë ¸®´ª½º¿¡¼­´Â °¢°¢ÀÇ Å½ºÅ©¸¦ ±¸ºÐÇϱâ À§ÇØ ¼¼±×¸ÕÅ×À̼ÇÀ» »ç¿ëÇÏÁö ¾Ê°í ÆäÀÌÁö³×À̼ÇÀ» »ç¿ëÇÑ´Ù. (¸ðµç ŽºÅ©´Â ¿ÀÁ÷ 2 °³ÀÇ ¼¼±×¸ÕÆ® (ÄÚµå ¼¼±×¸ÕÆ®¿Í µ¥ÀÌŸ (½ºÅÃ) ¼¼±×¸ÕÆ®) ¸¦ »ç¿ëÇÒ »ÓÀÌ´Ù.) °¢°¢ÀÇ Å½ºÅ©´Â ÀڽŸ¸ÀÇ ÆäÀÌÁö Å×À̺íÀ» »ç¿ëÇϹǷΠ¼­·Î ´Ù¸¥ ŽºÅ© °£ÀÇ ÆäÀÌÁö °ü·Ã ¿À·ù´Â Àý´ë ÀϾÁö ¾Ê´Â´Ù°í ¸»ÇÒ ¼ö ÀÖ´Ù. ¾î¶² °æ¿ì¿¡ À־´Â ¿©·¯ ŽºÅ©µéÀÌ ÇϳªÀÇ ÆäÀÌÁö Å×À̺íÀ» ÂüÁ¶Çϱ⵵ Çϴµ¥, °øÀ¯ ¶óÀ̺귯¸®¿Í °°Àº °æ¿ì (¸Þ¸ð¸®¸¦ Àý¾àÇϱâ À§ÇØ) ÄÚµå ºÎºÐÀ» °øÀ¯ÇÏ°í µ¥ÀÌŸ´Â °¢ ŽºÅ©ÀÇ ½ºÅÿ¡ ÀúÀåÇÏ´Â ¹æ½ÄÀ» »ç¿ëÇÑ´Ù. ¸®´ª½º ¼¼±×¸ÕÆ® ¸®´ª½º Ä¿³Î¿¡¼­´Â ´ÙÀ½°ú °°Àº ¿ÀÁ÷ 4 °³ÀÇ ¼¼±×¸ÕÆ® ¸¸ÀÌ Á¸ÀçÇÑ´Ù: Ä¿³Î ÄÚµå ¼¼±×¸ÕÆ® [0x10] Ä¿³Î µ¥ÀÌŸ/½ºÅà ¼¼±×¸ÕÆ® [0x18] »ç¿ëÀÚ ÄÚµå ¼¼±×¸ÕÆ® [0x23] »ç¿ëÀÚ µ¥ÀÌŸ/½ºÅà ¼¼±×¸ÕÆ® [0x2b] ¸ñÀû [¼¼±×¸ÕÆ®] ÀÇ ÇüÅ·ΠǥÇöÇÏ¿´´Ù. ÀÎÅÚ CPU ÀÇ °æ¿ì, ´ÙÀ½°ú °°Àº ¼¼±×¸ÕÆ® ·¹Áö½ºÅ͵éÀÌ »ç¿ëµÈ´Ù: CS - ÄÚµå ¼¼±×¸ÕÆ® DS - µ¥ÀÌŸ ¼¼±×¸ÕÆ® SS - ½ºÅà ¼¼±×¸ÕÆ® ES - ¿¹ºñ ¼¼±×¸ÕÆ® (¼­·Î ´Ù¸¥ ¼¼±×¸ÕÆ®¿¡ ¼ÓÇÑ ¸Þ¸ð¸® ¿µ¿ªÀ» º¹»çÇÏ´Â ÀÏ µîÀ» ¼öÇàÇÒ ¶§ ÇÊ¿äÇÏ´Ù) ±×·¡¼­ ¸ðµç ŽºÅ©´Â ÄÚµå ¼¼±×¸ÕÆ®·Î 0x23 À», µ¥ÀÌŸ/½ºÅà ¼¼±×¸ÕÆ®·Î 0x2b ¸¦ »ç¿ëÇÑ´Ù. ¸®´ª½º ÆäÀÌÁö³×ÀÌ¼Ç ¸®´ª½º¿¡¼­´Â Çϵå¿þ¾îÀÇ ±¸Á¶¿¡ µû¶ó 3 ´Ü°èÀÇ ÆäÀÌÁö°¡ »ç¿ëµÈ´Ù. ÀÎÅÚ CPU ¿¡¼­´Â ´ÜÁö 2 ´Ü°èÀÇ ÆäÀÌÁö ¸¸ÀÌ Áö¿øµÈ´Ù. ¸®´ª½º´Â ¶ÇÇÑ Copy on Write ¸ÞÄ«´ÏÁòÀ» Áö¿øÇÑ´Ù. (´õ ÀÚ¼¼ÇÑ Á¤º¸´Â   À» Âü°í) ¿Ö ŽºÅ©µé °£¿¡ ÁÖ¼Ò Ãæµ¹ÀÌ ÀϾÁö ¾Ê´Â°¡? ´ë´äÀº ¸Å¿ì °£´ÜÇÏ´Ù: ŽºÅ©µé °£¿¡ ÁÖ¼Ò Ãæµ¹ÀÌ ÀϾÁö ¾Ê´Â ÀÌÀ¯´Â ±×°ÍÀÌ ºÒ°¡´ÉÇϱ⠶§¹®ÀÌ´Ù. ¼±Çü ÁÖ¼Ò¸¦ ¹°¸® ÁÖ¼Ò·Î ¸ÅÇÎÇÏ´Â °ÍÀº ÆäÀÌÁö³×ÀÌ¼Ç ¿¡ ÀÇÇؼ­ ÇàÇØÁö¹Ç·Î ¹°¸®ÀûÀÎ ÆäÀÌÁö¸¦ ´ÜÀÏÇÑ (univocal) ¹æ¹ýÀ¸·Î ÇÒ´çÇÒ ÇÊ¿ä°¡ ¾ø´Ù. ¸Þ¸ð¸®¸¦ ÆäÀÌÁö ´ÜÀ§·Î ºÐ¸®ÇØ¾ß Çϴ°¡? ±×·² ÇÊ¿ä°¡ ¾ø´Ù. ÆäÀÌÁöÀÇ ÇÒ´çÀº µ¿ÀûÀ¸·Î ÀÌ·ç¾îÁø´Ù. ÆäÀÌÁö´Â ¿ÀÁ÷ ŽºÅ©°¡ ÆäÀÌÁö¸¦ ¿äûÇÑ °æ¿ì¿¡¸¸ ÇÊ¿äÇÏ´Ù. ±×·¡¼­ Å©±â º°·Î Á¤¸®µÈ ÀÌ¿ë °¡´ÉÇÑ ¸Þ¸ð¸® (ÆäÀÌÁö) ¿µ¿ª¿¡¼­ ¿øÇÏ´Â Å©±â¿¡ ÇØ´çÇÏ´Â ÆäÀÌÁö¸¦ ¼±ÅÃÇÑ´Ù. ÆäÀÌÁö°¡ ÇØÁ¦µÇ¸é ´ÜÁö ÀÌ¿ë °¡´ÉÇÑ ÆäÀÌÁö ¸®½ºÆ®¿¡ Ãß°¡ÇÏ¸é µÈ´Ù. Ä¿³Î ÆäÀÌÁö¿¡ ´ëÇÏ¿© Ä¿³Î ÆäÀÌÁö¿¡´Â ¹®Á¦Á¡ÀÌ Çϳª ÀÖ´Ù: Ä¿³Î ÆäÀÌÁö´Â µ¿ÀûÀ¸·Î ÇÒ´çµÇÁö¸¸ ÇÒ´çµÇ´Â ¿µ¿ªÀÌ ¿¬¼ÓµÈ ¿µ¿ªÀ̶ó´Â °ÍÀ» º¸ÀåÇÒ ¼ö´Â ¾ø´Ù´Â °ÍÀÌ´Ù. ¿Ö³ÄÇÏ¸é ¼±Çü Ä¿³Î °ø°£Àº ¹°¸®ÀûÀÎ Ä¿³Î °ø°£°ú µ¿ÀÏÇϱ⠶§¹®ÀÌ´Ù..?? ÄÚµå ¼¼±×¸ÕÆ®´Â ¹®Á¦°¡ ¾ø´Ù. ºÎÆ® ÄÚµå´Â ºÎÆà ½Ã¿¡ ÇÒ´çµÇ°í (µû¶ó¼­ °íÁ¤µÈ Å©±âÀÇ ¸Þ¸ð¸® ¿µ¿ª ¸¸À» °¡Áø´Ù) ¸ðµâ¿¡¼­´Â ¸ðµâ Äڵ带 Æ÷ÇÔÇÏ´Â ¸Þ¸ð¸® ¿µ¿ª ¸¸À» ÇÒ´çÇÑ´Ù. ½ÇÁ¦ÀûÀÎ ¹®Á¦´Â ½ºÅà ¼¼±×¸ÕÆ®¿¡¼­ ³ªÅ¸³ª´Âµ¥, °¢°¢ÀÇ Å½ºÅ©µéÀÌ Ä¿³Î ½ºÅà ÆäÀÌÁö¸¦ »ç¿ëÇϱ⠶§¹®ÀÌ´Ù. ½ºÅà ¼¼±×¸ÕÆ®´Â ¹Ýµå½Ã ¿¬¼ÓÀûÀÎ ¿µ¿ª¿¡ ÇÒ´çµÇ¾î¾ß ÇϹǷΠ(½ºÅÃÀÇ Á¤ÀÇ¿¡ µû¶ó) ŽºÅ©ÀÇ ½ºÅà ¿µ¿ªÀÇ ÃÖ´ë Å©±â¸¦ Á¤ÇÏ°Ô µÇ¾ú´Ù. ¸¸¾à ÀÌ Å©±â¸¦ ³Ñ¾î°¡°Ô µÇ¸é Ä¿³Î ¸ðµå ÇÁ·Î¼¼½ºÀÇ ÀÚ·á ±¸Á¶¸¦ µ¤¾î¾²°Ô µÇ´Â ÀÏÀÌ ¹ú¾îÁú °ÍÀÌ´Ù. Ä¿³ÎÀÇ ±¸Á¶´Â ÀÌ·¯ÇÑ ¹®Á¦Á¡À» ÇÇÇϱâ À§ÇØ ´ÙÀ½°ú °°Àº ¹æ½ÄÀ¸·Î ÇÔ¼ö¸¦ »ç¿ëÇÑ´Ù: Àç±ÍÀûÀÎ ÇÔ¼ö È£ÃâÀÌ ¾ø´Ù. N ¹ø ÀÌ»óÀÇ ÇÔ¼ö°£ È£ÃâÀÌ ¾ø´Ù. N À» ¾Ë°í, ¸ðµç Ä¿³Î ÇÔ¼öµéÀÇ Á¤Àû º¯¼öÀÇ Æò±ÕÄ¡¸¦ ¾Ë¸é ½ºÅÃÀÇ Å©±â Á¦ÇÑÀ» ÃßÁ¤ÇÒ ¼ö ÀÖ´Ù. ÀÌ ¹®Á¦Á¡À» ½ÇÁ¦·Î È®ÀÎÇØ º¸°í ½Í´Ù¸é, ³»ºÎÀûÀ¸·Î ÀÚ½ÅÀ» Àç±Í È£ÃâÇÏ´Â ÇÔ¼ö¸¦ °¡Áö°í ÀÖ´Â ¸ðµâÀ» »ý¼ºÇØ º¸¸é µÈ´Ù. ÀÌ ¸ðµâÀº ¸îÂ÷·Ê ¼öÇàµÈ ÈÄ¿¡ ÆäÀÌÁö ÆúÆ® ¿¹¿Ü Çڵ鷯¿¡ ÀÇÇؼ­ ÁßÁöµÉ °ÍÀÌ´Ù. (º¸ÅëÀº Àбâ Àü¿ë ÆäÀÌÁö¿¡ ¾²±â Á¢±Ù µîÀÇ ÀÌÀ¯·Î) ¼ÒÇÁÆ®¿þ¾î ÀÎÅÍ·´Æ® (SoftIRQ) IRQ °¡ ¹ß»ýÇÏ¿´À» ¶§, ¼º´É Çâ»óÀ» À§ÇØ Å½ºÅ© ±³È¯Àº ³ªÁßÀ¸·Î ¹Ì·ç¾î Áø´Ù. ¸î¸î°¡Áö ŽºÅ© µéÀº (IRQ ¸¦ ó¸®ÇÑ ÈÄ¿¡ ½ÇÇàµÇ¸ç, TCP/IP ÆÐŶÀ» ±¸¼ºÇÏ´Â °Í ó·³ CPU ÀÚ¿øÀ» ¸¹ÀÌ ÇÊ¿ä·Î ÇÏ´Â ÀÛ¾÷µé) Å¥¿¡ ³Ö¾îÁö¸ç ½ºÄÉÁÙ¸µÀÌ ÀϾ ¶§ ½ÇÇàµÈ´Ù. (ŸÀÓ ½½¶óÀ̽º°¡ ³¡³¯ ¶§) ÃÖ±Ù ¹öÀüÀÇ Ä¿³Î (2.4.x) ¿¡¼­´Â ¼ÒÇÁÆ®¿þ¾î ÀÎÅÍ·´Æ® ¸ÞÄ«´ÏÁòÀº kdoftirqd_CPUn À̶ó´Â Ä¿³Î ¾²·¹µå·Î ±¸ÇöÇÑ´Ù. n Àº Ä¿³Î ¾²·¹µå°¡ ½ÇÇàµÇ´Â CPU ÀÇ ¹øÈ£¸¦ ÀǹÌÇÑ´Ù (´ÜÀÏ CPU ½Ã½ºÅÛÀÇ °æ¿ì ksoftirqd_CPU0 Àº PID 3 ¹øÀ» »ç¿ëÇÑ´Ù). ¼ÒÇÁÆ®¿þ¾î ÀÎÅÍ·´Æ®ÀÇ Áغñ ¼ÒÇÁÆ®¿þ¾î ÀÎÅÍ·´Æ®ÀÇ ¼³Á¤ cpu_raise_softirq Àº Å¥¿¡ µé¾îÀÖ´Â ÀÛ¾÷µéÀ» °ü¸®ÇÏ´Â ksoftirqd_CPU0 Ä¿³Î ¾²·¹µå¸¦ ±ú¿ì´Â ·çƾÀÌ´Ù. |cpu_raise_softirq |__cpu_raise_softirq |wakeup_softirqd |wake_up_process cpu_raise_softirq [kernel/softirq.c] __cpu_raise_softirq [include/linux/interrupt.h] wakeup_softirq [kernel/softirq.c] wake_up_process [kernel/sched.c] __cpu_raise_softirq ·çƾÀº ÇØ´çÇÏ´Â ¼ÒÇÁÆ®¿þ¾î ÀÎÅÍ·´Æ®°¡ ¹ß»ýÇÏ¿´´Ù°í º¤ÅÍ ³»ÀÇ ºñÆ®¸¦ ¼³Á¤ÇÑ´Ù. wakeup_softirq ·çƾÀº ksoftirqd_CPU0 Ä¿³Î ¾²·¹µå¸¦ ±ú¿ì±â À§ÇØ wakeup_process À» »ç¿ëÇÑ´Ù. ¼ÒÇÁÆ®¿þ¾î ÀÎÅÍ·´Æ®ÀÇ ½ÇÇà TODO: ¼ÒÇÁÆ®¿þ¾î ÀÎÅÍ·´Æ® ¸ÞÄ«´ÏÁò¿¡ Æ÷ÇÔµÈ ÀÚ·á ±¸Á¶¸¦ ¼³¸í ksoftirqd_CPU0 Ä¿³Î ¾²·¹µå°¡ ±ú¾î³ª¸é Å¥¿¡ µé¾îÀÖ´Â ÀÛ¾÷µéÀ» ¼öÇàÇÒ °ÍÀÌ´Ù. ksoftirqd_CPU0 ÀÇ ÄÚµå´Â ´ÙÀ½°ú °°´Ù (ºÎºÐ ¹ßÃé): for ( ; ; ) { if (!softirq_pending(cpu)) schedule(); __set_current_state(TASK_RUNNING); while (softirq_pending(cpu)) { do_softirq(); if (current->need_resched) schedule } __set_current_state(TASK_INTERRUPTIBLE) } ksoftirqd [kernel/softirq.c] Ä¿³Î ¾²·¹µå ¸®´ª½º°¡ ¸ð³î¸®Æ½ ¿î¿µÃ¼Á¦ÀÌÁö¸¸, ½Ã½ºÅÛÀÇ °ü¸® (housekeeping) ÀÛ¾÷À» À§ÇÑ ¸î°³ÀÇ Ä¿³Î ¾²·¹µå °¡ Á¸ÀçÇÑ´Ù. ÀÌ·¯ÇÑ Å½ºÅ©µéÀº »ç¿ëÀÚ ¿µ¿ªÀÇ ¸Þ¸ð¸®¸¦ »ç¿ëÇÏÁö ¾Ê°í, Ä¿³Î ¿µ¿ªÀÇ ¸Þ¸ð¸®¸¦ °øÀ¯ÇÑ´Ù. ¶ÇÇÑ ´Ù¸¥ Ä¿³Î ¿µ¿ªÀÇ ÄÚµå¿Í ºñ½ÁÇÏ°Ô ³ôÀº ¿ì¼± ¼øÀ§¸¦ °¡Áö°í ½ÇÇàµÈ´Ù. (i386 ȯ°æ¿¡¼­ RING0) Ä¿³Î ¾²·¹µå´Â kernel_thread [arch/i386/kernel/process] ÇÔ¼ö¸¦ ÅëÇØ »ý¼ºµÈ´Ù. ÀÌ ÇÔ¼ö´Â ¾î¼Àºí¸® ºÎºÐ¿¡¼­ (fork ¿Í ºñ½ÁÇÑ ½Ã½ºÅÛ ÄÝÀÎ) clone [arch/i386/kernel/process.c] ½Ã½ºÅÛ ÄÝÀ» È£ÃâÇÑ´Ù: int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) { long retval, d0; __asm__ __volatile__( "movl %%esp,%%esi\n\t" "int $0x80\n\t" /* Linux/i386 system call */ "cmpl %%esp,%%esi\n\t" /* child or parent? */ "je 1f\n\t" /* parent - jump */ /* Load the argument into eax, and push it. That way, it does * not matter whether the called function is compiled with * -mregparm or not. */ "movl %4,%%eax\n\t" "pushl %%eax\n\t" "call *%5\n\t" /* call fn */ "movl %3,%0\n\t" /* exit */ "int $0x80\n" "1:\t" :"=&a" (retval), "=&S" (d0) :"0" (__NR_clone), "i" (__NR_exit), "r" (arg), "r" (fn), "b" (flags | CLONE_VM) : "memory"); return retval; } ÀÌ ÇÔ¼ö°¡ Çѹø È£ÃâµÇ¸é ¸Å¿ì ´À¸° ÀÚ¿ø (½º¿Ò ȤÀº USB À̺¥Æ®) À» ±â´Ù¸®°í ÀÖ´Â »õ·Î¿î ŽºÅ© (º¸Åë 2, 3 ó·³ ¸Å¿ì ³·Àº PID ¸¦ °¡Áø´Ù) ¸¦ »ý¼ºÇÑ °ÍÀÌ´Ù. ÀÌ·¸°Ô ¸Å¿ì ´À¸° ÀÚ¿øÀ» »ç¿ëÇÏ´Â ÀÌÀ¯´Â ŽºÅ© ±³È¯¿¡ µû¸£´Â ¿À¹öÇìµå¸¦ ÁÙÀ̱â À§Çؼ­ ÀÌ´Ù. ¾Æ·¡´Â (ps x ¸í·ÉÀ¸·Î ¾Ë¾Æº») ÀϹÝÀûÀÎ Ä¿³Î ¾²·¹µåÀÇ ¸®½ºÆ®ÀÌ´Ù. PID COMMAND 1 init 2 keventd 3 kswapd 4 kreclaimd 5 bdflush 6 kupdated 7 kacpid 67 khubd init Ä¿³Î ¾²·¹µå´Â ºÎÆýÿ¡ ÃÖÃÊ·Î »ý¼ºµÇ´Â ŽºÅ©ÀÌ´Ù. ÀÌ Å½ºÅ©´Â (/etc/inittab À» ÂüÁ¶ÇÏ¿©) ´Ù¸¥ ¸ðµç »ç¿ëÀÚ ¸ðµå ŽºÅ© - ÄÜ¼Ö µ¥¸ó, tty µ¥¸ó, ³×Æ®¿öÅ© µ¥¸ó (rc ½ºÅ©¸³Æ® Âü°í) µî - À» È£ÃâÇÑ´Ù. Ä¿³Î ¾²·¹µå ¿¹Á¦: kswapd [mm/vmscan.c] kswapd ´Â clone() [arch/i386/kernel/process.c] ¿¡ ÀÇÇØ »ý¼ºµÈ´Ù. ÃʱâÈ­ ·çƾÀº ´ÙÀ½°ú °°´Ù: |do_initcalls |kswapd_init |kernel_thread |syscall fork (in assembler) do_initcalls [init/main.c] kswapd_init [mm/vmscan.c] kernel_thread [arch/i386/kernel/process.c] Ä¿³Î ¸ðµâ °³¿ä ¸®´ª½º Ä¿³Î ¸ðµâÀº ½ÇÇà Áß¿¡ Ãß°¡ÇÒ ¼ö ÀÖ´Â Ä¿³Î ¸ðµå¿¡¼­ ½ÇÇàµÇ´Â ÄÚµåÀÇ ÀϺκР(¿¹¸¦ µé¸é, FS (ÆÄÀÏ ½Ã½ºÅÛ), ³×Æ®¿öÅ©, Çϵå¿þ¾î µå¶óÀ̹ö µî) À» ¸»ÇÑ´Ù. ¸®´ª½ºÀÇ ÇÙ½É ºÎºÐ - ÇÁ·Î¼¼½º ½ºÄÉÁÙ¸µ, ÀÎÅÍ·´Æ® °ü¸®, ³×Æ®¿öÅ©ÀÇ ÇÙ½ÉÀûÀÎ ºÎºÐ - µéÀº ¸ðµâÈ­µÉ ¼ö ¾ø´Ù. /lib/modules/Ä¿³Î¹öÀü/ µð·ºÅ丮¿¡ ½Ã½ºÅÛ¿¡ ¼³Ä¡µÈ ¸ðµâµéÀ» ã¾Æº¼ ¼ö ÀÖ´Ù. ¸ðµâÀÇ ·Îµù°ú ¾ð·Îµù ¸ðµâÀ» ·ÎµåÇϱâ À§Çؼ­´Â ´ÙÀ½°ú °°Àº ¸í·É¾î¸¦ »ç¿ëÇÑ´Ù: insmod ¸ðµâÀ̸§ parameters insmod ne io=0x300 irq=9 Ä¿³Î ¸î°¡Áö ÆĶó¹ÌÅ͵éÀ» ÀÚµ¿À¸·Î ã¾ÆÁֱ⸦ ¿øÇÑ´Ù¸é (¿¹¸¦ µé¸é PCI µå¶óÀ̹ö¸¦ »ç¿ëÇÏ´Â °æ¿ì³ª, /etc/conf.modules ¾È¿¡ ÆĶó¹ÌÅ͸¦ Àû¾îµÐ °æ¿ì) insmod ´ë½Å¿¡ modprobe ¸¦ »ç¿ëÇÒ ¼ö ÀÖ´Ù. ¸ðµâÀº ¾ð·ÎµùÇϱâ À§Çؼ­´Â ´ÙÀ½°ú °°Àº ¸í·É¾î¸¦ »ç¿ëÇÑ´Ù: rmmod ¸ðµâÀ̸§ ¸ðµâÀÇ Á¤ÀÇ ¸ðµâÀº Ç×»ó ´ÙÀ½°ú °°Àº ³»¿ëÀ» Æ÷ÇÔÇÑ´Ù: insmod (ȤÀº modprobe) ½Ã¿¡ ½ÇÇàµÇ´Â init_module ÇÔ¼ö rmmod ½Ã¿¡ ½ÇÇàµÇ´Â cleanup_module ÇÔ¼ö ¸¸¾à À§ÀÇ µÎ ÇÔ¼ö°¡ ¸ðµâ³»¿¡ Á¸ÀçÇÏÁö ¾Ê´Â´Ù¸é, ¾î¶² ÇÔ¼ö°¡ ÀÌ·¯ÇÑ ¿ªÇÒ (init, exit) À» ÇÒ °ÍÀÎÁö¸¦ ³ªÅ¸³»±â À§ÇØ ´ÙÀ½°ú °°Àº 2 °³ÀÇ ¸ÅÅ©·Î¸¦ Ãß°¡ÇØ¾ß ÇÑ´Ù. module_init(ÇÔ¼öÀ̸§) module_exit(ÇÔ¼öÀ̸§) ¸ðµâ¿¡¼­´Â ¿ÀÁ÷ (EXPORT_SYMBOL ¸ÅÅ©·Î¸¦ ÀÌ¿ëÇÏ¿©) ¿ÜºÎ·Î °ø°³µÈ Ä¿³Î º¯¼ö¸¸À» º¼ ¼ö ÀÖ´Ù. Ä¿³Î¿¡ À¯¿¬¼ºÀ» Ãß°¡ÇÏ´Â À¯¿ëÇÑ ÆÁ // kernel sources side void (*foo_function_pointer)(void *); if (foo_function_pointer) (foo_function_pointer)(parameter); // module side extern void (*foo_function_pointer)(void *); void my_function(void *parameter) { //My code } int init_module() { foo_function_pointer = &my_function; } int cleanup_module() { foo_function_pointer = NULL; } ÀÌ °£´ÜÇÑ ÆÁÀº ¿ÀÁ÷ ¸ðµâÀÌ ·ÎµåµÇ¾úÀ» ¶§¸¸ my_function ·çƾÀ» ½ÇÇàÇϵµ·Ï Çϱ⠶§¹®¿¡ Ä¿³Î¿¡ ³ôÀº À¯¿¬¼ºÀ» ÁÖ°Ô µÈ´Ù. ÀÌ ÇÔ¼ö ³»¿¡¼­´Â ¿øÇÏ´Â ¾î¶² ÇൿÀÌ¶óµµ ¼öÇàÇÒ ¼ö ÀÖ´Ù: ¿¹¸¦ µé¾î rshape ¸ðµâÀº ³×Æ®¿öÅ©·ÎºÎÅÍ µé¾î¿À´Â ÀÔ·Â Æ®·¡ÇÈÀÇ BandWidth ¸¦ Á¶ÀýÇÏ´Â °Í°ú °°Àº ¿ªÇÒÀ» ÇÑ´Ù. Àüü ¸ðµâ ¸ÞÄ«´ÏÁòÀº °í¸¿°Ôµµ head list (¿øÇÏ´Â ¸¸Å­ ¸®½ºÆ®¸¦ È®ÀåÇÒ ¼ö ÀÖ°Ô Çã¿ë) ¿Í °°Àº Àü¿ª º¯¼ö¸¦ ¸ðµâ¿¡ °ø°³ (export) ÇÏ´Â °ÍÀÌ °¡´ÉÇÏ´Ù. ÀüÇüÀûÀÎ ¿¹·Î´Â ÆÄÀÏ ½Ã½ºÅÛ, Generic devices (¹®ÀÚ, ºí·°, ³×Å©¿öÅ©, ÀüÈ­ ¿¬°á) µîÀÌ ÀÖ´Ù. ±×¸®°í Ä¿³ÎÀÌ ¸ðµâÀ» »ç¿ëÇÒ ¼ö ÀÖµµ·Ï ÁغñÇØ¾ß ÇÑ´Ù: ƯÁ¤ÇÑ °æ¿ì¿¡ À־´Â °¡´ÉÇÑ Ç¥ÁØ¿¡ ¸Â°Ô ´Ù¸¥ ±¸Á¶ (infrastructure) µéÀ» »ý¼ºÇØ¾ß ÇÑ´Ù. (ÃÖ±Ù¿¡ »ý¼ºµÈ ÀüÈ­¿¬°á ÀåÄ¡¿Í °°ÀÌ) proc µð·ºÅ丮 proc ÆÄÀÏ ½Ã½ºÅÛÀº /proc µð·ºÅ丮¿¡ ÀÖÀ¸¸ç, Ä¿³Î°ú Á÷Á¢ ´ëÈ­ÇÏ´Â °ÍÀÌ Çã¿ëµÈ Ư¼öÇÑ µð·ºÅ丮ÀÌ´Ù. ¸®´ª½º´Â Ä¿³Î°úÀÇ Á÷Á¢ÀûÀÎ Åë½ÅÀ» Áö¿øÇϱâ À§ÇØ proc µð·ºÅ丮¸¦ »ç¿ëÇÑ´Ù: ÀÌ°ÍÀº ¸¹Àº °æ¿ì¿¡ À¯¿ëÇÏ´Ù - ¿¹¸¦ µé¾î ¸ÞÀÎ ÇÁ·Î¼¼½ºÀÇ ÀÚ·á ±¸Á¶¸¦ º¸°í ½Í´Ù°Å³ª ƯÁ¤ÇÑ ÇϳªÀÇ ³×Æ®¿öÅ© ÀÎÅÍÆäÀ̽º¿¡¸¸ proxy-arp ±â´ÉÀ» È°¼ºÈ­ÇÏ´Â °æ¿ì, ÃÖ´ë ¾²·¹µåÀÇ °¹¼ö¸¦ º¯°æÇÏ°í ½ÍÀº °æ¿ì, ȤÀº ISA ³ª PCI ¿Í °°Àº ƯÁ¤ ¹ö½ºÀÇ »óŸ¦ µð¹ö±ëÇÏ´Â °æ¿ì¿¡ À־ ¾î¶² Ä«µå°¡ ¼³Ä¡µÇ¾î ÀÖ°í, ¾î¶² I/O address ¸¦ »ç¿ëÇϸç, ÇÒ´çµÈ IRQ °¡ ¾î¶² °ÍÀÌ ÀÖ´ÂÁö¸¦ ¾Ë°í ½ÍÀº °æ¿ì µîÀÌ ÀÖ°Ú´Ù. |-- bus | |-- pci | | |-- 00 | | | |-- 00.0 | | | |-- 01.0 | | | |-- 07.0 | | | |-- 07.1 | | | |-- 07.2 | | | |-- 07.3 | | | |-- 07.4 | | | |-- 07.5 | | | |-- 09.0 | | | |-- 0a.0 | | | `-- 0f.0 | | |-- 01 | | | `-- 00.0 | | `-- devices | `-- usb |-- cmdline |-- cpuinfo |-- devices |-- dma |-- dri | `-- 0 | |-- bufs | |-- clients | |-- mem | |-- name | |-- queues | |-- vm | `-- vma |-- driver |-- execdomains |-- filesystems |-- fs |-- ide | |-- drivers | |-- hda -> ide0/hda | |-- hdc -> ide1/hdc | |-- ide0 | | |-- channel | | |-- config | | |-- hda | | | |-- cache | | | |-- capacity | | | |-- driver | | | |-- geometry | | | |-- identify | | | |-- media | | | |-- model | | | |-- settings | | | |-- smart_thresholds | | | `-- smart_values | | |-- mate | | `-- model | |-- ide1 | | |-- channel | | |-- config | | |-- hdc | | | |-- capacity | | | |-- driver | | | |-- identify | | | |-- media | | | |-- model | | | `-- settings | | |-- mate | | `-- model | `-- via |-- interrupts |-- iomem |-- ioports |-- irq | |-- 0 | |-- 1 | |-- 10 | |-- 11 | |-- 12 | |-- 13 | |-- 14 | |-- 15 | |-- 2 | |-- 3 | |-- 4 | |-- 5 | |-- 6 | |-- 7 | |-- 8 | |-- 9 | `-- prof_cpu_mask |-- kcore |-- kmsg |-- ksyms |-- loadavg |-- locks |-- meminfo |-- misc |-- modules |-- mounts |-- mtrr |-- net | |-- arp | |-- dev | |-- dev_mcast | |-- ip_fwchains | |-- ip_fwnames | |-- ip_masquerade | |-- netlink | |-- netstat | |-- packet | |-- psched | |-- raw | |-- route | |-- rt_acct | |-- rt_cache | |-- rt_cache_stat | |-- snmp | |-- sockstat | |-- softnet_stat | |-- tcp | |-- udp | |-- unix | `-- wireless |-- partitions |-- pci |-- scsi | |-- ide-scsi | | `-- 0 | `-- scsi |-- self -> 2069 |-- slabinfo |-- stat |-- swaps |-- sys | |-- abi | | |-- defhandler_coff | | |-- defhandler_elf | | |-- defhandler_lcall7 | | |-- defhandler_libcso | | |-- fake_utsname | | `-- trace | |-- debug | |-- dev | | |-- cdrom | | | |-- autoclose | | | |-- autoeject | | | |-- check_media | | | |-- debug | | | |-- info | | | `-- lock | | `-- parport | | |-- default | | | |-- spintime | | | `-- timeslice | | `-- parport0 | | |-- autoprobe | | |-- autoprobe0 | | |-- autoprobe1 | | |-- autoprobe2 | | |-- autoprobe3 | | |-- base-addr | | |-- devices | | | |-- active | | | `-- lp | | | `-- timeslice | | |-- dma | | |-- irq | | |-- modes | | `-- spintime | |-- fs | | |-- binfmt_misc | | |-- dentry-state | | |-- dir-notify-enable | | |-- dquot-nr | | |-- file-max | | |-- file-nr | | |-- inode-nr | | |-- inode-state | | |-- jbd-debug | | |-- lease-break-time | | |-- leases-enable | | |-- overflowgid | | `-- overflowuid | |-- kernel | | |-- acct | | |-- cad_pid | | |-- cap-bound | | |-- core_uses_pid | | |-- ctrl-alt-del | | |-- domainname | | |-- hostname | | |-- modprobe | | |-- msgmax | | |-- msgmnb | | |-- msgmni | | |-- osrelease | | |-- ostype | | |-- overflowgid | | |-- overflowuid | | |-- panic | | |-- printk | | |-- random | | | |-- boot_id | | | |-- entropy_avail | | | |-- poolsize | | | |-- read_wakeup_threshold | | | |-- uuid | | | `-- write_wakeup_threshold | | |-- rtsig-max | | |-- rtsig-nr | | |-- sem | | |-- shmall | | |-- shmmax | | |-- shmmni | | |-- sysrq | | |-- tainted | | |-- threads-max | | `-- version | |-- net | | |-- 802 | | |-- core | | | |-- hot_list_length | | | |-- lo_cong | | | |-- message_burst | | | |-- message_cost | | | |-- mod_cong | | | |-- netdev_max_backlog | | | |-- no_cong | | | |-- no_cong_thresh | | | |-- optmem_max | | | |-- rmem_default | | | |-- rmem_max | | | |-- wmem_default | | | `-- wmem_max | | |-- ethernet | | |-- ipv4 | | | |-- conf | | | | |-- all | | | | | |-- accept_redirects | | | | | |-- accept_source_route | | | | | |-- arp_filter | | | | | |-- bootp_relay | | | | | |-- forwarding | | | | | |-- log_martians | | | | | |-- mc_forwarding | | | | | |-- proxy_arp | | | | | |-- rp_filter | | | | | |-- secure_redirects | | | | | |-- send_redirects | | | | | |-- shared_media | | | | | `-- tag | | | | |-- default | | | | | |-- accept_redirects | | | | | |-- accept_source_route | | | | | |-- arp_filter | | | | | |-- bootp_relay | | | | | |-- forwarding | | | | | |-- log_martians | | | | | |-- mc_forwarding | | | | | |-- proxy_arp | | | | | |-- rp_filter | | | | | |-- secure_redirects | | | | | |-- send_redirects | | | | | |-- shared_media | | | | | `-- tag | | | | |-- eth0 | | | | | |-- accept_redirects | | | | | |-- accept_source_route | | | | | |-- arp_filter | | | | | |-- bootp_relay | | | | | |-- forwarding | | | | | |-- log_martians | | | | | |-- mc_forwarding | | | | | |-- proxy_arp | | | | | |-- rp_filter | | | | | |-- secure_redirects | | | | | |-- send_redirects | | | | | |-- shared_media | | | | | `-- tag | | | | |-- eth1 | | | | | |-- accept_redirects | | | | | |-- accept_source_route | | | | | |-- arp_filter | | | | | |-- bootp_relay | | | | | |-- forwarding | | | | | |-- log_martians | | | | | |- mc_forwarding | | | | | |-- proxy_arp | | | | | |-- rp_filter | | | | | |-- secure_redirects | | | | | |-- send_redirects | | | | | |-- shared_media | | | | | `-- tag | | | | `-- lo | | | | |-- accept_redirects | | | | |-- accept_source_route | | | | |-- arp_filter | | | | |-- bootp_relay | | | | |-- forwarding | | | | |-- log_martians | | | | |-- mc_forwarding | | | | |-- proxy_arp | | | | |-- rp_filter | | | | |-- secure_redirects | | | | |-- send_redirects | | | | |-- shared_media | | | | `-- tag | | | |-- icmp_echo_ignore_all | | | |-- icmp_echo_ignore_broadcasts | | | |-- icmp_ignore_bogus_error_responses | | | |-- icmp_ratelimit | | | |-- icmp_ratemask | | | |-- inet_peer_gc_maxtime | | | |-- inet_peer_gc_mintime | | | |-- inet_peer_maxttl | | | |-- inet_peer_minttl | | | |-- inet_peer_threshold | | | |-- ip_autoconfig | | | |-- ip_conntrack_max | | | |-- ip_default_ttl | | | |-- ip_dynaddr | | | |-- ip_forward | | | |-- ip_local_port_range | | | |-- ip_no_pmtu_disc | | | |-- ip_nonlocal_bind | | | |-- ipfrag_high_thresh | | | |-- ipfrag_low_thresh | | | |-- ipfrag_time | | | |-- neigh | | | | |-- default | | | | | |-- anycast_delay | | | | | |-- app_solicit | | | | | |-- base_reachable_time | | | | | |-- delay_first_probe_time | | | | | |-- gc_interval | | | | | |-- gc_stale_time | | | | | |-- gc_thresh1 | | | | | |-- gc_thresh2 | | | | | |-- gc_thresh3 | | | | | |-- locktime | | | | | |-- mcast_solicit | | | | | |-- proxy_delay | | | | | |-- proxy_qlen | | | | | |-- retrans_time | | | | | |-- ucast_solicit | | | | | `-- unres_qlen | | | | |-- eth0 | | | | | |-- anycast_delay | | | | | |-- app_solicit | | | | | |-- base_reachable_time | | | | | |-- delay_first_probe_time | | | | | |-- gc_stale_time | | | | | |-- locktime | | | | | |-- mcast_solicit | | | | | |-- proxy_delay | | | | | |-- proxy_qlen | | | | | |-- retrans_time | | | | | |-- ucast_solicit | | | | | `-- unres_qlen | | | | |-- eth1 | | | | | |-- anycast_delay | | | | | |-- app_solicit | | | | | |-- base_reachable_time | | | | | |-- delay_first_probe_time | | | | | |-- gc_stale_time | | | | | |-- locktime | | | | | |-- mcast_solicit | | | | | |-- proxy_delay | | | | | |-- proxy_qlen | | | | | |-- retrans_time | | | | | |-- ucast_solicit | | | | | `-- unres_qlen | | | | `-- lo | | | | |-- anycast_delay | | | | |-- app_solicit | | | | |-- base_reachable_time | | | | |-- delay_first_probe_time | | | | |-- gc_stale_time | | | | |-- locktime | | | | |-- mcast_solicit | | | | |-- proxy_delay | | | | |-- proxy_qlen | | | | |-- retrans_time | | | | |-- ucast_solicit | | | | `-- unres_qlen | | | |-- route | | | | |-- error_burst | | | | |-- error_cost | | | | |-- flush | | | | |-- gc_elasticity | | | | |-- gc_interval | | | | |-- gc_min_interval | | | | |-- gc_thresh | | | | |-- gc_timeout | | | | |-- max_delay | | | | |-- max_size | | | | |-- min_adv_mss | | | | |-- min_delay | | | | |-- min_pmtu | | | | |-- mtu_expres | | | | |-- redirect_load | | | | |-- redirect_number | | | | `-- redirect_silence | | | |-- tcp_abort_on_overflow | | | |-- tcp_adv_win_scale | | | |-- tcp_app_win | | | |-- tcp_dsack | | | |-- tcp_ecn | | | |-- tcp_fack | | | |-- tcp_fin_timeout | | | |-- tcp_keepalive_intvl | | | |-- tcp_keepalive_probes | | | |-- tcp_keepalive_time | | | |-- tcp_max_orphans | | | |-- tcp_max_syn_backlog | | | |-- tcp_max_tw_buckets | | | |-- tcp_mem | | | |-- tcp_orphan_retries | | | |-- tcp_reordering | | | |-- tcp_retrans_collapse | | | |-- tcp_retries1 | | | |-- tcp_retries2 | | | |-- tcp_rfc1337 | | | |-- tcp_rmem | | | |-- tcp_sack | | | |-- tcp_stdurg | | | |-- tcp_syn_retries | | | |-- tcp_synack_retries | | | |-- tcp_syncookies | | | |-- tcp_timestamps | | | |-- tcp_tw_recycle | | | |-- tcp_window_scaling | | | `-- tcp_wmem | | `-- unix | | `-- max_dgram_qlen | |-- proc | `-- vm | |-- bdflush | |-- kswapd | |-- max-readahead | |-- min-readahead | |-- overcommit_memory | |-- page-cluster | `-- pagetable_cache |-- sysvipc | |-- msg | |-- sem | `-- shm |-- tty | |-- driver | | `-- serial | |-- drivers | |-- ldisc | `-- ldiscs |-- uptime `-- version ÀÌ µð·ºÅ丮¿¡´Â ¸ðµç ŽºÅ©¿¡ °üÇÑ Á¤º¸°¡ µé¾îÀÖ´Ù. (°¢ µð·ºÅ丮ÀÇ À̸§Àº ŽºÅ©ÀÇ PID ¿¡ ÇØ´çÇÏ´Â ¼ýÀÚÀÌ°í À̸¦ ÀÌ¿ëÇÏ¿© ŽºÅ©¿¡ ´ëÇÑ ¸ðµç Á¤º¸ - ½ÇÇà ÆÄÀÏÀÇ °æ·Î¶óµçÁö ¸Þ¸ð¸® »ç¿ë·® µî - ¸¦ º¼ ¼ö ÀÖ´Ù) Èï¹Ì·Î¿î Á¡Àº ÀÌ·¯ÇÑ Ä¿³ÎÀÇ Á¤º¸ µéÀ» ´ÜÁö º¼ ¼ö¸¸ ÀÖ´Â °ÍÀÌ ¾Æ´Ï¶ó (ŽºÅ©ÀÇ Á¤º¸ ȤÀº TCP/IP ½ºÅÃÀ» È°¼ºÈ­ÇÏ´Â ³×Æ®¿öÅ© ¿É¼Ç¿¡ °üÇÑ »çÇ×µéÀ» º¸´Â °Í) ¸î¸î Á¤º¸µéÀº ¼öÁ¤ÇÒ ¼öµµ ÀÖ´Ù´Â °ÍÀÌ´Ù. ÀϹÝÀûÀ¸·Î ÀÌ·¯ÇÑ °ÍµéÀº /proc/sys µð·ºÅ丮 ¾Æ·¡¿¡ ÀÖ´Ù. /proc/sys/ acpi dev debug fs proc net vm kernel /proc/sys/kernel ´ÙÀ½Àº ¸Å¿ì Áß¿äÇÏ°í Àß ¾Ë·ÁÁø ¼öÁ¤ÇÒ ¼ö ÀÖ´Â Ä¿³Î Á¤º¸µéÀÌ´Ù: overflowgid overflowuid random threads-max // Max number of threads, typically 16384 sysrq // kernel hack: you can view instant register values and more sem msgmnb msgmni msgmax shmmni shmall shmmax rtsig-max rtsig-nr modprobe // modprobe file location printk ctrl-alt-del cap-bound panic domainname // domain name of your Linux box hostname // host name of your Linux box version // date info about kernel compilation osrelease // kernel version (i.e. 2.4.5) ostype // Linux! /proc/sys/net ÀÌ°ÍÀº proc ÀÇ ÇÏÀ§ µð·ºÅ丮 Áß¿¡¼­ °¡Àå À¯¿ëÇÑ µð·ºÅ丮ÀÏ °ÍÀÌ´Ù. ¿©±â¼­´Â Ä¿³ÎÀÇ ³×Æ®¿öÅ© ¼³Á¤¿¡ ´ëÇÑ ¸Å¿ì Áß¿äÇÑ ºÎºÐµéÀ» º¯°æÇÒ ¼ö ÀÖ´Ù. core ipv4 ipv6 unix ethernet 802 /proc/sys/net/core ¾Æ·¡ÀÇ ¸®½ºÆ®´Â netdev_max_backlog - ³×Æ®¿öÅ© ÆÐŶÀÇ Àüü °¹¼ö (º¸Åë 300) - ¿Í °°Àº ÀϹÝÀûÀÎ ³×Æ®¿öÅ© ¼³Á¤À» º¸¿©ÁØ´Ù. ÀÌ °ªÀº ÆÐŶÀ» ¹ÞÀ» ¶§ ³×Æ®¿öÅ©ÀÇ BandWidth ¸¦ Á¦ÇÑÇÒ ¼ö ÀÖ´Ù. ¸®´ª½º´Â ¹öÆÛ¸¦ ºñ¿ì±â À§ÇØ ½ºÄÉÁÙ¸µÀÌ ÀϾ ¶§ ±îÁö ±â´Ù·Á¾ß ÇÑ´Ù (bottom half ¸ÞÄ«´ÏÁò¿¡ ÀÇÇØ Ã³¸®). 1000/HZ ms ÀÏ ¶§ 300 * 100 = 30 000 packets HZ(Timeslice freq) packets/s 30 000 * 1000 = 30 M packets average (Bytes/packet) throughput Bytes/s ¸¸¾à ´õ ³ôÀº throughput À» ¿øÇÑ´Ù¸é netdev_max_backlog À» ´ÙÀ½°ú °°ÀÌ Áõ°¡½Ãų ¼ö ÀÖ´Ù: echo 4000 > /proc/sys/net/core/netdev_max_backlog HZ °ª¿¡ ÁÖÀÇÇϱ⠹ٶõ´Ù: (alpha ³ª arm-tbox °°Àº) ƯÁ¤ ȯ°æ¿¡¼­´Â ÀÌ °ªÀÌ 1000 À¸·Î ¼³Á¤µÇ¾î Àֱ⠶§¹®¿¡ Æò±Õ 300 MBytes/sec ÀÇ throughput ÀÌ ³ª¿Â´Ù. /proc/sys/net/ipv4 ip_forward °ªÀº ¸®´ª½º ¹Ú½ºÀÇ IP Æ÷¿öµùÀ» È°¼ºÈ­Çϰųª ºñÈ°¼ºÈ­ ½ÃÅ°´Â ¿ªÇÒÀ» ÇÑ´Ù. ÀÌ°ÍÀº ¸ðµç ÀåÄ¡¿¡ ´ëÇÑ ÀϹÝÀûÀÎ ¼³Á¤ÀÌ°í, °¢°¢ÀÇ ÀåÄ¡¸¦ ¼±ÅÃÇÏ¿© ¸í½ÃÇÒ ¼öµµ ÀÖ´Ù. /proc/sys/net/ipv4/conf/interface °³ÀÎÀûÀÎ »ý°¢À¸·Î´Â ÀÌ µð·ºÅ丮°¡ /proc Áß¿¡¼­ °¡Àå À¯¿ëÇÑ °÷À̶ó°í »ý°¢ÇÑ´Ù. ¿Ö³ÄÇϸé ÀÌ°÷¿¡¼­ ³×Æ®¿öÅ© ¼³Á¤À» Á¶±Ý º¯°æÇÏ¿© ¹«¼± ³×Æ®¿öÅ©¸¦ Áö¿øÇϵµ·Ï ÇÒ ¼ö Àֱ⠶§¹®ÀÌ´Ù. (ÀÚ¼¼ÇÑ ³»¿ëÀº Wireless-HOWTO ¹®¼­¸¦ Âü°íÇϱ⠹ٶõ´Ù) À̸¦ ÀÌ¿ëÇÏ´Â ¿¹Á¦·Î´Â ´ÙÀ½°ú °°Àº °ÍµéÀÌ ÀÖ´Ù: forwarding, ³×Æ®¿öÅ© ÀÎÅÍÆäÀ̽ºÀÇ IP Æ÷¿öµù ±â´ÉÀ» È°¼ºÈ­ÇÑ´Ù. proxy_arp, proxy arp ±â´ÉÀ» È°¼ºÈ­ÇÑ´Ù. ÀÌ¿¡ ´ëÇÑ ´õ ÀÚ¼¼ÇÑ ³»¿ëÀº The Linux Documentation Project ÀÇ ProxyARP Subnetting HOWTO ¹®¼­¿Í ¹«¼± ³×Æ®¿öÅ© »ó¿¡¼­ proxy arp ¸¦ »ç¿ëÇÏ´Â ¹ý¿¡ ´ëÇؼ­ ¼³¸íÇÑ Wireless HOWTO ¹®¼­¸¦ Âü°íÇϱ⠹ٶõ´Ù) send_redirects, ³×Æ®¿öÅ© ÀÎÅÍÆäÀ̽º°¡ ICMP_REDIRECT ¸Þ½ÃÁö¸¦ º¸³»Áö ¾Êµµ·Ï ¼³Á¤ÇÒ ¼ö ÀÖ´Ù. (À§¿¡µµ ¾ê±âÇßµíÀÌ ´õ ÀÚ¼¼ÇÑ ³»¿ëÀº Wireless HOWTO ¹®¼­¸¦ Âü°íÇ϶ó) ¸®´ª½º ¸ÖƼŽºÅ· °³¿ä ÀÌ Àý¿¡¼­´Â ¸®´ª½º¿¡¼­ ¸ÖƼŽºÅ· ȯ°æÀ» °ü¸®ÇÏ´Â ¸ÞÄ«´ÏÁò°ú ÀÚ·á ±¸Á¶¿¡ ´ëÇؼ­ ºÐ¼®ÇØ º¼ °ÍÀÌ´Ù. ŽºÅ© »óÅ ¸®´ª½ºÀÇ Å½ºÅ©´Â ´ÙÀ½ ÁßÀÇ ÇÑ°¡Áö »óŸ¦ °¡Áø´Ù ([include/linux.h] Âü°í): TASK_RUNNING, ÀÌ »óÅ´ Å½ºÅ©°¡ Ready ¸®½ºÆ® ¿¡ µé¾îÀÖÀ½À» ¸»ÇÑ´Ù. TASK_INTERRUPTIBLE, ŽºÅ©´Â ½Ã±×³ÎÀ̳ª ÀÚ¿øÀ» ±â´Ù¸®´Â ÁßÀÌ´Ù. (sleep) TASK_UNINTERRUPTIBLE, ŽºÅ©´Â ÀÚ¿øÀ» ±â´Ù¸®°í ÀÖÀ¸¸ç (sleep), °°Àº ´ë±â Å¥ ¿¡ µé¾îÀÖ´Ù. TASK_ZOMBIE, ºÎ¸ð°¡ ¾ø´Â ÀÚ½Ä Å½ºÅ© TASK_STOPPED, ŽºÅ©´Â µð¹ö±ë ÁßÀÌ´Ù. ______________ CPU Available ______________ | | ----------------> | | | TASK_RUNNING | | Real Running | |______________| <---------------- |______________| CPU Busy | /|\ Waiting for | | Resource Resource | | Available \|/ | ______________________ | | | TASK_INTERRUPTIBLE / | | TASK-UNINTERRUPTIBLE | |______________________| Main Multitasking Flow ŸÀÓ ½½¶óÀ̽º PIT 8253 ÇÁ·Î±×·¡¹Ö ¸Å 10 ms ¸¶´Ù (HZ °ªÀÇ ¼³Á¤¿¡ µû¶ó ´Ù¸¦ ¼ö ÀÖÀ½) ¸ÖƼŽºÅ· ȯ°æÀ» Áö¿øÇϵµ·Ï IRQ0 ÀÌ ¹ß»ýÇÑ´Ù. ÀÌ ½ÅÈ£´Â 1.19318 MHz ÀÇ ÁÖÆļö¸¦ °¡Áö´Â PIT 8253 Ŭ·°¿¡ ¿¬°áµÈ PIC 8259 (i386 À̻󿡼­) Ĩ¿¡¼­ ¹ß»ýµÈ´Ù. _____ ______ ______ | CPU |<------| 8259 |------| 8253 | |_____| IRQ0 |______| |___/|\| |_____ CLK 1.193.180 MHz // From include/asm/param.h #ifndef HZ #define HZ 100 #endif // From include/asm/timex.h #define CLOCK_TICK_RATE 1193180 /* Underlying HZ */ // From include/linux/timex.h #define LATCH ((CLOCK_TICK_RATE + HZ/2) / HZ) /* For divider */ // From arch/i386/kernel/i8259.c outb_p(0x34,0x43); /* binary, mode 2, LSB/MSB, ch 0 */ outb_p(LATCH & 0xff , 0x40); /* LSB */ outb(LATCH >> 8 , 0x40); /* MSB */ ±×·¡¼­ 8253 PIT (Programmable Inteval Timer) ¸¦ ÇÁ·Î±×·¡¹ÖÇÒ ¶§ HZ °ªÀÌ 100 ÀÎ °æ¿ì (±âº»°ª) LATCH °ªÀ» 11931.8 (1193180 / HZ) ·Î ¼³Á¤ÇÑ´Ù. LATCH °ªÀº ÁÖÆļö¸¦ °áÁ¤ÇÏ´Â ¿ä¼Ò°¡ µÈ´Ù. (frequence divisor factor) LATCH ¸¦ 11931.8 ·Î ¼³Á¤ÇÏ´Â °ÍÀº 8253 ÀÇ Ãâ·Â°ªÀÌ 1193180/11931.8 = 100 HZ ÀÇ ÁÖÆļö¸¦ °¡Áöµµ·Ï ÇÑ´Ù. µû¶ó¼­ ÁÖ±â´Â 10 ms °¡ µÈ´Ù. Áï, ŸÀÓ ½½¶óÀ̽º °ªÀº 1/HZ ÀÌ´Ù. °¢ ŸÀÓ ½½¶óÀ̽º ¸¶´Ù ÀϽÃÀûÀ¸·Î ÇöÀç ÇÁ·Î¼¼½ºÀÇ ½ÇÇàÀ» ÁßÁöÇÏ°í (ŽºÅ© ½ºÀ§Äª ¾øÀÌ) ¸î°¡Áö ºÎ¼öÀûÀÎ ÀϵéÀ» ó¸®ÇÑ ÈÄ¿¡ ´Ù½Ã ÀÌÀüÀÇ ÇÁ·Î¼¼½º·Î µ¹¾Æ¿À°Ô µÈ´Ù. ¸®´ª½º ŸÀÌ¸Ó ÀÎÅÍ·´Æ® - ÇÔ¼ö°£ È£Ã⠺м® Linux Timer IRQ IRQ 0 [Timer] | \|/ |IRQ0x00_interrupt // Æ÷Àå (wrapper) IRQ Çڵ鷯 |SAVE_ALL --- |do_IRQ | Æ÷Àå ÇÔ¼ö |handle_IRQ_event --- |handler() -> timer_interrupt // µî·ÏµÈ IRQ 0 Çڵ鷯 |do_timer_interrupt |do_timer |jiffies++; |update_process_times |if (--counter <= 0) { // ÇÁ·Î¼¼½ºÀÇ Å¸ÀÓ ½½¶óÀ̽º°¡ ´Ù µÈ °æ¿ì |counter = 0; // counter °ªÀ» Áö¿ì°í |need_resched = 1; // ½ºÄÉÁÙ¸µÀ» ¿äûÇÔ |} |do_softirq |while (need_resched) { // ÇÊ¿äÇÑ °æ¿ì |schedule // ÇÁ·Î¼¼½º¸¦ ½ºÄÉÁÙ¸µ |handle_softirq |} |RESTORE_ALL °¢ ÇÔ¼öµéÀº ¾Æ·¡¿Í °°ÀÌ Ã£¾Æº¼ ¼ö ÀÖ´Ù: IRQ0x00_interrupt, SAVE_ALL [include/asm/hw_irq.h] IRQ0x00_interrupt, SAVE_ALL [include/asm/hw_irq.h] timer_interrupt, do_timer_interrupt [arch/i386/kernel/time.c] do_timer, update_process_times [kernel/timer.c] do_softirq [kernel/soft_irq.c] RESTORE_ALL, while loop [arch/i386/kernel/entry.S] IRQ0x00_interrupt ÇÔ¼ö´Â (´Ù¸¥ IRQ0xXY_interrupt ÇÔ¼öó·³) IDT (Interrupt Descriptor Table, ¸®¾ó ¸ðµåÀÇ Interrupt Vector Table °ú °°´Ù. 11 Àå Âü°í) ¿¡¼­ Á÷Á¢ °¡¸®Å°°í ÀÖÀ¸¹Ç·Î, ÇÁ·Î¼¼¼­·Î µé¾î¿À´Â ¸ðµç ÀÎÅÍ·´Æ®´Â IRQ0x#NR_interrupt ÇÔ¼ö¿¡ ÀÇÇØ Ã³¸®µÈ´Ù. (¿©±â¼­ #NR Àº ÀÎÅÍ·´Æ® ¹øÈ£¸¦ ÀǹÌ) ±×·¡¼­ ¿©±â¿¡¼­´Â ÀÌ·± ÇÔ¼öµéÀº Æ÷Àå IRQ Çڵ鷯 (wrapper irq handler) ¶ó°í ºÎ¸¥´Ù. do_IRQ À̳ª handle_IRQ_event ¿Í °°Àº Æ÷Àå ÇÔ¼öµéÀÌ ½ÇÇàµÈ´Ù. [arch/i386/kernel/irq.c] ±× ÀÌÈÄ¿¡´Â ÀÌÀü¿¡ request_irq [arch/i386/kernel/irq.c] ¿¡¼­ µî·ÏµÈ (handler() ·Î ÂüÁ¶µÇ´Â) °ø½ÄÀûÀÎ IRQ ·çƾ À¸·Î Á¦¾î°¡ ³Ñ¾î°£´Ù. ÀÌ °æ¿ì¿¡´Â timer_interrupt [arch/i386/kernel/time.c] °¡ µÈ´Ù. timer_interrupt [arch/i386/kernel/time.c] °¡ ½ÇÇàµÈ´Ù. Á¦¾î´Â ¾î¼Àºí¸® ·çƾÀ¸·Î ³Ñ¾î°£´Ù. [arch/i386/kernel/entry.S] ¼³¸í: ¸ÖƼŽºÅ·À» °ü¸®Çϱâ À§ÇØ ¸®´ª½º¿¡¼­´Â (´Ù¸¥ À¯´Ð½º¿¡¼­¿Í °°ÀÌ) counter À̶ó´Â º¯¼ö¸¦ µÎ¾î¼­ ŽºÅ©°¡ CPU ¸¦ ¾ó¸¸Å­ »ç¿ëÇß´ÂÁö¸¦ ±â·ÏÇØ µÐ´Ù. ±×·¡¼­ ¸Å IRQ 0 ¿¡¼­ ÀÌ °ªÀ» °¨¼Ò½ÃÅ°°í (4 ¹ø ºÎºÐ¿¡ ÇØ´ç), counter °ªÀÌ 0 ÀÌ µÇ¸é ŽºÅ© ½ºÀ§ÄªÀÌ ÀϾµµ·Ï ÇÑ´Ù. (4 ¹ø¿¡¼­ need_resched °ªÀ» 1 ·Î ¼³Á¤ÇÏ°í, 5 ¹ø¿¡¼­ resched °ª¿¡ µû¶ó schedule [kernel/sched.c] ÀÌ ½ÇÇàµÈ´Ù) ½ºÄÉÁÙ·¯ ½ºÄÉÁÙ·¯´Â ÁÖ¾îÁø ƯÁ¤ ½Ã°£¿¡¼­ ½ÇÇàµÇ¾î¾ß ÇÒ Å½ºÅ©¸¦ ¼±ÅÃÇÏ´Â ºÎºÐÀÇ Äڵ带 ¸»ÇÑ´Ù. ½ÇÇàµÇ°í Àִ ŽºÅ©¸¦ ±³Ã¼ÇØ¾ß ÇÏ´Â °æ¿ì¿¡ ±× È帰¡ µÉ ŽºÅ©¸¦ ¼±ÅÃÇÑ´Ù. ¾Æ·¡´Â schedule ÇÔ¼öÀÌ´Ù. [kernel/sched.c] |schedule |do_softirq // ÀÌÀü¿¡ °É¸° soft-IRQ ó¸® |for each task |calculate counter |prepare_to__switch // ŽºÅ© ½ºÀ§ÄªÀ» À§ÇÑ È¯°æ ¼³Á¤ |switch_mm // ¸Þ¸ð¸® ȯ°æ º¯°æ (CR3 ·¹Áö½ºÅÍ °ª ¼öÁ¤) |switch_to (assembler) |SAVE ESP |RESTORE future_ESP |SAVE EIP |push future_EIP *** ÇÔ¼ö È£ÃâÀ» ÇÑ °Í ó·³ ÆĶó¹ÌÅÍ ¼³Á¤ |jmp __switch_to (TSS ¿¡ °ü·ÃµÈ ÀÛ¾÷À» ¼öÇà) |__switch_to() .. |ret *** future_EIP °¡ °¡¸®Å°´Â °÷À¸·Î º¹±Í new_task ÇϹݺΠ(Bottom Half), ŽºÅ© Å¥ (Task Queues), ¼ÒÀÛ¾÷ (Tasklets) °³¿ä ÀüÅëÀûÀÎ À¯´Ð½º¿¡¼­´Â (ÀåÄ¡·Î ºÎÅÍ) IRQ °¡ ¹ß»ýÇßÀ» ¶§, ÀåÄ¡°¡ ¿äûÇÑ Å½ºÅ©¸¦ ó¸®Çϱâ À§ÇØ Å½ºÅ© ½ºÀ§Äª À» ¼öÇàÇÏ¿´´Ù. ¸®´ª½º¿¡¼­´Â ¼º´ÉÀ» Çâ»ó½ÃÅ°±â À§ÇØ ±ä±ÞÇÏÁö ¾ÊÀº ÀÛ¾÷Àº µÚ·Î ¹Ì·ç¾î ´õ ºü¸¥ À̺¥Æ® 󸮸¦ ÇÒ ¼ö ÀÖµµ·Ï ÇÑ´Ù. ÀÌ ±â´ÉÀº Ä¿³Î ¹öÀü 1.x ¿¡¼­ºÎÅÍ ÇϹݺΠ(Bottom Half - BH) ¿¡ ÀÇÇØ ¼öÇàµÇ¾î Á³´Ù. IRQ Çڵ鷯¿¡¼­´Â (³ªÁß¿¡ - ½ºÄÉÁÙ¸µ½Ã - ¼öÇàµÇµµ·Ï) ÇϹݺηΠǥ½ÃÇÑ´Ù. ÃÖ½ÅÀÇ Ä¿³Î ¹öÀü¿¡¼­´Â Á» ´õ µ¿ÀûÀÌ°í ¸ÖƼ ÇÁ·Î¼¼¼­ ȯ°æÀ» Áö¿øÇÏ´Â ¼ÒÀÛ¾÷ (Tasklet) À̶ó´Â °³³äÀ» µµÀÔÇÏ¿´´Ù. ÇϹݺδ ´ÙÀ½°ú °°Àº ÇüÅ°¡ µÉ °ÍÀÌ´Ù: ¼±¾ð (Declaration) Ç¥½Ã (Mark) ½ÇÇà (Execution) ¼±¾ð #define DECLARE_TASK_QUEUE(q) LIST_HEAD(q) #define LIST_HEAD(name) \ struct list_head name = LIST_HEAD_INIT(name) struct list_head { struct list_head *next, *prev; }; #define LIST_HEAD_INIT(name) { &(name), &(name) } DECLARE_TASK_QUEUE [include/linux/tqueue.h, include/linux/list.h] DECLARE_TASK_QUEUE(q) ¸ÅÅ©·Î´Â ŽºÅ© Å¥¸¦ °ü¸®ÇÏ´Â q ¶ó´Â ±¸Á¶Ã¼¸¦ ¼±¾ðÇϴµ¥ »ç¿ëµÈ´Ù. Ç¥½Ã ¾Æ·¡´Â mark_bh ÇÔ¼ö¿¡ ´ëÇÑ ÇÔ¼ö°£ È£Ã⠺м®ÀÌ´Ù [include/linux/interrupt.h]: |mark_bh(NUMBER) |tasklet_hi_schedule(bh_task_vec + NUMBER) |insert into tasklet_hi_vec |__cpu_raise_softirq(HI_SOFTIRQ) |soft_active |= (1 << HI_SOFTIRQ) ''mark_bh''[include/linux/interrupt.h] ½ÇÇà do_IRQ ÇÔ¼ö¿¡¼­ ¾Æ·¡¿Í °°Àº ºÎºÐÀÌ È£ÃâµÇ´Â °ÍÀ» º¼ ¼ö ÀÖÀ» °ÍÀÌ´Ù [arch/i386/kernel/irq.c]: |do_softirq |h->action(h)-> softirq_vec[TASKLET_SOFTIRQ]->action -> tasklet_action |tasklet_vec[0].list->func h->action(h) Àº ÀÌÀü¿¡ Å¥¿¡ µé¾î°¡ ÀÖ´ø ÇÔ¼öÀÌ´Ù. Àú¼öÁØ ·çƾµé set_intr_gate set_trap_gate set_task_gate (»ç¿ëµÇÁö ¾ÊÀ½) (*interrupt)[NR_IRQS](void) = { IRQ0x00_interrupt, IRQ0x01_interrupt, ..} NR_IRQS = 224 [kernel 2.4.2] ŽºÅ© ½ºÀ§Äª ŽºÅ© ½ºÀ§ÄªÀº ¾ðÁ¦ ÀϾ´Â°¡? ¿©±â¼­´Â ¸®´ª½º Ä¿³ÎÀÌ ¼öÇàÁßÀΠŽºÅ©¸¦ ´Ù¸¥ ŽºÅ©·Î ±³Ã¼ÇÏ´Â °ÍÀ» »ìÆ캼 °ÍÀÌ´Ù. ŽºÅ© ½ºÀ§ÄªÀº ´ÙÀ½°ú °°Àº ¸¹Àº °æ¿ì¿¡¼­ ÇÊ¿äÇÏ´Ù: ŸÀÓ ½½¶óÀ̽º°¡ ³¡³­ °æ¿ì, ´Ù¸¥ ŽºÅ©¸¦ ½ÇÇàÇØ¾ß ÇÑ´Ù. ŽºÅ©°¡ ÀÚ¿øÀ» »ç¿ëÇÏ·Á´Â °æ¿ì ÀÌ ÀÚ¿øÀ» ÀÌ¿ëÇÒ ¼ö ÀÖÀ» ¶§±îÁö Àáµé°Ô µÈ´Ù. ÀÌ ¶§¿¡µµ ´Ù¸¥ ŽºÅ©¸¦ ½ÇÇàÇØ¾ß ÇÑ´Ù. ŽºÅ©°¡ ÆÄÀÌÇÁ¸¦ ±â´Ù¸®°í ÀÖ´Â °æ¿ì, ÆÄÀÌÇÁ¿¡ ¾²±â ¿¬»êÀ» ¼öÇàÇÒ ´Ù¸¥ ŽºÅ©¸¦ ½ÇÇàÇØ¾ß ÇÑ´Ù. ŽºÅ© ½ºÀ§Äª TASK SWITCHING TRICK #define switch_to(prev,next,last) do { \ asm volatile("pushl %%esi\n\t" \ "pushl %%edi\n\t" \ "pushl %%ebp\n\t" \ "movl %%esp,%0\n\t" /* save ESP */ \ "movl %3,%%esp\n\t" /* restore ESP */ \ "movl $1f,%1\n\t" /* save EIP */ \ "pushl %4\n\t" /* restore EIP */ \ "jmp __switch_to\n" \ "1:\t" \ "popl %%ebp\n\t" \ "popl %%edi\n\t" \ "popl %%esi\n\t" \ :"=m" (prev->thread.esp),"=m" (prev->thread.eip), \ "=b" (last) \ :"m" (next->thread.esp),"m" (next->thread.eip), \ "a" (prev), "d" (next), \ "b" (prev)); \ } while (0) ¿©±â¿¡´Â ´ÙÀ½°ú °°Àº Æ®¸¯ÀÌ Á¸ÀçÇÑ´Ù: push %4 ¸¦ ÅëÇØ ½ºÅÿ¡ future_EIP ¸¦ ³Ö´Â´Ù. jmp __switch_to ´Â __switch_to ÇÔ¼ö¸¦ ½ÇÇàÇÑ´Ù. ÇÏÁö¸¸ call ¸í·ÉÀ» ÅëÇØ ½ÇÇàÇÑ °ÍÀÌ ¾Æ´Ï±â ¶§¹®¿¡ ½ÇÇàµÈ µÚ¿¡´Â À§¿¡¼­ ¼³Á¤ÇÑ future_EIP ºÎºÐÀ¸·Î ¸®Å쵃 °ÍÀÌ´Ù. (µû¶ó¼­ »õ·Î¿î ŽºÅ©°¡ ½ÇÇàµÈ´Ù) U S E R M O D E K E R N E L M O D E | | | | | | | | | | | | Timer | | | | | | | Normal | IRQ | | | | | | | Exec |------>|Timer_Int.| | | | | | | | | .. | | | | | | \|/ | |schedule()| | Task1 Ret| | | | | |_switch_to|<-- | Address | |__________| |__________| | | | | | | | |S | | Task1 Data/Stack Task1 Code | | |w | | | | T|i | | | | a|t | | | | | | | | s|c | | | | | | Timer | | k|h | | | | | Normal | IRQ | | |i | | | | | Exec |------>|Timer_Int.| |n | | | | | | | | .. | |g | | | | | \|/ | |schedule()| | | Task2 Ret| | | | | |_switch_to|<-- | Address | |__________| |__________| |__________| |__________| Task2 Data/Stack Task2 Code Kernel Code Kernel Data/Stack Fork °³¿ä fork ´Â »õ·Î¿î ŽºÅ©¸¦ »ý¼ºÇϱâ À§ÇØ »ç¿ëµÈ´Ù. Task Parent ¿¡¼­ ½ÃÀÛÇÏ¿© Task Child ·Î ¸¹Àº ÀڷᱸÁ¶¸¦ º¹»çÇÑ´Ù. | | | .. | Task Parent | | | | | | | fork |---------->| CREATE | | | /| NEW | |_________| / | TASK | / | | --- / | | --- / | .. | / | | Task Child / | | / | fork |<-/ | | |_________| Fork SysCall ¹«¾ùÀÌ º¹»çµÇÁö ¾Ê´Â°¡? »õ·Î »ý¼ºµÈ ŽºÅ© (Task Child) ´Â ±× ºÎ¸ð ŽºÅ© (Task Parent) ¿Í °ÅÀÇ °°Áö¸¸, ´ÙÀ½°ú °°Àº Â÷ÀÌÁ¡ÀÌ ÀÖ´Ù: ¸í¹éÇÑ Â÷ÀÌÁ¡À¸·Î´Â PID °ªÀÌ ´Ù¸£´Ù. ÀÚ½Ä Å½ºÅ©¿¡¼­´Â fork() ÇÔ¼ö°¡ 0 À» ¸®ÅÏÇÏÁö¸¸, ºÎ¸ð ŽºÅ©¿¡¼­´Â ÀÚ½Ä Å½ºÅ©ÀÇ PID °ªÀº ¸®ÅÏÇÑ´Ù. (»ç¿ëÀÚ ¸ðµå¿¡¼­ À̸¦ ÀÌ¿ëÇØ ¼­·Î¸¦ ±¸º°ÇÑ´Ù) ÀÚ½Ä Å½ºÅ©ÀÇ ¸ðµç µ¥ÀÌŸ ÆäÀÌÁö´Â (ºÎ¸ð ŽºÅ©¿¡¼­ ÀÚ½ÅÀÇ ÆäÀÌÁö¿¡ WRITE ±ÇÇÑÀ» °¡Áöµµ·Ï ¼³Á¤µÈ µ¥ ¹ÝÇØ) WRITE ±ÇÇÑ ¾øÀÌ READ + EXECUTE ±ÇÇÑÀ¸·Î ¼³Á¤µÇ¾î Áø´Ù. ±×·¡¼­ ¾²±â ¿¬»êÀÌ ¿äûµÇ¸é Page Fault ¿¹¿Ü°¡ ¹ß»ýµÇ¾î »õ·Î¿î µ¶¸³ÀûÀÎ ÆäÀÌÁö¸¦ »ý¼ºÇÏ°Ô µÈ´Ù. ÀÌ·¯ÇÑ ¸ÞÄ«´ÏÁòÀ» Copy on Write ¶ó°í ºÎ¸¥´Ù. (´õ ÀÚ¼¼ÇÑ »çÇ×Àº   ¿¡¼­ ¼³¸íÇÑ´Ù) fork ÇÔ¼ö°£ È£Ã⠺м® |sys_fork |do_fork |alloc_task_struct |__get_free_pages |p->state = TASK_UNINTERRUPTIBLE |copy_flags |p->pid = get_pid |copy_files |copy_fs |copy_sighand |copy_mm // CopyOnWrite ¸ÞÄ«´ÏÁòÀ» °ü¸® (I part) |allocate_mm |mm_init |pgd_alloc -> get_pgd_fast |get_pgd_slow |dup_mmap |copy_page_range |ptep_set_wrprotect |clear_bit // ÆäÀÌÁö¸¦ read-only ·Î ¼³Á¤ |copy_segments // For LDT |copy_thread |childregs->eax = 0 |p->thread.esp = childregs // ÀÚ½Ä Å½ºÅ©¿¡¼­ 0 À» ¸®ÅÏÇϵµ·Ï ¼³Á¤ |p->thread.eip = ret_from_fork // ÀÚ½Ä Å½ºÅ©°¡ ¼öÇàµÉ ½ÃÀÛ ºÎºÐ ¼³Á¤ |retval = p->pid // ºÎ¸ð ŽºÅ©´Â ÀÚ½Ä Å½ºÅ©ÀÇ pid ¸¦ ¸®ÅÏÇϵµ·Ï ¼³Á¤ |SET_LINKS // ŽºÅ©¸¦ ¸®½ºÆ® Æ÷ÀÎÅÍ¿¡ »ðÀÔ |nr_threads++ // Àü¿ª º¯¼ö |wake_up_process(p) // »õ·Î »ý¼ºµÈ ÀÚ½Ä Å½ºÅ©¸¦ ±ú¿ò |return retval fork ICA sys_fork [arch/i386/kernel/process.c] do_fork [kernel/fork.c] alloc_task_struct [include/asm/processor.c] __get_free_pages [mm/page_alloc.c] get_pid [kernel/fork.c] copy_files copy_fs copy_sighand copy_mm allocate_mm mm_init pgd_alloc -> get_pgd_fast [include/asm/pgalloc.h] get_pgd_slow dup_mmap [kernel/fork.c] copy_page_range [mm/memory.c] ptep_set_wrprotect [include/asm/pgtable.h] clear_bit [include/asm/bitops.h] copy_segments [arch/i386/kernel/process.c] copy_thread SET_LINKS [include/linux/sched.h] wake_up_process [kernel/sched.c] Copy on Write ¸®´ª½º¿¡¼­´Â ´ÙÀ½°ú °°Àº ¹æ¹ýÀ¸·Î Copy on Write ¸¦ ±¸ÇöÇÑ´Ù: ¾²±â ¿¬»êÀÌ ÀϾ ¶§ Page Falut °¡ ÀϾµµ·Ï º¹»çµÈ ¸ðµç ÆäÀÌÁö¸¦ read-only ·Î Ç¥½ÃÇÑ´Ù. Page Fault Çڵ鷯¿¡¼­ »õ·Î¿î ÆäÀÌÁö¸¦ »ý¼ºÇÑ´Ù. | Page | Fault | Exception | | -----------> |do_page_fault |handle_mm_fault |handle_pte_fault |do_wp_page |alloc_page // »õ·Î¿î ÆäÀÌÁö ÇÒ´ç |break_cow |copy_cow_page // ÀÌÀü ÆäÀÌÁö¸¦ »õ·Î¿î ÆäÀÌÁö·Î º¹»ç |establish_pte // ÆäÀÌÁö Å×À̺í Æ÷ÀÎÅ͸¦ ´Ù½Ã ¼³Á¤ |set_pte Page Fault ICA do_page_fault [arch/i386/mm/fault.c] handle_mm_fault [mm/memory.c] handle_pte_fault do_wp_page alloc_page [include/linux/mm.h] break_cow [mm/memory.c] copy_cow_page establish_pte set_pte [include/asm/pgtable-3level.h] ¸Þ¸ð¸® °ü¸® °³¿ä °£´ÜÈ÷ ¸»Çؼ­, ¸®´ª½º´Â segmentation °ú pagnation À» µ¿½Ã¿¡ »ç¿ëÇÑ´Ù. ¼¼±×¸ÕÆ® ¸®´ª½º´Â ¿ÀÁ÷ 4 °³ÀÇ ¼¼±×¸ÕÆ® ¸¸À» »ç¿ëÇÑ´Ù: KERNEL SPACE (0xC000 0000 (3 GB) ºÎÅÍ 0xFFFF FFFF (4 GB) ±îÁö) ¸¦ À§ÇÑ 2 °³ÀÇ ¼¼±×¸ÕÆ® (code ¿Í data/stack) USER SPACE (0 (0 GB) ºÎÅÍ 0xBFFF FFFF (3 GB) ±îÁö) ¸¦ À§ÇÑ 2 °³ÀÇ ¼¼±×¸ÕÆ® (code ¿Í data/stack) __ 4 GB--->| | | | Kernel | | Kernel Space (Code + Data/Stack) | | __| 3 GB--->|----------------| __ | | | | | | 2 GB--->| | | | Tasks | | User Space (Code + Data/Stack) | | | 1 GB--->| | | | | | |________________| __| 0x00000000 Kernel/User Linear addresses i386 ¿¡¼­ÀÇ Æ¯Â¡ ÀÌÀü¿¡µµ ¸»ÇßµíÀÌ ¸®´ª½º´Â Pagination À» 3 ´Ü°èÀÇ ÆäÀÌ¡À» ÀÌ¿ëÇؼ­ ±¸ÇöÇÏÁö¸¸, i386 ȯ°æ¿¡¼­´Â ½ÇÁ¦·Î ±× Áß¿¡¼­ 2 ´Ü°è ¸¸À» »ç¿ëÇÑ´Ù: ------------------------------------------------------------------ L I N E A R A D D R E S S ------------------------------------------------------------------ \___/ \___/ \_____/ PD offset PF offset Frame offset [10 bits] [10 bits] [12 bits] | | | | | ----------- | | | | Value |----------|--------- | | | | |---------| /|\ | | | | | | | | | | | | | | | | | | Frame offset | | | | | | | \|/ | | | | | |---------|<------ | | | | | | | | | | | | | | | | x 4096 | | | | PF offset|_________|------- | | | | /|\ | | | PD offset |_________|----- | | | _________| /|\ | | | | | | | | | | | \|/ | | \|/ _____ | | | ------>|_________| PHYSICAL ADDRESS | | \|/ | | x 4096 | | | CR3 |-------->| | | | |_____| | ....... | | ....... | | | | | Page Directory Page File Linux i386 Paging ¸Þ¸ð¸® ¸ÅÇÎ ¸®´ª½º¿¡¼­´Â ÆäÀÌÁö ´ÜÀ§·Î¸¸ Á¢±Ù Á¦¾î¸¦ °ü¸®ÇÑ´Ù. ±×·¡¼­ ¼­·Î ´Ù¸¥ ŽºÅ©°¡ °°Àº ¼¼±×¸ÕÆ® ÁÖ¼Ò¸¦ °¡Áú ¼ö ÀÖÁö¸¸, ´Ù¸¥ ÆäÀÌÁö Å×ÀÌºí ¿£Æ®¸®¸¦ °¡¸®Å°´Â °¢°¢ÀÇ CR3 (ÆäÀÌÁö µð·ºÅ丮ÀÇ ÁÖ¼Ò¸¦ ÀúÀåÇÏ°í ÀÖ´Â ·¹Áö½ºÅÍ) °ªÀ» °¡Áø´Ù. »ç¿ëÀÚ ¸ðµåÀÇ Å½ºÅ©´Â 3 GB (0x C000 0000) ÀÇ Á¦ÇÑÀ» ³ÑÀ» ¼ö ¾ø´Ù. ±×·¡¼­ ÆäÀÌÁö µð·ºÅ丮ÀÇ Ã¹ 768 ¿£Æ®¸®¸¸ÀÌ Àǹ̸¦ °¡Áø´Ù. (768 * 4 MB = 3 GB) ŽºÅ©°¡ (½Ã½ºÅÛ ÄÝÀ̳ª IRQ ¿¡ ÀÇÇØ) Ä¿³Î ¸ðµå·Î ÁøÀÔÇÏ°Ô µÇ¸é, ³ª¸ÓÁö 256 ¿£Æ®¸®°¡ Áß¿äÇØÁø´Ù. À̵éÀº ´Ù¸¥ ¸ðµç ŽºÅ©¿¡¼­ µ¿ÀÏÇÑ ÆäÀÌÁö¸¦ °¡¸®Å²´Ù. (Ä¿³Î¿¡¼­ »ç¿ë) (¿ÀÁ÷) Ä¿³ÎÀÇ ¼±Çü ÁÖ¼Ò °ø°£Àº Ä¿³ÎÀÇ ¹°¸®ÀûÀÎ ÁÖ¼Ò °ø°£°ú µ¿ÀÏÇÔ¿¡ ÁÖÀÇÇ϶ó. Áï: ________________ _____ |Other KernelData|___ | | | |----------------| | |__| | | Kernel |\ |____| Real Other | 3 GB --->|----------------| \ | Kernel Data | | |\ \ | | | __|_\_\____|__ Real | | Tasks | \ \ | Tasks | | __|___\_\__|__ Space | | | \ \ | | | | \ \|----------------| | | \ |Real KernelSpace| |________________| \|________________| Logical Addresses Physical Addresses Ä¿³ÎÀÇ ¼±Çü ÁÖ¼Ò °ø°£Àº 3 GB ¾Æ·¡¿¡ ÀÖ´Â ¹°¸®ÀûÀÎ ÁÖ¼Ò °ø°£¿¡ ´ëÀÀÇÑ´Ù. (½ÇÁ¦·Î ÆäÀÌÁö Å×À̺íÀº { "00000000", "00000001" } ¿Í °°Àº ÇüŸ¦ °¡Áø´Ù. Áï ¾î¶°ÇÑ º¯È¯ °úÁ¤ÀÌ ÀϾ´Â °ÍÀº ¾Æ´Ï¸ç, ´ÜÁö ¼±Çü ÁÖ¼Ò °ø°£¿¡ ´ëÇÑ ¹°¸®ÀûÀÎ ÁÖ¼Ò¸¦ ³ªÅ¸³¾ »ÓÀÌ´Ù.) ÆäÀÌÁö Å×À̺íÀ» ÀÌ¿ëÇÏ¿© ¹°¸® ÁÖ¼Ò¸¦ °ü¸®Çϱ⠶§¹®¿¡ Ä¿³Î°ú »ç¿ëÀÚ ¸ðµå °£ÀÇ ÁÖ¼Ò Ãæµ¹ °ú °°Àº ÀÏÀº ÀϾÁö ¾Ê´Â´Ù. Àú¼öÁØÀÇ ¸Þ¸ð¸® ÇÒ´ç ºÎÆýà ÃʱâÈ­ °úÁ¤ ¸ÕÀú kmem_cache_init ÇÔ¼ö (ºÎÆýà start_kernel [init/main.c] ¿¡¼­ È£Ãâ) ºÎÅÍ »ìÆ캸ÀÚ. |kmem_cache_init |kmem_cache_estimate kmem_cache_init [mm/slab.c] kmem_cache_estimate ´ÙÀ½À¸·Î »ìÆ캼 ÇÔ¼ö´Â mem_init (¿ª½Ã start_kernel [init/main.c] ¿¡¼­ È£ÃâµÊ) ÀÌ´Ù. |mem_init |free_all_bootmem |free_all_bootmem_core mem_init [arch/i386/mm/init.c] free_all_bootmem [mm/bootmem.c] free_all_bootmem_core ·±Å¸ÀÓ ÇÒ´ç ¸®´ª½º¿¡¼­ ¸Þ¸ð¸®¸¦ ÇÒ´ç¹Þ±â¸¦ ¿øÇÏ´Â °æ¿ìÀÌ´Ù. ¿¹¸¦ µé¸é Copy on Write ¸ÞÄ«´ÏÁò µ¿¾È¿¡ ÀϾ´Â ÀϵéÀ» »ìÆ캸¸é (  Âü°í): |copy_mm |allocate_mm = kmem_cache_alloc |__kmem_cache_alloc |kmem_cache_alloc_one |alloc_new_slab |kmem_cache_grow |kmem_getpages |__get_free_pages |alloc_pages |alloc_pages_pgdat |__alloc_pages |rmqueue |reclaim_pages °¢ ÇÔ¼öµéÀº ¾Æ·¡ÀÇ ¸®½ºÆ®¿¡¼­ ã¾Æº¼ ¼ö ÀÖ´Ù: copy_mm [kernel/fork.c] allocate_mm [kernel/fork.c] kmem_cache_alloc [mm/slab.c] __kmem_cache_alloc kmem_cache_alloc_one alloc_new_slab kmem_cache_grow kmem_getpages __get_free_pages [mm/page_alloc.c] alloc_pages [mm/numa.c] alloc_pages_pgdat __alloc_pages [mm/page_alloc.c] rm_queue reclaim_pages [mm/vmscan.c] TODO: Understand Zones ½º¿ÍÇÎ °³¿ä ½º¿ÍÇÎÀº kswapd µ¥¸ó (Ä¿³Î ¾²·¹µå) ÀÌ °ü¸®ÇÑ´Ù. kswapd ´Ù¸¥ Ä¿³Î ¾²·¹µåµé°ú ¸¶Âù°¡Áö·Î kswapd µµ ±ú¾î³ª±â¸¦ ±â´Ù¸®´Â ¸ÞÀÎ ·çÇÁ¸¦ °¡Áø´Ù. |kswapd |// ÃʱâÈ­ ·çƾ |for (;;) { // ¸ÞÀÎ ·çÇÁ |do_try_to_free_pages |recalculate_vm_stats |refill_inactive_scan |run_task_queue |interruptible_sleep_on_timeout // »õ·Î¿î ½º¿Ò ¿äûÀÌ ÀÖÀ» ¶§±îÁö Àáµë |} kswapd [mm/vmscan.c] do_try_to_free_pages recalculate_vm_stats [mm/swap.c] refill_inactive_scan [mm/vmswap.c] run_task_queue [kernel/softirq.c] interruptible_sleep_on_timeout [kernel/sched.c] ¾ðÁ¦ ½º¿ÍÇÎÀÌ ÇÊ¿äÇÑ°¡? ½º¿ÍÇÎÀº ½ÇÁ¦ ¸Þ¸ð¸® »ó¿¡ Á¸ÀçÇÏÁö ¾Ê´Â ÆäÀÌÁö¿¡ Á¢±ÙÇÏ°íÀÚ ÇÒ ¶§ ÇÊ¿äÇÏ´Ù. ¸®´ª½º¿¡¼­´Â kswapd Ä¿³Î ¾²·¹µå¸¦ ÀÌ¿ëÇÏ¿© ÀÌ·¯ÇÑ ÀÛ¾÷À» ¼öÇàÇÑ´Ù. ŽºÅ©°¡ ÆäÀÌÁö ÆúÆ® ¿¹¿Ü¸¦ ¹Þ°Ô µÇ¸é ´ÙÀ½°ú °°Àº ÀϵéÀÌ ¼öÇàµÈ´Ù: | Page Fault Exception ÀÌ ¹ß»ýÇÏ¿´À» ¶§ | ´ÙÀ½°ú °°Àº Á¶°ÇÀ» ¸ðµÎ ¸¸Á·ÇÏ´Â °æ¿ì: | a-) »ç¿ëÀÚ ¸ðµåÀÇ ÆäÀÌÁö | b-) Àбâ ȤÀº ¾²±â¸¦ À§ÇÑ Á¢±Ù | c-) ÆäÀÌÁö°¡ ¹°¸®ÀûÀÎ ¸Þ¸ð¸®¿¡ Á¸ÀçÇÏÁö ¾ÊÀ½ | | -----------> |do_page_fault |handle_mm_fault |pte_alloc |pte_alloc_one |__get_free_page = __get_free_pages |alloc_pages |alloc_pages_pgdat |__alloc_pages |wakeup_kswapd // kswapd Ä¿³Î ¾²·¹µå¸¦ ±ú¿ò Page Fault ICA do_page_fault [arch/i386/mm/fault.c] handle_mm_fault [mm/memory.c] pte_alloc pte_alloc_one [include/asm/pgalloc.h] __get_free_page [include/linux/mm.h] __get_free_pages [mm/page_alloc.c] alloc_pages [mm/numa.c] alloc_pages_pgdat __alloc_pages wakeup_kswapd [mm/vmscan.c] ¸®´ª½º ³×Æ®¿öÅ· ¸®´ª½ºÀÇ ³×Æ®¿öÅ© °ü¸® ¹æ¹ý °¢°¢ÀÇ NIC (Network Interface Card) ÀÇ Á¾·ù¿¡ µû¶ó µð¹ÙÀ̽º µå¶óÀ̹ö°¡ Á¸ÀçÇÑ´Ù. ±× ¾È¿¡¼­´Â Ç×»ó Ç¥ÁØÀûÀÎ °í¼öÁØ ·çƾÀÎ netif_rx [net/core/dev.c] ¸¦ È£ÃâÇÒ °ÍÀÌ´Ù. ÀÌ ÇÔ¼ö´Â ÇÁ·¹ÀÓÀÌ ¼ÓÇÑ 3 ´Ü°èÀÇ ÇÁ·ÎÅäÄÝ (ÀϹÝÀûÀ¸·Î IP) À» Á¦¾îÇÏ°í, ±×¿¡ ´ëÇÑ ÀûÀýÇÑ ÇÔ¼ö¸¦ È£ÃâÇÑ´Ù. (À̸¦ À§ÇØ ÇÔ¼ö Æ÷ÀÎÅ͸¦ »ç¿ëÇÒ °ÍÀÌ´Ù) TCP ¿¹Á¦ ÀÌÁ¦ºÎÅÍ´Â ¿ì¸®°¡ ¸®´ª½º ¹Ú½º¿¡ TCP ÆÐŶÀ» º¸³½ °æ¿ì¿¡ ¾î¶² ÀÏÀÌ ÀϾ´ÂÁö »ìÆ캼 °ÍÀÌ´Ù. ÀÎÅÍ·´Æ® ó¸®: netif_rx |netif_rx |__skb_queue_tail |qlen++ |* ´Ü¼øÇÑ Æ÷ÀÎÅÍ »ðÀÔ ¿¬»ê * |cpu_raise_softirq |softirq_active(cpu) |= (1 << NET_RX_SOFTIRQ) // BH º¤ÅÍ (softirq) ³»¿¡ NET_RX_SOFTIRQ ºñÆ® ¼³Á¤ __skb_queue_tail [include/linux/skbuff.h] cpu_raise_softirq [kernel/softirq.c] ÀÎÅÍ·´Æ® ó¸® ÈÄ: net_rx_action ÀÏ´Ü IRQ °¡ ó¸®µÈ ÈÄ¿¡ ÇÁ·¹ÀÓÀÌ ¾î¶»°Ô 󸮵ǴÂÁö¿Í NET_RX_SOFTIRQ ÀÌ ¹«½¼ ÀÏÀ» ÇÏ´ÂÁö¸¦ »ìÆ캼 ÇÊ¿ä°¡ ÀÖ´Ù. ´ÙÀ½À¸·Î »ìÆ캼 ÇÔ¼ö´Â net_dev_init [net/core/dev.c] ¿¡¼­ ¼³Á¤ÇÑ net_rx_action [net/core/dev.c] ÇÔ¼öÀÌ´Ù. |net_rx_action |skb = __skb_dequeue (the exact opposite of __skb_queue_tail) |for (ptype = first_protocol; ptype < max_protocol; ptype++) // ³×Æ®¿öÅ© ÇÁ·ÎÅäÄÝÀÌ ¹«¾ùÀÎÁö ¾Ë¾Æ³¿ |if (skb->protocol == ptype) |ptype->func -> ip_rcv // ''struct ip_packet_type [net/ipv4/ip_output.c]'' ¿¡¼­ ¼³Á¤ **** ¿©±â¼­ºÎÅÍ´Â IP ÆÐŶ¿¡ ´ëÇÑ Ã³¸® **** |ip_rcv |NF_HOOK (ip_rcv_finish) |ip_route_input // È£ÃâÇÒ ÇÔ¼ö¸¦ °áÁ¤Çϱâ À§ÇØ ¶ó¿ìÆà Å×ÀÌºí °Ë»ö |skb->dst->input -> ip_local_deliver // ¾ÕÀÇ ¶ó¿ìÆà Å×ÀÌºí °Ë»ö¿¡ µû¶ó ¸ñÀûÁö´Â ·ÎÄà ¸Ó½Å |ip_defrag // IP ÆÐŶÀÇ Á¶°¢ (fragments) µéÀ» ´Ù½Ã ÇÕħ |NF_HOOK (ip_local_deliver_finish) |ipprot->handler -> tcp_v4_rcv // ''tcp_protocol [include/net/protocol.c]'' ¿¡¼­ ¼³Á¤ **** ¿©±â¼­ºÎÅÍ´Â TCP ÆÐŶ¿¡ ´ëÇÑ Ã³¸® **** |tcp_v4_rcv |sk = __tcp_v4_lookup |tcp_v4_do_rcv |switch(sk->state) *** ÆÐŶÀº ÇØ´çÇÏ´Â ¼ÒÄÏÀ» »ç¿ëÇϴ ŽºÅ©¿¡°Ô º¸³»Áø´Ù *** |case TCP_ESTABLISHED: |tcp_rcv_established |__skb_queue_tail // ÆÐŶÀ» ¼ÒÄÏÀÇ Å¥¿¡ ³ÖÀ½ |sk->data_ready -> sock_def_readable |wake_up_interruptible *** ÆÐŶÀº 3-way TCP handshake °úÁ¤¿¡ ÀÇÇØ ¿¬°áµÇ¾î¾ß ÇÑ´Ù *** |case TCP_LISTEN: |tcp_v4_hnd_req |tcp_v4_search_req |tcp_check_req |syn_recv_sock -> tcp_v4_syn_recv_sock |__tcp_v4_lookup_established |tcp_rcv_state_process *** 3-Way TCP Handshake *** |switch(sk->state) |case TCP_LISTEN: // SYN ÆÐŶÀ» ¹ÞÀ½ |conn_request -> tcp_v4_conn_request |tcp_v4_send_synack // SYN + ACK ÆÐŶÀ» º¸³¿ |tcp_v4_synq_add // set SYN state |case TCP_SYN_SENT: // SYN + ACK ÆÐŶÀ» ¹ÞÀ½ |tcp_rcv_synsent_state_process tcp_set_state(TCP_ESTABLISHED) |tcp_send_ack |tcp_transmit_skb |queue_xmit -> ip_queue_xmit |ip_queue_xmit2 |skb->dst->output |case TCP_SYN_RECV: // ACK ÆÐŶÀ» ¹ÞÀ½ |if (ACK) |tcp_set_state(TCP_ESTABLISHED) °¢ ÇÔ¼öµéÀº ¾Æ·¡¿Í °°ÀÌ Ã£¾Æº¼ ¼ö ÀÖ´Ù: net_rx_action [net/core/dev.c] __skb_dequeue [include/linux/skbuff.h] ip_rcv [net/ipv4/ip_input.c] NF_HOOK -> nf_hook_slow [net/core/netfilter.c] ip_rcv_finish [net/ipv4/ip_input.c] ip_route_input [net/ipv4/route.c] ip_local_deliver [net/ipv4/ip_input.c] ip_defrag [net/ipv4/ip_fragment.c] ip_local_deliver_finish [net/ipv4/ip_input.c] tcp_v4_rcv [net/ipv4/tcp_ipv4.c] __tcp_v4_lookup tcp_v4_do_rcv tcp_rcv_established [net/ipv4/tcp_input.c] __skb_queue_tail [include/linux/skbuff.h] sock_def_readable [net/core/sock.c] wake_up_interruptible [include/linux/sched.h] tcp_v4_hnd_req [net/ipv4/tcp_ipv4.c] tcp_v4_search_req tcp_check_req tcp_v4_syn_recv_sock __tcp_v4_lookup_established tcp_rcv_state_process [net/ipv4/tcp_input.c] tcp_v4_conn_request [net/ipv4/tcp_ipv4.c] tcp_v4_send_synack tcp_v4_synq_add tcp_rcv_synsent_state_process [net/ipv4/tcp_input.c] tcp_set_state [include/net/tcp.h] tcp_send_ack [net/ipv4/tcp_output.c] ¼³¸í: ¿ì¼± ÇÁ·ÎÅäÄÝÀÇ Å¸ÀÔÀ» °áÁ¤ÇÑ´Ù. (IP ±×¸®°í TCP) NF_HOOK(function) Àº Æ÷Àå ÇÔ¼ö·Î¼­ ¸ÕÀú ³×Æ®¿öÅ© ÇÊÅÍ (¿¹¸¦ µé¸é ¹æÈ­º®) ¸¦ ó¸®ÇÏ°í ±× ´ÙÀ½À¸·Î function ÇÔ¼ö¸¦ È£ÃâÇÑ´Ù. ±×¸®°í ¾Æ·¡¿Í °°Àº TCP ÀÇ 3-way handshake ¸¦ ¼öÇàÇÏ°í: SERVER (LISTENING) CLIENT (CONNECTING) SYN <------------------- SYN + ACK -------------------> ACK <------------------- 3-Way TCP handshake ¸¶Áö¸·À¸·Î ÆÐŶÀ» »ç¿ëÀÚ ¼ÒÄÏ¿¡ Àü´ÞÇÏ°í ±ú¿öÁÖ´Â ¿ªÇÒÀ» ÇÏ´Â tcp_rcv_established [net/ipv4/tcp_input.c] ÇÔ¼ö¸¦ È£ÃâÇÑ´Ù. ¸®´ª½º ÆÄÀÏ ½Ã½ºÅÛ TODO À¯¿ëÇÑ ÆÁ ½ºÅðú Èü °³¿ä À̹ø Àý¿¡¼­´Â ¸Þ¸ð¸® »ó¿¡ ½ºÅà °ú Èü ÀÌ ¾î¶»°Ô ÇÒ´çµÇ´ÂÁö¸¦ »ìÆ캸°Ú´Ù. ¸Þ¸ð¸® ÇÒ´ç FF.. | | <-- bottom of the stack /|\ | | | higher | | | | stack values | | | \|/ growing | | XX.. | | <-- top of the stack [Stack Pointer] | | | | | | 00.. |_________________| <-- end of stack [Stack Segment] Stack ¸Þ¸ð¸® ÁÖ¼Ò°ªÀº 00.. (½ºÅà ¼¼±×¸ÕÆ®°¡ ½ÃÀ۵Ǵ °÷À̱⵵ ÇÏ´Ù) ¿¡¼­ ºÎÅÍ ½ÃÀÛÇÏ¿© FF.. °ªÀ» °¡Áö´Â ¹æÇâÀ¸·Î Áõ°¡ÇÑ´Ù. XX.. ´Â ½ºÅà Æ÷ÀÎÅÍ°¡ ½ÇÁ¦·Î À§Ä¡ÇÏ°í ÀÖ´Â °÷ÀÇ °ªÀÌ´Ù. ½ºÅÃÀº ÇÔ¼ö¿¡¼­ ´ÙÀ½°ú °°Àº Á¤º¸¸¦ ÀúÀåÇϱâ À§ÇØ »ç¿ëÇÑ´Ù. Àü¿ª º¯¼ö (?) Áö¿ª º¯¼ö ¸®Å쵃 ÁÖ¼Ò°ª ¿¹¸¦ µé¾î, ´ÙÀ½°ú °°Àº ÀϹÝÀûÀÎ ÇÔ¼ö¸¦ Çϳª »ý°¢ÇØ º¸¸é: |int foo_function (parameter_1, parameter_2, ..., parameter_n) { |variable_1 declaration; |variable_2 declaration; .. |variable_n declaration; |// ÇÔ¼ö º»Ã¼ |dynamic variable_1 declaration; |dynamic variable_2 declaration; .. |dynamic variable_n declaration; |// ÄÚµå ºÎºÐÀº ÄÚµå ¼¼±×¸ÕÆ®¿¡ Æ÷ÇԵǹǷÎ, µ¥ÀÌŸ/½ºÅà ¼¼±×¸ÕÆ®¿¡´Â Æ÷ÇÔµÇÁö ¾ÊÀ½ |return (ret-type) value; // ¸®ÅÏ°ªÀº ƯÁ¤ ·¹Áö½ºÅÍ¿¡ ÀúÀåµÇ±âµµ ÇÑ´Ù. i386 ÀÇ °æ¿ì¿¡´Â eax ·¹Áö½ºÅ͸¦ »ç¿ëÇÑ´Ù. |} À§ÀÇ ÇÔ¼ö¿¡ ´ëÇÑ ¸Þ¸ð¸® ÇÒ´çÀº ¾Æ·¡¿Í °°ÀÌ ÀÌ·ç¾î Áú °ÍÀÌ´Ù. | | | 1. parameter_1 pushed | \ S | 2. parameter_2 pushed | | ÇÔ¼ö È£Ãâ Àü T | ................... | | A | n. parameter_n pushed | / C | ** Return address ** | -- ÇÔ¼ö È£Ãâ K | 1. local variable_1 | \ | 2. local variable_2 | | ÇÔ¼ö È£Ãâ ÈÄ | ................. | | | n. local variable_n | / | | ... ... ½ºÅÃÀÇ ¿©À¯ °ø°£ ... ... | | H | n. dynamic variable_n | \ E | ................... | | malloc À̳ª kmalloc A | 2. dynamic variable_2 | | ¿¡ ÀÇÇØ ÇÒ´çµÈ °ø°£ P | 1. dynamic variable_1 | / |_______________________| Typical stack usage º¯¼ö°¡ ½ºÅÿ¡ ÀúÀåµÇ´Â ¼ø¼­´Â Çϵå¿þ¾îÀÇ ±¸Á¶¿¡ µû¶ó ´Þ¶óÁú ¼ö ÀÖ´Ù. ÀÀ¿ë ÇÁ·Î±×·¥ (Application) °ú ÇÁ·Î¼¼½º ±âº»ÀûÀÎ Á¤ÀÇ ´ÙÀ½ 2 °¡ÁöÀÇ °³³äÀ» ±¸ºÐÇØ¾ß ÇÑ´Ù. ÀÀ¿ë ÇÁ·Î±×·¥: ¿ì¸®°¡ ½ÇÇàÇϱ⸦ ¿øÇÏ´Â À¯¿ëÇÑ ÄÚµå ÇÁ·Î¼¼½º: ¸Þ¸ð¸® »ó¿¡ ÀÖ´Â ÀÀ¿ë ÇÁ·Î±×·¥ÀÇ À̹ÌÁö (ÀÌ°ÍÀº »ç¿ëµÈ ¸Þ¸ð¸® °ü¸® Àü·«, ¼¼±×¸ÕÅ×ÀÌ¼Ç È¤Àº ÆäÀÌÁö³×À̼Ç, ¿¡ ÀÇÁ¸ÇÑ´Ù). ÇÁ·Î¼¼½º´Â Á¾Á¾ ŽºÅ© ȤÀº ¾²·¹µå ¶ó°í ºÒ¸®¿ì±âµµ ÇÑ´Ù. ¶ô (locks) °³¿ä Å©°Ô ´ÙÀ½°ú °°Àº 2 Á¾·ùÀÇ ¶ôÀÌ ÀÖ´Ù: CPU ³»ºÎÀûÀÎ ¶ô (intraCPU) CPU °£ÀÇ ¶ô (interCPU) Copy on Write Copy on Write ´Â ¸Þ¸ð¸®ÀÇ »ç¿ëÀ» ÁÙÀ̱â À§ÇÑ ¸ÞÄ«´ÏÁòÀÌ´Ù. ÀÌ´Â ¸Þ¸ð¸®ÀÇ ÇÒ´çÀ» ¸Þ¸ð¸®°¡ ½ÇÁ¦·Î ÇÊ¿äÇÑ ½ÃÁ¡±îÁö ¹Ì·ç´Â °ÍÀÌ´Ù. ¿¹¸¦ µé¸é, ŽºÅ©°¡ (»õ·Î¿î ŽºÅ©¸¦ »ý¼ºÇϱâ À§ÇØ) fork() ½Ã½ºÅÛ ÄÝÀ» È£ÃâÇÏ´Â °æ¿ì, ÀÚ½Ä Å½ºÅ©´Â Àбâ Àü¿ë ¸ðµå (RO Access) ·Î ºÎ¸ð ŽºÅ©ÀÇ ¸Þ¸ð¸® ÆäÀÌÁö¸¦ °øÀ¯ÇÑ´Ù. ÀÌÈÄ¿¡ ÀÌ ÆäÀÌÁö¿¡ ´ëÇÑ ¾²±â ¿¬»êÀÌ ¼öÇàµÇ´Â °æ¿ì¿¡ ¿¹¿Ü ¿ªÀÚÁÖ: ÆäÀÌÁö ÆúÆ® (Page Fault) ¿¹¿Ü¿¡ ÇØ´çÇÑ´Ù. °¡ ¹ß»ýµÇ°í ÆäÀÌÁö´Â º¹»çµÇ°í Àб⾲±â ¸ðµå (RW Access) ·Î ¼³Á¤µÈ´Ù. ÆäÀÌÁö X ´Â ºÎ¸ð ŽºÅ©¿Í ÀÚ½Ä Å½ºÅ© °£¿¡ °øÀ¯µÈ´Ù. Task Parent | | RO Access ______ | |---------->|Page X| |_________| |______| /|\ | Task Child | | | RO Access | | |---------------- |_________| ¾²±â ¿äûÀÌ ÀϾ´Â °æ¿ì Task Parent | | RO Access ______ | |---------->|Page X| Trying to write |_________| |______| /|\ | Task Child | | | RO Access | | |---------------- |_________| ¸¶Áö¸· ¼³Á¤: °¢°¢ÀÇ Å½ºÅ©´Â µ¶¸³µÈ ÆäÀÌÁö X ¿Í Y ¸¦ °¡Áø´Ù. Task Parent | | RW Access ______ | |---------->|Page X| |_________| |______| Task Child | | RW Access ______ | |---------->|Page Y| |_________| |______| 80386 CPU ¿¡ ´ëÇÑ ºÎºÐµé ºÎÆà °úÁ¤ bbootsect.s [arch/i386/boot] setup.S (+video.S) head.S (+misc.c) [arch/i386/boot/compressed] start_kernel [init/main.c] 80386 (±× ÀÌÈÄ ¹öÀü Æ÷ÇÔ) ÀÇ µð½ºÅ©¸³ÅÍ(Descriptors) °³¿ä µð½ºÅ©¸³ÅÍ´Â ÀÎÅÚ i386+ ¸¶ÀÌÅ©·ÎÇÁ·Î¼¼¼­ÀÇ °¡»ó ¸Þ¸ð¸®¿¡¼­ »ç¿ëµÇ´Â ÀÚ·á ±¸Á¶ÀÌ´Ù. µð½ºÅ©¸³ÅÍÀÇ Á¾·ù GDT (Global Descriptor Table) LDT (Local Descriptor Table) IDT (Interrupt Descriptor Table) IRQ °³¿ä IRQ ´Â ¿äûÇÑ ÀÛ¾÷ÀÌ ¿Ï·áµÇ¾úÀ½À» ¾Ë·ÁÁÖ±â À§ÇØ ¸¶ÀÌÅ©·ÎÇÁ·Î¼¼¼­¿¡°Ô º¸³»Áö´Â ºñµ¿±âÀûÀÎ ½Ã±×³ÎÀÌ´Ù. »óÈ£ÀÛ¿ë µµ½Ä (Interaction Schema) |<--> IRQ(0) [Timer] |<--> IRQ(1) [Device 1] | .. |<--> IRQ(n) [Device n] _____________________________| /|\ /|\ /|\ | | | \|/ \|/ \|/ Task(1) Task(2) .. Task(N) IRQ - Tasks Interaction Schema ¹«½¼ ÀÏÀÌ ÀϾ´Â°¡? ÀϹÝÀûÀÎ ¿î¿µÃ¼Á¦´Â ÇÁ·Î¼¼½ºÀÇ ½ÇÇàÀ» ÁßÁö (interrupt) ½ÃÅ°°í ½Ã½ºÅÛÀ» °ü¸®ÇÏ´Â ÀÛ¾÷µéÀ» ¼öÇàÇϱâ À§ÇØ ¸¹Àº IRQ ½Ã±×³ÎÀ» »ç¿ëÇÑ´Ù. IRQ (i) °¡ ¹ß»ýÇÏ°í Task (j) ´Â ÀÎÅÍ·´Æ®µÈ´Ù. IRQ(i)_handler °¡ ½ÇÇàµÈ´Ù. Á¦¾î´Â Task (j) ÀÇ ÀÎÅÍ·´Æ®µÈ ºÎºÐÀ¸·Î µ¹¾Æ¿Â´Ù. ¸®´ª½º¿¡¼­´Â IRQ °¡ ¹ß»ýÇÏ¿´À» ¶§, ¸ÕÀú IRQ Æ÷Àå ÇÔ¼ö (interrupt0x?? °ú °°Àº À̸§ÀÏ °ÍÀÌ´Ù) °¡ ½ÇÇàµÇ°í ´ÙÀ½À¸·Î °ø½ÄÀûÀÎ IRQ(i)_handler °¡ ½ÇÇàµÉ °ÍÀÌ´Ù. ÀÌ°ÍÀº ŸÀÓ ½½¶óÀ̽º ¼±Á¡°ú °°Àº ¸î¸î°¡Áö ÀÛ¾÷µéÀ» °¡´ÉÇÏ°Ô ÇØÁØ´Ù. À¯Æ¿¸®Æ¼ ÇÔ¼öµé list_entry [include/linux/list.h] Á¤ÀÇ: #define list_entry(ptr, type, member) \ ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member))) ÀǹÌ: list_entry ¸ÅÅ©·Î´Â ±¸Á¶Ã¼ ³»ºÎÀÇ ¸â¹ö¿¡ ´ëÇÑ Æ÷ÀÎÅ͸¦ ÅëÇؼ­ ±× ±¸Á¶Ã¼ ÀÚüÀÇ Æ÷ÀÎÅ͸¦ ¾ò¾î³»±â À§ÇØ »ç¿ëµÈ´Ù. struct __wait_queue { unsigned int flags; struct task_struct * task; struct list_head task_list; }; struct list_head { struct list_head *next, *prev; }; // wait queue ¿¡ ´ëÇÑ Å¸ÀÔÀ» Á¤ÀÇÇÏ°í typedef struct __wait_queue wait_queue_t; // ´ÙÀ½°ú °°ÀÌ »ç¿ëÇÑ´Ù. wait_queue_t *out = list_entry(tmp, wait_queue_t, task_list); // ÀÌ ¶§ tmp ´Â list_head ¸¦ °¡¸®Å°´Â Æ÷ÀÎÅÍ¿©¾ß ÇÑ´Ù. Áï, ÀÌ °æ¿ì¿¡´Â *tmp [list_head] Æ÷ÀÎÅ͸¦ ÅëÇØ *out [wait_queue_t] Æ÷ÀÎÅ͸¦ ¾ò¾î³Â´Ù. ____________ <---- *out [we calculate that] |flags | /|\ |task *--> | | |task_list |<---- list_entry | prev * -->| | | | next * -->| | | |____________| ----- *tmp [we have this] Sleep Sleep Code ÆÄÀÏ: kernel/sched.c include/linux/sched.h include/linux/wait.h include/linux/list.h ÇÔ¼ö: interruptible_sleep_on interruptible_sleep_on_timeout sleep_on sleep_on_timeout ºÒ·ÁÁö´Â ÇÔ¼ö: init_waitqueue_entry __add_wait_queue list_add __list_add __remove_wait_queue ÇÔ¼ö°£ È£Ã⠺м®: |sleep_on |init_waitqueue_entry -- |__ add_wait_queue | ¿äûÇÑ ÀÛ¾÷À» Å¥¿¡ Áý¾î ³ÖÀ½ |list_add | |__list_add -- |schedule --- ¿äûÇÑ ÀÛ¾÷ÀÌ ¼öÇàµÉ ¼ö ÀÖÀ»¶§ ±îÁö ±â´Ù¸² |__remove_wait_queue -- |list_del | Å¥¿¡¼­ ¿äûÀ» ÀÛ¾÷À» ²¨³»¿È |__list_del -- ¼³¸í: ¸®´ª½º¿¡¼­ °¢°¢ÀÇ ÀÚ¿øµéÀº (ÀÌ»óÀûÀ¸·Î °´Ã¼´Â ´Ù¼öÀÇ »ç¿ëÀÚ¿Í ÇÁ·Î¼¼½º »çÀÌ¿¡¼­ °øÀ¯µÈ´Ù) ÀÚ½ÅÀ» ¿äûÇÑ ¸ðµç ŽºÅ©¸¦ °ü¸®Çϱâ À§Çؼ­ Å¥¸¦ °¡Áø´Ù. ÀÌ·¯ÇÑ Å¥¸¦ wait queue ¶ó°í Çϸç, ÀÌ°ÍÀº ¸¹Àº ¸â¹öµéÀ» Æ÷ÇÔÇÏ°í ÀÖ´Ù (¾ÕÀ¸·Î ÀÌ°ÍÀº wait queue element ¶ó°í ºÎ¸£°Ú´Ù): *** wait queue structure [include/linux/wait.h] *** struct __wait_queue { unsigned int flags; struct task_struct * task; struct list_head task_list; } struct list_head { struct list_head *next, *prev; }; ±×¸²À¸·Î ³ªÅ¸³»¸é: *** wait queue element *** /|\ | <--[prev *, flags, task *, next *]--> *** wait queue list *** /|\ /|\ /|\ /|\ | | | | --> <--[task1]--> <--[task2]--> <--[task3]--> .... <--[taskN]--> <-- | | |__________________________________________________________________| *** wait queue head *** task1 <--[prev *, lock, next *]--> taskN wait queue head À̶ó´Â Æ÷ÀÎÅÍ´Â wait queue list ÀÇ Ã¹¹ø° ¿ø¼Ò (next *) ¿Í ¸¶Áö¸· ¿ø¼Ò (prev *) ¸¦ °¡¸®Å²´Ù. »õ·Î¿î ¿ø¼Ò°¡ Çϳª »ðÀԵǾî¾ß ÇÒ ¶§´Â __add_wait_queue [include/linix/wait.h} °¡ È£ÃâµÈ´Ù. ÀÌ°ÍÀº ÀϹÝÀûÀÎ ÇÔ¼öÀÎ list_add [include/linux/list.h] ¸¦ ½ÇÇà½Ãų °ÍÀÌ´Ù: *** function list_add [include/linux/list.h] *** // classic double link list insert static __inline__ void __list_add (struct list_head * new, \ struct list_head * prev, \ struct list_head * next) { next->prev = new; new->next = next; new->prev = prev; prev->next = new; } ¸¶Áö¸·À¸·Î »ìÆ캼 ÇÔ¼ö´Â __list_del [include/linux/list.h] ÀÌ´Ù. ÀÌ ÇÔ¼ö´Â remove_wait_queue [include/linux/wait.h] ÇÔ¼ö ³»ºÎ¿¡¼­ list_del [include/linux/list.h] ÇÔ¼ö¿¡ ÀÇÇØ È£ÃâµÈ´Ù: *** function list_del [include/linux/list.h] *** // classic double link list delete static __inline__ void __list_del (struct list_head * prev, struct list_head * next) { next->prev = prev; prev->next = next; } ½ºÅÃÀÇ °í·Á ÀϹÝÀûÀÎ ¸®½ºÆ® (ȤÀº Å¥) ´Â º¸Åë Èü ¿µ¿ª¿¡ ÇÒ´çÇÏ¿© °ü¸®ÇÑ´Ù. (½ºÅðú Èü¿¡ °üÇÑ ³»¿ëÀº   À» Âü°íÇϱ⠹ٶõ´Ù) ÇÏÁö¸¸ ¿©±â¼­´Â Wait Queue µ¥ÀÌŸ¸¦ Áö¿ª º¯¼ö·Î (½ºÅÃ) ÇÒ´çÇÏ¿´±â ¶§¹®¿¡ ÇÔ¼ö°¡ ½ºÄÉÁÙ¸µµÇ¾î ¸®ÅϵǸé Áö¿ª º¯¼ö¸¦ Áö¿ì°Ô µÉ °ÍÀÌ´Ù..??? new task <----| task1 <------| task2 <------| | | | | | | |..........| | |..........| | |..........| | |wait.flags| | |wait.flags| | |wait.flags| | |wait.task_|____| |wait.task_|____| |wait.task_|____| |wait.prev |--> |wait.prev |--> |wait.prev |--> |wait.next |--> |wait.next |--> |wait.next |--> |.. | |.. | |.. | |schedule()| |schedule()| |schedule()| |..........| |..........| |..........| |__________| |__________| |__________| Stack Stack Stack Á¤Àû º¯¼öµé °³¿ä ¸®´ª½º´Â C ¾ð¾î·Î Â¥¿©Á³À¸¸ç, ´Ù¸¥ ÀÀ¿ë ÇÁ·Î±×·¥µé°ú °°ÀÌ ´ÙÀ½°ú °°Àº °ÍµéÀ» Æ÷ÇÔÇÑ´Ù: Áö¿ª º¯¼ö ¸ðµâ º¯¼ö (¼Ò½º ÆÄÀÏ¿¡ Á¸ÀçÇϸç, ¿ÀÁ÷ ±× ¸ðµâ ³»¿¡¼­¸¸ »ç¿ëµÇ´Â º¯¼ö) ¿ÀÁ÷ 1 °³ ¸¸ÀÌ Á¸ÀçÇÏ´Â Àü¿ª/Á¤Àû º¯¼ö (¸ðµç ¸ðµâ¿¡¼­ Á¢±Ù °¡´ÉÇÑ º¯¼ö) ÇÑ ¸ðµâ¿¡¼­ Á¤Àû º¯¼ö °ªÀ» ¼öÁ¤Çϸé, ´Ù¸¥ ¸ðµâ¿¡¼­µµ º¯È­µÈ °ªÀÌ »ç¿ëµÉ °ÍÀÌ´Ù. ¸®´ª½º¿¡¼­ Á¤Àû º¯¼ö´Â ¸Å¿ì Áß¿äÇÑ ¿ªÇÒÀ» ÇÑ´Ù. À̸¦ ÀÌ¿ëÇؼ­ Ä¿³Î¿¡ »õ·Î¿î ±â´ÉÀ» Ãß°¡ÇÒ ¼ö ÀÖµµ·Ï ÇØ Áֱ⠶§¹®ÀÌ´Ù: À̵é Á¤Àû º¯¼ö´Â ÁÖ·Î µî·ÏµÈ ¿ø¼ÒµéÀÇ ¸®½ºÆ®ÀÇ ¸Ç óÀ½À» °¡¸®Å°´Â Æ÷ÀÎÅÍÀÏ °ÍÀ̸ç, ´ÙÀ½°ú °°Àº ÀϵéÀÌ °¡´ÉÇÏ´Ù: Ãß°¡ »èÁ¦ ¼öÁ¤ _______ _______ _______ Global variable -------> |Item(1)| -> |Item(2)| -> |Item(3)| .. |_______| |_______| |_______| ÁÖ¿ä º¯¼öµé current ________________ Current ----------------> | Actual process | |________________| current ´Â task_struct ±¸Á¶Ã¼¸¦ °¡¸®Å²´Ù. ÀÌ ±¸Á¶Ã¼´Â ´ÙÀ½°ú °°ÀÌ ÇÁ·Î¼¼½º¿¡ ´ëÇÑ ¸ðµç Á¤º¸¸¦ Æ÷ÇÔÇÏ°í ÀÖ´Ù: pid, À̸§, »óÅÂ, ŸÀÓ ½½¶óÀ̽º, ½ºÄÉÁÙ¸µ Á¤Ã¥ ´Ù¸¥ ÀÚ·á ±¸Á¶¿¡ ´ëÇÑ Æ÷ÀÎÅ͵é: files, vfs, signal, ´Ù¸¥ ÇÁ·Î¼¼½º, .. »ç½Ç current Àº ½ÇÁ¦ º¯¼ö°¡ ¾Æ´Ï¶ó ´ÙÀ½°ú °°Àº ÇÔ¼öÀÇ ÇüÅÂÀÌ´Ù. static inline struct task_struct * get_current(void) { struct task_struct *current; __asm__("andl %%esp,%0; ":"=r" (current) : "0" (~8191UL)); return current; } #define current get_current() À§¿¡¼­ º¸µíÀÌ esp ·¹Áö½ºÅÍ (½ºÅà Æ÷ÀÎÅÍ) ÀÇ °ªÀ» ÀÌ¿ëÇÏ¿© ÇöÀçÀÇ task_struct ±¸Á¶Ã¼ÀÇ Æ÷ÀÎÅ͸¦ ¾ò¾î¿À°Ô µÈ´Ù. ¿ªÀÚÁÖ: °¢ ÇÁ·Î¼¼½º´Â ÀÚ½ÅÀÇ task_struct ±¸Á¶Ã¼¿Í ½ºÅà °ø°£À» 8192 ¹ÙÀÌÆ® ´ÜÀ§·Î ÇÒ´ç¹Þ´Â´Ù. ÇÒ´ç¹ÞÀº °ø°£ÀÇ °¡Àå ¾Æ·¡ÂÊ¿¡ task_struct ±¸Á¶Ã¼°¡ À§Ä¡ÇÏ°í, °¡Àå À§ÂʺÎÅÍ ½ºÅÃÀ¸·Î ÀÌ¿ëÇϹǷΠÇöÀç ½ºÅà Æ÷ÀÎÅÍÀÇ ÇÏÀ§ 13 ºñÆ®¸¦ Áö¿ì¸é 8192 Å©±â ºí·°ÀÇ °¡Àå ÇÏÀ§ ÁÖ¼Ò¸¦ ¾òÀ» ¼ö ÀÖ°í, ÀÌ´Â task_struct ±¸Á¶Ã¼ÀÇ ÁÖ¼Ò°¡ µÈ´Ù. current º¯¼ö¸¦ ÀÌ¿ëÇÏ¿© ´Ù¸¥ ÇÁ·Î¼¼½ºµé (´Ù¸¥ »óÅ¿¡ ÀÖ´Â ÇÁ·Î¼¼½ºµéÀ» Æ÷ÇÔÇÏ¿©) ÀÇ ÀÚ·á ±¸Á¶¿¡ Á¢±ÙÇÒ ¼ö ÀÖ´Ù. ¿¹¸¦ µé¾î, (I/O µå¶óÀ̹ö¿¡¼­ ÇϵíÀÌ) ÇÁ·Î¼¼½ºÀÇ »óŸ¦ º¯È­½ÃÅ°°Å³ª, pid, Áغñ ¸®½ºÆ® ȤÀº ºí·Ï ¸®½ºÆ®¸¦ ¼öÁ¤ÇÏ´Â ÀÏ µîÀÌ °¡´ÉÇÏ´Ù. µî·ÏµÈ ÆÄÀÏ ½Ã½ºÅÛ ______ _______ ______ file_systems ------> | ext2 | -> | msdos | -> | ntfs | [fs/super.c] |______| |_______| |______| ¸¸¾à ½©¿¡¼­ modprobe some_fs ¶ó´Â ¸í·ÉÀ» ÀÔ·ÂÇÑ´Ù¸é ÆÄÀÏ ½Ã½ºÅÛÀÇ ¸®½ºÆ®¿¡ »õ·Î¿î ¿£Æ®¸®°¡ Ãß°¡µÉ °ÍÀÌ´Ù. ¹Ý´ë·Î (rmmod ¸í·ÉÀ» ÀÌ¿ëÇؼ­) ÆÄÀÏ ½Ã½ºÅÛÀÇ ¸®½ºÆ®¿¡¼­ Áö¿ï ¼ö ÀÖ´Ù. ¸¶¿îÆ®µÈ ÆÄÀÏ ½Ã½ºÅÛ ______ _______ ______ mount_hash_table ---->| / | -> | /usr | -> | /var | [fs/namespace.c] |______| |_______| |______| mount ¸í·ÉÀ» ÀÌ¿ëÇؼ­ ÆÄÀÏ ½Ã½ºÅÛÀ» Ãß°¡ÇÏ´Â °æ¿ì, ÀÌ ¸®½ºÆ®¿¡ »õ·Î¿î ¿ø¼Ò°¡ Ãß°¡µÈ´Ù. ¹Ý´ë·Î unmount ¸í·ÉÀº ¸®½ºÆ®¿¡¼­ ¿ø¼Ò¸¦ Áö¿ï °ÍÀÌ´Ù. µî·ÏµÈ ³×Æ®¿öÅ© ÆÐŶ ŸÀÔ ______ _______ ______ ptype_all ------>| ip | -> | x25 | -> | ipv6 | [net/core/dev.c] |______| |_______| |______| ¿¹¸¦ µé¾î, IPv6 ¿¡ ´ëÇÑ Áö¿øÀ» Ãß°¡ÇÑ´Ù¸é (°ü·ÃµÈ ¸ðµâÀ» ·Îµù) ÀÌ ¸®½ºÆ®¿¡ »õ·Î¿î ¿ø¼Ò°¡ Ãß°¡µÉ °ÍÀÌ´Ù. µî·ÏµÈ ³×Æ®¿öÅ© ÀÎÅÍ³Ý ÇÁ·ÎÅäÄÝ ______ _______ _______ inet_protocol_base ----->| icmp | -> | tcp | -> | udp | [net/ipv4/protocol.c] |______| |_______| |_______| ¶ÇÇÑ (IPv6 ¿Í °°Àº) ´Ù¸¥ ÆÐŶ ŸÀԵ鿡¼­ ´ëÇؼ­µµ °¢°¢ÀÇ ¸®½ºÆ®¿¡ ¸¹Àº ÀÎÅÍ³Ý ÇÁ·ÎÅäÄÝ Á¤º¸¸¦ °¡Áö°í ÀÖ´Ù. ______ _______ _______ inet6_protos ----------->|icmpv6| -> | tcpv6 | -> | udpv6 | [net/ipv6/protocol.c] |______| |_______| |_______| µî·ÏµÈ ³×Æ®¿öÅ© ÀåÄ¡ ______ _______ _______ dev_base --------------->| lo | -> | eth0 | -> | ppp0 | [drivers/core/Space.c] |______| |_______| |_______| µî·ÏµÈ ¹®ÀÚ ÀåÄ¡ ______ _______ ________ chrdevs ---------------->| lp | -> | keyb | -> | serial | [fs/devices.c] |______| |_______| |________| chrdevs Àº ½ÇÁ¦·Î ¸®½ºÆ®¿¡ ´ëÇÑ Æ÷ÀÎÅÍ°¡ ¾Æ´Ï¶ó, Ç¥ÁØÀûÀÎ º¤ÅÍ (¹è¿­?) ¿¡ ´ëÇÑ Æ÷ÀÎÅÍÀÌ´Ù. µî·ÏµÈ ºí·° ÀåÄ¡ ______ ______ ________ bdev_hashtable --------->| fd | -> | hd | -> | scsi | [fs/block_dev.c] |______| |______| |________| bdev_hashtable Àº Çؽ¬ º¤ÅÍÀÌ´Ù. ¿ë¾î ¸µÅ© °ø½Ä ¸®´ª½º Ä¿³Î ½ÎÀÌÆ® ¸®´ª½º Ä¿³Î¿¡ ´ëÇÑ À¯¿ëÇÑ ¹®¼­ °ø½Ä Ä¿³Î ¸ÞÀϸµ ¸®½ºÆ® ¸®´ª½º ¹®¼­È­ ÇÁ·ÎÁ§Æ® °¡ÀÌµå ¸®´ª½º Çѱ۹®¼­ ÇÁ·ÎÁ§Æ® ÀÌÈ£´ÔÀÇ ¸®´ª½º Ä¿³Î ȨÆäÀÌÁö Çѱ¹ ÀÓº£µðµå ¸®´ª½º ÇÁ·ÎÁ§Æ®
}}}