Powered by AdLogger, Click Fraud Protection.
HOME | WIKI | JOINC RSS | °Ô½ÃÆÇ RSS    lynx ¿¡¼­µµ (±¤°í¸¸ »©°í)¹®Á¦¾øÀÌ º¸ÀÌ´Â »çÀÌÆ® JOINC
WIKI ÆäÀÌÁö
x man page
x ¹Ì´Ï»çÀÌÆ®
x Àüü±â»ç¸ñ·Ï
x ±â»çÁÖÁ¦º°
x Á¶°¢ÄÚµå
x ÆÁ¸ðÀ½
x ´ÚºÏ¿ø¹®µé
x ÄÄÇ»ÅÍ¿ë¾î»çÀü
x FAQ
x JCvs
x ¸µÅ©¸ðÀ½
x ÀÚ·á¹æ

·Î±×ÀÎ
¾ÆÀ̵ð

ÆÐ½º¿öµå

°¡ÀÔÇϱâ

°Ô½ÃÆÇ
x ¹¯°í´äÇϱâ
x ²ôÀûÀ̱â
x ÆÁ¸ðÀ½
x »õ¼Ò½Ä
x ±¤°í/È«º¸
x Á¦¾È¹× Àǰß

Åë°è
MRTG Æ®·¡ÇÈÁ¤º¸
À¥·Î±×ºÐ¼® º¸±â
Á¢±ÙÁ¤º¸ º¸±â
3,054 ÀÏ ¿î¿µÁß

´º½º±×·ì
han.comp.lang.c
han.comp.lang.c++

±âº»¹®¼­
o ÀÌ »çÀÌÆ®¿¡ ´ëÇØ¼­
o Âü¿©Çϱâ
o docbook »ç¿ëÇϱâ
o vim »ç¿ëÇϱâ
o C++ÇÁ·Î±×·¡¹Ö HOWTO
o CÇÁ·Î±×·¡¹Ö FAQ

   ÀλýÀº ´ÙÀ½ µÎ°¡Áö·Î ¼º¸³µÈ´Ù. ÇÏ°í ½ÍÁö¸¸ ÇÒ ¼ö ¾ø´Ù. ÇÒ ¼ö ÀÖÁö¸¸ ÇÏ°í ½ÍÁö ¾Ê´Ù. - ±«Å× -
¾²·¹µåÇ® ÀÛ¼º
Posted on 2002/12/23
Topic: ±âº»¶óÀ̺귯¸®
¾²·¹µå Ç®Àº ¿¬°á/Á¾·á°¡ ÀÚÁÖÀϾ´Â À¥¼­¹ö¿Í °°Àº ¹Ù»Û ¼­¹ö¿¡°Ô À־ È¿À²ÀûÀΠŬ¶óÀÌ¾ðÆ® ¿¬°á 󸮸¦ À§Çؼ­ »ç¿ëÇÏ´Â ÇÁ·Î±×·¡¹Ö ±â¹ýÀÌ´Ù. À̹ø¿¡´Â ¾²·¹µåÇ®À» ÀÌ¿ëÇÑ ¾îÇø®ÄÉÀÌ¼Ç Á¦ÀÛ¹æ¹ý¿¡ ´ëÇØ¼­ ¾Ë¾Æº¸µµ·Ï ÇϰڴÙ.

Thread Pooling

Thread Pooling

À± »ó¹è

dreamyun@yahoo.co.kr

교정 과정
교정 0.72003³â 1¿ù 24ÀÏ 14½Ã
Thread Pool ±¸¼ºµµ À̹ÌÁö Ãß°¡,¹®¼­ È÷½ºÅ丮 Ãß°¡


1절. Thread Pooling

1.1절. Thread Pooling À̶õ

pool ÀÇ »çÀüÀûÀÎ ¶æÀ» ã¾Æº¸¸é ¿¬¸ø, Àú¼öÁö, ¼ö¿µÀå Ç® µî "¹«¾ùÀ» ´ã¾Æ³õ´Â" ÀÇ ¶æÀ» °¡Áø´Ù. ÀÌ´ë·Î ÇØ¼®ÇÏÀÚ¸é Thread Pooling À̶õ ¾²·¹µå¸¦ ´ã¾Æ ³õ´Â ¿ë±â(¸Þ¸ð¸®°¡ µÉ°ÍÀÌ´Ù) ¸¦ ¶æÇϸç, ÇÁ·Î±×·¡¹Ö Ãø¸é¿¡¼­ ÇØ¼®ÇÏÀÚ¸é, "¹Ì¸® ¾²·¹µå¸¦ ÇÒ´ç½ÃÄÑ ³õ´Â±â¹ý" À» ¶æÇÑ´Ù.

±×·¸´Ù¸é ¾²·¹µå¸¦ ¹Ì¸® ÇÒ´ç½ÃÄÑ ³õ´Â ÀÌÀ¯¿¡ ´ëÇØ¼­ »ý°¢Çغ¸ÀÚ, Áö±Ý±îÁö ÀÌ »çÀÌÆ®¿¡¼­ ´Ù·ç¾ú´ø ¾²·¹µåÇÁ·Î±×·¡¹Ö ±â¹ýÀº ±âº»ÀûÀ¸·Î fork ¹æ½Ä°ú ¸Å¿ì ºñ½ÁÇϸç, ¾²·¹µå¸¦ »ý¼º½ÃÄÑ¾ß µÉ Çʿ䰡 ÀÖÀ»¶§ pthread_create(3)µîÀÇ ÇÔ¼ö¸¦ ÀÌ¿ëÇÏ¿© »õ·Î¿î ÀÛ¾÷¾²·¹µå¸¦ »ý¼º½ÃŰ´Â ¹æ½ÄÀ» »ç¿ëÇß´Ù. º¸Åë ¾²·¹µåÇÁ·Î±×·¡¹ÖÀº ³×Æ®¿÷ ÇÁ·Î±×·¡¹Ö½Ã ÁÖ·Î »ç¿ëµÊÀ¸·Î accept(2) ·Î ¿¬°áÀ» ±â´Ù¸®´Ù°¡ ¿¬°áÀÌ ¸¸µé¾îÁö¸é accept ¿¡¼­ ³Ñ¾î¿Â ¼ÒÄÏ Áö½ÃÀÚ¸¦ ÀÎÀÚ·Î ÇÏ´Â ¾²·¹µå¸¦ »ý¼ºÇß´Ù.

ÀÌ·¯ÇÑ ¹æ½Ä - ¿äûÀÌ ÀÖÀ»¶§ ¾²·¹µå¸¦ »ý¼º½ÃŰ´Â - ÀÇ ¾²·¹µå ÇÁ·Î±×·¡¹Ö±â¹ýÀº ´ëºÎºÐÀÇ ÀÛ¾÷À» ó¸®Çϱ⿡ ÃæºÐÈ÷ È¿À²ÀûÀ̸ç, ºü¸£±äÇÏÁö¸¸ Ŭ¶óÀÌ¾ðÆ®·Î ºÎÅÍÀÇ ¿¬°á°ú Á¾·á°¡ ¸Å¿ì ¹Ù»Ú°Ô ÀϾ´Â ¼­¹öÀÇ °æ¿ì, °è¼ÓÀûÀ¸·Î ¾²·¹µå¸¦ »ý¼ºÇϰí Á¾·áÇØ¾ß ÇÏ´Â ºñ¿ëÀ» ¹«½ÃÇÒ¼ö ¾ø°Ô µÈ´Ù. ¾²·¹µå°¡ ºñ·Ï fork()¿¡ ºñÇØ¼­ »ý¼º°ú ¼Ò¸ê½Ã¿¡ ÈξÀ ÀûÀº ºñ¿ëÀ» ¼Ò¸ðÇÑ´Ù°í´Â ÇÏÁö¸¸, ÀÌ°Ç ¾îµð±îÁö³ª »ó´ëÀûÀÎ °ÍÀ¸·Î ½Ç»óÀº ²Ï ¸¹Àº ½Ã°£°ú ºñ¿ëÀ» ¼ÒºñÇÏ´Â ÀÛ¾÷ÀÌ´Ù. ƯÈ÷ Linux ¿¡¼­ÀÇ Pthread ÀÇ °æ¿ì clone(2)¸¦ ÀÌ¿ëÇÑ ±¸ÇöÀÓÀ¸·Î ´õ¿í´õ ¸¹Àº ºñ¿ëÀ» ¼ÒºñÇÏ°Ô µÈ´Ù.

Thread Pooling Àº ÀÌ·¯ÇÑ ¹Ýº¹ÀûÀÎ ¾²·¹µåÀÇ »ý¼º/¼Ò¸ê¿¡ ÀÇÇÑ ºñÈ¿À²ÀûÀÎ Ãø¸éÀ» ¾ø¾Ö°íÀÚ ÇÏ´Â ¸ñÀûÀ¸·Î ¸¸µé¾îÁø ÇÁ·Î±×·¡¹Ö ±â¹ýÀÌ´Ù.


1.1.1절. Thread PoolÀÇ ±¸Çö¹æ½Ä

°³³äÀûÀ¸·Î º¸ÀÚ¸é Thread Pool À» ±¸¼ºÇÏ´Â°Ç ¸Å¿ì °£´ÜÇÏ´Ù. »ý¼ºÇϰíÀÚ ÇÏ´Â Å©±â¸¸Å­ ptread_create() ÇÔ¼ö¸¦ µ¹¸®¸é µÇ±â ¶§¹®ÀÌ´Ù.

ÇÏÁö¸¸ ÀÌ°Ç ¾îµð±îÁö³ª °³³äÀûÀÎ °ÍÀ¸·Î ´ëºÎºÐÀÇ °æ¿ì °¢°¢ÀÇ ¾²·¹µå¸¦ ½ºÄÉÁ층 ÇØÁÖ¾î¾ß ÇÔÀ¸·Î, ¶§¿¡ µû¶ó¼­´Â ±¸ÇöÀ» À§Çؼ­ ¸Å¿ì º¹ÀâÇÑ ÇÁ·Î±×·¡¹Ö ±â¹ýÀ» µ¿¿øÇØ¾ß ÇÒ¶§µµ ÀÖ´Ù. °£´ÜÈ÷ À¥ ¼­¹ö¸¦ Thread Pool ·Î ±¸ÇöÇÑ´Ù°í °¡Á¤À» ÇØº¸ÀÚ - º¸Åë À¥¼­¹ö´Â HTTP ÀÇ Æ¯¼º»ó ¿¬°á°ú/Á¾·á°¡ ºó¹øÇÏ°Ô ÀÏ¾î ³²À¸·Î ¾²·¹µåÇ®À» »ç¿ëÇÒ°æ¿ì ¸¹Àº ÀÌÀÍÀ» ¾òÀ»¼ö ÀÖ´Ù -, ¸¸¾à 100 °³ÀÇ Thread ¸¦ ¹Ì¸® »ý¼º½ÃÄ×°í, °¢°¢ÀÇ Thread ´Â ÇϳªÀÇ Å¬¶óÀÌ¾ðÆ® ¿¬°áÀ» ó¸®ÇÑ´Ù°í °¡Á¤ÇßÀ»¶§, main ¾²·¹µå´Â accept(2) ¸¦ ÅëÇØ¼­ Ŭ¶óÀÌ¾ðÆ®¸¦ ¹Þ¾Æµé¿´À»¶§, accept() ·Î ¸¸µé¾îÁø ¼ÒÄÏ ÁöÁ¤¹øÈ£¸¦ ¹Ì¸® ¸¸µé¾îÁø 100 °³ÀÇ ¾²·¹µåÁß "³î°í" ÀÖ´Â ¾²·¹µå¿¡°Ô ³Ñ°ÜÁÖ¾î¾ß ÇÒ°ÍÀÌ´Ù. ±×·¯±â À§Çؼ­´Â main ¾²·¹µå¿¡¼­ °¢°¢ÀÇ ¾²·¹µå »óŸ¦ À¯ÁöÇØ¼­ Àû´çÇÑ ¾²·¹µå¿¡°Ô ÆÄÀÏÁöÁ¤ÀÚ¸¦ ³Ñ°ÜÁà¾ß ÇÒ°ÍÀÌ´Ù.

±×³ª¸¶ À§ÀÇ °æ¿ì´Â ÇϳªÀÇ ¾²·¹µå°¡ ÇϳªÀÇ ¿¬°áÀ» ó¸®ÇÔÀ¸·Î ¾î·ÆÁö ¾Ê°Ô ±¸ÇöÇϰÚÁö¸¸, ¸¸¾à 100°³ÀÇ ¾²·¹µå°¡ ÀÖ°í, °Å±â¿¡ °¢°¢ÀÇ ¾²·¹µå°¡ 10°³ ¾¿ÀÇ Å¬¶óÀÌ¾ðÆ® ¿¬°áÀ» ó¸®Çϵµ·Ï ±¸¼ºÇÑ´Ù¸é, °Å±â¿¡´Ù°¡ Àû´çÇÑ ·Îµå¹ë·±½Ì ±â´É ±îÁö Æ÷ÇÔ½Ã۰íÀÚ ÇÑ´Ù¸é, ±¸ÇöÀÌ ²Ï º¹ÀâÇØ Áú¼öµµ ÀÖ´Ù.

그림 1. Thread Pool ±¸¼ºµµ

À§´Â Thread Pool ÀÇ ´ë·«ÀûÀÎ ±¸Çö»óŸ¦ ±×¸²? À¸·Î ³ªÅ¸³½ °ÍÀÌ´Ù. Thread Pool ¿¡ µé¾îÀÖ´Â °¢°¢ÀÇ ¾²·¹µå¸¦ °ü¸®Çϱâ À§Çؼ­´Â ÇʼöÀûÀ¸·Î °¢°¢ÀÇ ¾²·¹µåÀÇ »óŸ¦ °¡Áö°í ÀÖ´Â Schedul ÀڷᱸÁ¶ ¸¦ °¡Áö°í ÀÖ¾î¾ßÇÑ´Ù. ±×·¡¾ß¸¸ MAIN THREAD ¿¡¼­ ¾²·¹µå »óŸ¦ È®ÀÎÇØ¼­ Àû´çÇÑ ¾²·¹µå·Î ÀÛ¾÷ºÐ¹è°¡ °¡´ÉÇÒ°ÍÀ̱⠶§¹®ÀÌ´Ù. - ½ÇÁ¦ Linux Ä¿³Îµµ °¢°¢ÀÇ task ÀÇ ½ºÄÉÁ층À» À§Çؼ­ task ±¸Á¶Ã¼¸¦ À¯ÁöÇÑ´Ù. -


1.1.2절. ±¸Çö ÇÁ·Î¼¼½º

ÀÌÁ¦ ±¸Çö¹æ½Ä¿¡ ´ëÇÑ ¹Ø±×¸²ÀÌ ³ª¿ÔÀ¸´Ï, ½ÇÁ¦·Î ±¸ÇöÀ» À§ÇÑ ÇÁ·Î¼¼½º¸¦ ¸¸µé¾î º¸µµ·Ï ÇÏÀÚ. ÇÁ·Î¼¼½º´Â ½´µµÄÚµå·Î ±¸¼ºÀ» Çϵµ·Ï ÇϰڴÙ. ³×Æ®¿÷ ¼­¹ö ÀÛ¼ºÀ» ±âÁØÀ¸·Î ÇϰڴÙ.
½ºÄÉÁì°ü·Ã ÀڷᱸÁ¶
{
   ÇöÀç ¿¬°áµÈ Ŭ¶óÀÌ¾ðÆ®¼ö
   ÇöÀç ó¸®ÇØ¾ßµÉ Å¬¶óÀÌ¾ðÆ® ¼ÒÄÏÁö½ÃÀÚ

   ¾²·¹µåÇ®¿¡ ¸¸µé¾îÁø ¾²·¹µå »óÅ : ¾²·¹µåÇ® Å©±â¸¸Å­ÀÇ ¹è¿­ 
   {
       0 À̸é È޽ĻóÅ 
       1 À̸é ÀÛ¾÷»óÅ 
       ó¸®ÁßÀÎ ¼ÒÄÏÁö½ÃÀÚ
   }
};

main ÇÔ¼ö½ÃÀÛ
{
    ¾Æ±Ô¸ÕÆ®·Î ¸î°³ÀÇ ¾²·¹µå¸¦ »ý¼ºÇÒÁö¸¦ ¹ÞÀ½
    while(¾²·¹µå »ý¼º¼ö¸¸Å­)
    {
        pthread_create ¸¦ ÀÌ¿ëÇØ¼­ ¾²·¹µå »ý¼º
        // Åë½Å¾²·¹µå ÇÔ¼ö
        {
            WAIT:
            main ¾²·¹µå°¡ ±ú¿ì±æ ±â´Ù¸°´Ù. 
            ¸¸¾à main ¾²·¹µå·Î ºÎÅÍ ±ú¿òÀÌ ÀÖ´Ù¸é   
            {
                ½ºÄÉÁì ÀڷᱸÁ¶->ÇöÀç ó¸®ÇØ¾ßµÉ ¼ÒÄÏÁö½ÃÀÚ ¸¦ Àоî¿Â´Ù. 
                ½ºÄÉÁì ÀڷᱸÁ¶->ÀÚ½ÅÀÇ »óŸ¦ 1·Î ¼¼ÆÃÇÑ´Ù.  
                ½ºÄÉÁì ÀڷᱸÁ¶->ó¸®ÁßÀÎ ¼ÒÄÏÁö½ÃÀÚ¸¦ ¼¼ÆÃÇÑ´Ù. 
                while(1)
                {
                    Ŭ¶óÀÌ¾ðÆ®¿Í Åë½ÅÇÑ´Ù. 
                    ¸¸¾à ¿¡·¯°¡ ¹ß»ýÇϸé 
                    {
                        ½ºÄÉÁì ÀڷᱸÁ¶->ó¸®ÁßÀÎ ¼ÒÄÏÁö½ÃÀÚ¸¦ 0À¸·Î ¼¼ÆÃ  
                        ½ºÄÉÁì ÀڷᱸÁ¶->ÀÚ½ÅÀÇ »óŸ¦ 0À¸·Î ¼¼ÆÃ
                        ½ºÄÉÁì ÀڷᱸÁ¶->ÇöÀç ¿¬°áµÈ Ŭ¶óÀÌ¾ðÆ®¼ö --; 
                        goto WAIT:
                    }
                }
            }
        } 
    }

    // main ¾²·¹µå
    while(1)
    {
        ¸¸¾à accept ¸¦ ÅëÇØ¼­ ¿¬°áÀÌ ¹ß»ýÇÑ´Ù¸é
        {
            ½ºÄÉÁì°ü·Ã ÀڷᱸÁ¶->ÇöÀ翬°áµÈ Ŭ¶óÀÌ¾ðÆ®¼ö°¡ MAX ¸¦ ÃʰúÇÏÁö ¾Ê¾Ò´Ù¸é
            {
                ½ºÄÉÁì°ü·Ã ÀڷᱸÁ¶->ÇöÀ翬°áµÈ Ŭ¶óÀÌ¾ðÆ®¼ö ++; 
                ½ºÄÉÁì°ü·Ã ÀڷᱸÁ¶->ÇöÀçó¸®ÇØ¾ßµÉ Å¬¶óÀÌ¾ðÆ® ¼ÒÄÏÁö½ÃÀÚ = accept();
                ½ºÄÉÁÙ°ü·Ã ÀڷᱸÁ¶->¾²·¹µåÇ®¿¡ ¸¸µé¾îÁø ¾²·¹µå»óÅ °¡ 0ÀÎ 
                  ¾²·¹µå¸¦ ã¾Æ¼­ ÇØ´ç ¾²·¹µå¸¦ ±ú¿î´Ù.  
            }
            ±×·¸Áö ¾Ê°í ÃʰúÇßÀ»°æ¿ì
            {
                Ŭ¶û¸®¾ðÆ®¿¡°Ô ¿¡·¯¸Þ½ÃÁö¸¦ Àü¼ÛÇÑ´Ù. 
            }
        }
    }
}
				
±¸ÇöÀº ±¸ÇöÇÏ´Â ÇÁ·Î±×·¡¸Ó°¡ »óȲ¿¡ µû¶ó¼­ ¼±ÅÃÇϱ⠳ª¸§À̱ä ÇÏÁö¸¸ º¸ÅëÀº À§ÀÇ ¹æ¹ýÀ» ±âº»À¸·Î ÇØ¼­, ¾à°£ÀÇ º¯°æÀ» °¡ÇÏ´Â Á¤µµ°¡ µÉ°ÍÀÌ´Ù. À§ÀÇ ½´µµÄڵ带 º¸¸é main ¾²·¹µå¿¡¼­ accept ¸¦ ¹ÞÀ¸¸é È޽ĻóÅ¿¡ ÀÖ´Â ¾²·¹µå¸¦ ±ú¿î´Ù°í µÇ¾îÀִµ¥, À̶§ ±ú¿ì±â À§Çؼ­´Â ¾²·¹µå Á¶°Çº¯¼ö¸¦ »ç¿ëÇÏ¸é µÉ°ÍÀÌ´Ù.

±×·¸´Ù¸é ½ºÄÉÁì°ü·Ã ÀڷᱸÁ¶´Â ¾î¶»°Ô ±¸ÇöÇÏ´Â°Ô ½¬¿î¹æ¹ýÀÎÁö »ý°¢Çغ¸µµ·Ï ÇÏÀÚ. ±¸ÇöÇÏ´Â ¹æ¹ýÀº ÇÁ·Î±×·¡¸Ó ¸¾À̰ÚÁö¸¸, ÇÊÀÚ°¡ ±¸ÇöÇϰíÀÚ ÇÑ´Ù¸é multimap À» ÀÌ¿ëÇØ¼­ ±¸ÇöÇÒ°ÍÀÌ´Ù. ÀÌ ÀڷᱸÁ¶´Â ¾Æ¸¶ ´ÙÀ½°ú °°À»°ÍÀÌ´Ù.
// ¾²·¹µå Á¤º¸ ±¸Á¶Ã¼
struct ph
{
   int sockfd;    // ó¸®ÁßÀÎ ¼ÒÄÏÁöÁ¤¹øÈ£
   int index_num; // ¾²·¹µåÀÇ À妽º ¹øÈ£
};

// ¾²·¹µå ±¸Á¶Ã¼ MAP
multimap<int, struct ph> phinfo;

struct schedul_info
{
    int client_num;      // ÃÑ ¿¬°áÁßÀΠŬ¶óÀÌ¾ðÆ®¼ö 
    int current_sockfd;  // °¡ÀåÃÖ±Ù¿¡ ¿¬°áµÈ ¼ÒÄÏÁöÁ¤¹øÈ£
    phinfo mphinfo;      // ¾²·¹µå ±¸Á¶Ã¼ map
} 
				
¸ÖƼ¸ÊÀÇ key ´Â ¾²·¹µåÀÇ È°¼ºÈ­ ¿©ºÎ·Î 1 ȤÀº 0ÀÌ µÈ´Ù. ±×¸®°í value ´Â ÇØ´ç ¾²·¹µå Á¤º¸°¡ µÉ°ÍÀÌ´Ù. ÀÌ·¸°Ô ¸ÖƼ¸ÊÀ¸·Î ¸¸µçÀÌÀ¯´Â °£´ÜÇÏ´Ù. ¸ÖƼ¸ÊÀº Á¤·Ä¿¬°ü ÄÁÅ×ÀÌ³Ê ÀÓÀ¸·Î key ¸¦ ±âÁØÀ¸·Î ÀÚµ¿ÀûÀ¸·Î Á¤·ÄÀÌ µÉ°ÍÀÌ´Ù. ¸¸¾à ù¹øÂ° ¾²·¹µå°¡ ó¸®Áß(1)·Î º¯°æµÇ¾ú´Ù¸é ÀÌ ¿ø¼Ò´Â multimap ÀÇ °¡Àå µÚ·Î Á¤·ÄÀÌ µÉ°ÍÀÌ´Ù. ±×·³À¸·Î ¿ì¸®´Â Ŭ¶óÀ̾ðÆ®ÀÇ ¼ö°¡ ÃÑ¿¬°á°¡´ÉÇÑ Å¬¶óÀÌ¾ðÆ®¼ö(Thread Pool ¿¡ »ý¼ºµÈ ¾²·¹µå¼ö) ¸¦ ÃʰúÇÏÁö ¾Ê´ÂÇÑ phinfo.begin() À¸·Î °¡Á®¿Â ¾²·¹µå´Â È޽ĻóÅÂ(0) À̶ó´Â°É ¹ÏÀ»¼ö ÀÖ°Ô µÈ´Ù. ´Ù½Ã ¸»Çؼ­ º¹ÀâÇØ¼­ ¾²·¹µå»óŰ¡ 0ÀÎÁö 1ÀÎÁö óÀ½ºÎÅÍ °Ë»çÇÒ Çʿ䰡 ¾ø´Ù´Â ¶æÀÌ´Ù.
  1 2 3 4 5 6 7    99 100  : ¾²·¹µå ¹øÈ£
 +-+-+-+-+-+-+-+---+-+-+
 |0|0|0|0|0|0|0|...|0|0|
 +-+-+-+-+-+-+-+---+-+-+

 --> ¿¬°áÀÌ µé¾î¿Ô´Ù¸é 
  1 2 3 4 5 6 7    99 100  : ¾²·¹µå ¹øÈ£
 +-+-+-+-+-+-+-+---+-+-+
 |1|0|0|0|0|0|0|...|0|0|
 +-+-+-+-+-+-+-+---+-+-+
  |                   |  
  +----------->-------+
  °¡Àå µÚ·Î ÀÚµ¿À¸·Î sort µÊ

 --> Sort ÈÄ
  2 3 4 5 6 7 8   100 1 : ¾²·¹µå ¹øÈ£
 +-+-+-+-+-+-+-+---+-+-+
 |0|0|0|0|0|0|0|...|0|1|
 +-+-+-+-+-+-+-+---+-+-+

 --> Ŭ¶óÀÌ¾ðÆ®°¡ 99°³°¡ Á¢¼ÓÇØ ÀÖÀ»°æ¿ì
 +-+-+-+-+-+-+-+---+-+-+
 |0|1|1|1|1|1|1|...|1|1|
 +-+-+-+-+-+-+-+---+-+-+

 ±×·³À¸·Î begin() À» »ç¿ëÇÏ°Ô µÉ°æ¿ì 
 ¾ðÁ¦³ª È޽ĻóÅ¿¡ ÀÖ´Â ¾²·¹µå¸¦ °¡Á®¿Ã¼ö ÀÖÀ½ 
				
»ç½Ç multimap À» ¾´´Ù¸é ±»ÀÌ "ÇöÀç ¿¬°áµÈ Ŭ¶óÀÌ¾ðÆ® ¼ö" ¸¦ À¯ÁöÇϱâ À§Çؼ­ º°µµÀÇ º¯¼ö¸¦ µÑ Çʿ䰡 ¾øÀ»°ÍÀÌ´Ù. multimap ¿¡¼­ Á¦°øÇÏ´Â count() ¸¦ ÀÌ¿ëÇØ¼­ key °¡ "1" ÀÎ ¿ä¼ÒÀÇ ¼ö¸¦ ±¸ÇÏ¸é µÇ±â ¶§¹®ÀÌ´Ù. ¸¸¾à multimp ÀÇ begin() °ªÀÌ 1 À̶ó¸é MAX Ŭ¶óÀÌ¾ðÆ®°¡ °¡µæÃ¡´Ù´Â°É ÀǹÌÇÒ°ÍÀÌ´Ù.

¹°·Ð multimap ÀÇ °æ¿ì ±âº»ÀûÀ¸·Î key °ªÀÇ ¼öÁ¤Àº Çã¿ëÇÏÁö ¾Ê±â ¶§¹®¿¡ 0 À» 1·Î º¯°æÇÒ°æ¿ì ½ÇÁ¦·Î´Â 0 À» °¡Áö´Â ¿ä¼Ò¸¦ »èÁ¦Çϰí, 1À» °¡Áö´Â »õ·Î¿î ¿ä¼Ò¸¦ »ðÀÔÇÏ´Â ¹æ½ÄÀ» ÃëÇØ¾ß ÇÒ°ÍÀÌ´Ù. ¸¶Âù°¡Áö·Î Ŭ¶óÀÌ¾ðÆ®°¡ Á¾·áÇØ¼­ 1À» 0À¸·Î º¯°æÇÒ¶§¿¡µµ »èÁ¦/Àμ­Æ®¸¦ ÇØ¾ßÇÒ°ÍÀÌ´Ù. Value(°ª) ´Â ±×´ë·Î º¹»çÇØ¼­ »èÁ¦/Àμ­Æ®¸¦ ÇØ¾ß ÇÑ´Ù.

ÀÌ ¹æ¹ýÀÌ ¹ø°Å·Ó´Ù¸é, ±×³É ¹è¿­À» ¾²°Å³ª ȤÀº ´Ù¸¥ ¾î¶² ÀڷᱸÁ¶¸¦ ¾²´õ¶óµµ ÀüÇô °ü°è¾ø±â´Â ÇÏ´Ù. ±×°Ç ÀÚ±âÀÇ ±âÈ£¿¡ ¸Â°Ô ¼±ÅÃÇØ¼­ »ç¿ëÇÏ¸é µÉ¹®Á¦ÀÌ´Ù.


1.2절. ¿¹Á¦

Áö±Ý±îÁö Thread POOL ÀÇ ±¸Çö¹æ¹ý¿¡ ´ëÇØ¼­ ¾Ë¾ÆºÃÀ¸´Ï, °£´ÜÇÏ°Ô ±¸ÇöÇØ º¸µµ·Ï ÇϰڴÙ. ÀÌ ÄÚµå´Â Áö±ØÈ÷ ±â´É±¸Çö¿¡¸¸ ½Å°æ¾´ ÄÚµåÀÌ´Ù. ¿¡·¯Ã³¸®¿Í ¸î±ºµ¥ ¹ÂÅØ½ºÀá±Ý󸮴 °¢ÀÚÀÇ Àç·®¿¡ ¸Ã±â°Ú´Ù.

¿¹Á¦ : pool_echo.cc
#include <map>
#include <iostream>
#include <pthread.h>
#include <unistd.h>
#include <stdlib.h>
#include <time.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <signal.h>
#include <arpa/inet.h>
#include <sys/un.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// ÃÖ´ë ¾²·¹µå POOL Å©±â
#define MAX_THREAD_POOL 256
using namespace std;

// Àü¿ª ¾²·¹µå ±¸Á¶Ã¼ 
typedef struct _ph
{
    int sockfd;    // ÇöÀç »ç¿ëÁßÀÎ ¼ÒÄÏ fd
    int index_num; // À妽º ¹øÈ£
} ph;

// Àü¿ª¾²·¹µå ±¸Á¶Ã¼·Î½á 
// ÇöÀç ¾²·¹µå »óȲÀ» ÆÄ¾ÇÇÔ
struct schedul_info
{
    int client_num;       // ÇöÀç ¿¬°áµÈ Ŭ¶óÀÌ¾ðÆ®¼ö
    int current_sockfd;   // °¡ÀåÃÖ±Ù¿¡ ¸¸µé¾îÁø ¼ÒÄÏÁö½ÃÀÚ
    multimap<int, ph> phinfo; 
};

// °¢ ¾²·¹µåº° Á¶°Çº¯¼ö
pthread_cond_t *mycond;
// ¾²·¹µå µ¿±âÈ­¸¦ À§ÇÑ Á¶°Çº¯¼ö
pthread_cond_t async_cond = PTHREAD_COND_INITIALIZER;

// °¢ ¾²·¹µåº° Á¶°Çº¯¼öÀÇ Å©¸®Æ¼Äü¼¼Ç ÁöÁ¤À» À§ÇÑ 
// ¹ÂÅØ½º 
pthread_mutex_t mutex_lock= PTHREAD_MUTEX_INITIALIZER; 
// ¾²·¹µå µ¿±âÈ­¿ë Á¶°Çº¯¼öÀÇ Å©¸®Æ¼Äü¼¼Ç ÁöÁ¤À» À§ÇÑ 
// ¹ÂÅØ½º
pthread_mutex_t async_mutex = PTHREAD_MUTEX_INITIALIZER;

// Ŭ¶óÀÌ¾ðÆ®¿ÍÀÇ Åë½Å¿ë ¾²·¹µå
void *thread_func(void *data);
// ÇöÀç Ŭ¶óÀÌ¾ðÆ® »óÅ ¸ð´ÏÅÍ¿ë ¾²·¹µå
// ÇѸ¶µð·Î µð¹ö±ë¿ë 
void *mon_thread(void *data);

schedul_info s_info;

// ¸ÞÀÎ ÇÔ¼ö
int main(int argc, char **argv)
{
    int i;
    ph myph;
    int status;
    int pool_size = atoi(argv[2]);
    pthread_t p_thread;
    struct sockaddr_in clientaddr, serveraddr;
    int server_sockfd;
    int client_sockfd;
    int client_len;    

    // Ç®»çÀÌÁî °Ë»ç
    if ((pool_size < 0) || (pool_size > MAX_THREAD_POOL))
    {    
        cout << "Pool size Error" << endl;
        exit(0);    
    }

    // Make Socket
    if ((server_sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
    {
        perror("error : ");
        exit(0);
    }

    // Bind
    bzero(&serveraddr, sizeof(serveraddr));
    serveraddr.sin_family = AF_INET;
    serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);
    serveraddr.sin_port = htons(atoi(argv[1]));

    if (bind (server_sockfd, (struct sockaddr *)&serveraddr, 
                        sizeof(serveraddr)) == -1) 
    {
        perror("bind error : ");
        exit(0);
    }

    // Listen
    if (listen(server_sockfd, 5) == -1)
    {
        perror("listen error : ");
        exit(0);
    }

    // ¾²·¹µå °¹¼ö¸¸Å­ Á¶°Çº¯¼ö »ý¼º 
    mycond     = (pthread_cond_t *)malloc(sizeof(pthread_cond_t)*pool_size);

    // ¾²·¹µå Àü¿ªº¯¼ö ÃʱâÈ­
    s_info.client_num = 0;
    s_info.current_sockfd = 0; 

    // ¾²·¹µå POOL »õ¼º
    for (i = 0; i < pool_size; i++)
    {
        memset((void *)&myph, 0x00, sizeof(myph));
        myph.index_num = i;
        s_info.phinfo.insert(pair<int, ph>(0, myph));

        // Á¶°Çº¯¼ö¸¦ ÀÌ¿ëÇØ¼­ ¾²·¹µå°£ µ¿±âÈ­¸¦ ½Ç½ÃÇÑ´Ù.
        pthread_mutex_lock(&async_mutex);
        if (pthread_create(&p_thread, NULL, thread_func, (void *)&i) < 0)
        {
            perror("thread Create error : ");
            exit(0);    
        }    
        pthread_cond_wait(&async_cond, &async_mutex); 
        pthread_mutex_unlock(&async_mutex);
    }

    // µð¹ö±ë¿ë ¾²·¹µå »ý¼º
    pthread_create(&p_thread, NULL, mon_thread, (void *)NULL);

    // MAIN THREAD accept wait
    client_len = sizeof(clientaddr);

    // Ŭ¶óÀÌ¾ðÆ® ACCEPT 󸮸¦ À§ÇÑ 
    // MAIN ¾²·¹µå 
    while(1)
    {
        multimap<int, ph>::iterator mi;
        client_sockfd = accept(server_sockfd, (struct sockaddr *)&clientaddr, 
                                        (socklen_t *)&client_len);
        if (client_sockfd > 0)
        {
            // ¸¸¾à ¾²·¹µåÇ®ÀÌ °¡µæÃ¡´Ù¸é Ŭ¶óÀÌ¾ðÆ® ¿¬°áÀ»
            // Á¾·á½ÃŲ´Ù.
            mi = s_info.phinfo.begin();
            if (mi->first == 1)
            {
                //error message send to client_sockfd
                cout << "SOCKET IS FULL" << endl;    
                close(client_sockfd);
            }
            // ±×·¸Áö ¾Ê´Ù¸é ¿¬°áÀ» ¹Þ¾ÆµéÀ̰í 
            // Ŭ¶óÀÌ¾ðÆ® Àü¿ª º¯¼ö¸¦ ¼¼ÆÃÇÑ´Ù. 
            // ¼¼ÆÃÈÄ ÇØ´ç 󸮾²·¹µå¿¡°Ô ½Ã±×³ÎÀ» º¸³»¾î¼­ 
            // ó¸®ÇÏ°Ô ÇÑ´Ù. 
            else
            {
                ph tmpph;
                int psockfd;
                int pindex_num;
                s_info.current_sockfd = client_sockfd;

                tmpph.sockfd = client_sockfd;
                tmpph.index_num = mi->second.index_num;
                s_info.phinfo.erase(mi);    
                s_info.phinfo.insert(pair<int, ph>(1,tmpph));
                s_info.client_num ++;
                cout << "SEND SIGNAL " << mi->second.index_num << endl;     
                pthread_cond_signal(&mycond[mi->second.index_num]);    
            }
        }
        else
        {
            cout << "ACCEPT ERROR " << endl;    
        }
    }
    pthread_join(p_thread, (void **)status);
}

void *thread_func(void *data)
{
    char buf[255];
    int mysocket;
    int mynum = *((int *)data); 
    multimap<int, ph>::iterator mi;
    // ¾²·¹µå µ¿±âÈ­¿ë Á¶°Çº¯¼ö
    pthread_mutex_lock(&async_mutex);
    pthread_cond_signal(&async_cond);
    pthread_mutex_unlock(&async_mutex);

    cout << "Thread create " << mynum << endl;
    while(1)
    {
        // MAIN ¾²·¹µå·Î ºÎÅÍ ½ÅÈ£¸¦ ±â´Ù¸°´Ù. 
        // ½ÅÈ£°¡ µµÂøÇÏ¸é ¾²·¹µå Àü¿ªº¯¼ö·Î ºÎÅÍ 
        // ÇöÀç ó¸®ÇؾßÇÒ ¼ÒÄÏÁöÁ¤°ªÀ» °¡Á®¿Â´Ù. 
        pthread_mutex_lock(&mutex_lock);
        pthread_cond_wait(&mycond[mynum], &mutex_lock);
        mysocket = s_info.current_sockfd;
        pthread_mutex_unlock(&mutex_lock);
        memset(buf, 0x00, 255);    

        // µ¥ÀÌŸ¸¦ ó¸®ÇÑ´Ù. 
        // ¸¸¾à quit ¹®ÀÚ¿­À» ¸¸³ª¸é 
        // ¾²·¹µå Àü¿ªº¯¼ö¸¦ ¼¼ÆÃÇÑ´ÙÀ½ ¿¬°áÁ¾·á ÇÑ´Ù. 
        while(1)
        {
            read(mysocket, buf, 255);
            if (strstr(buf, "quit") == NULL)
            {
                write(mysocket, buf, 255);
            }
            else
            {
                mi = s_info.phinfo.begin();
                while(mi != s_info.phinfo.end())
                {
                    cout << "search " << mi->second.index_num << endl;
                    if (mi->second.index_num == mynum)
                    {
                        ph tmpph;
                        tmpph.index_num = mynum;
                        tmpph.sockfd = 0;
                        s_info.phinfo.erase(mi);
                        s_info.phinfo.insert(pair<int, ph>(0, tmpph));
                        s_info.client_num --;
                        close(mysocket);
                        break;
                    }
                    mi ++;
                }
                break;
            }
            memset(buf, 0x00, 255);    
        }
    }
}

void *mon_thread(void *data)
{
    cout << "moniter thread" << endl;
    while(1)
    {
        sleep(10);
        multimap<int, ph>::iterator mi;
        mi = s_info.phinfo.begin();
        cout << "size " << s_info.phinfo.size() << endl;
        while(mi != s_info.phinfo.end())
        {
            cout << mi->first << " : " << mi->second.index_num 
                 << " : " << mi->second.sockfd << endl; 
            mi ++;
        }
    }
}
			
ÀÌ ÇÁ·Î±×·¥Àº 2°³ÀÇ ÀÎÀÚ¸¦ ¹Þ¾ÆµéÀ̸ç, Ŭ¶óÀ̾ðÆ®ÀÇ ÀÔ·ÂÀ» µÇµ¹·ÁÁÖ´Â ÀÏÀ»ÇÑ´Ù (echo ¼­¹ö). ù¹øÂ° ÀÎÀÚ´Â ¼­ºñ½ºÇÒ PORT ¹øÈ£À̰í, µÎ¹øÂ° ÀÎÀÚ´Â ¾²·¹µå »ý¼º°¹¼öÀÌ´Ù. ÇÁ·Î±×·¥Àº ÀÎÀÚÀÇ Á¤º¸¸¦ ÀÌ¿ëÇØ¼­ PORT ¸¦ ¿­°í Ŭ¶óÀÌ¾ðÆ®¸¦ ¹Þ¾ÆµéÀδÙ. Ŭ¶óÀÌ¾ðÆ®°¡ ¿¬°áÇϸé, Thread Pool ¿¡ ³²´Â °ø°£ÀÌ ÀÖ´ÂÁö¸¦ È®ÀÎÇϰí, ³²´Â °ø°£ÀÌ ÀÖ´Ù¸é Ŭ¶óÀÌ¾ðÆ®¿Í Åë½ÅÇÏ°Ô µÈ´Ù.

´ÜÁö ¾²·¹µå¸¦ ¹Ì¸® »ý¼º½ÃŰ°í ³ª¼­, À̰ÍÀ» ½ºÄÉÁ층Çϱâ À§ÇÑ Äڵ尡 ¸îÁÙ Ãß°¡µÇ¾úÀ» »Ó Ưº°È÷ º¹ÀâÇÑ ÄÚµå´Â ¾Æ´Ò°Å¶ó°í »ý°¢µÈ´Ù.


2절. °á·Ð

ÀÌ»ó °£´ÜÇÑ ¾²·¹µå Ç®ÀÇ ÀÛ¼º¿ä·É¿¡ ´ëÇØ¼­ ¾Ë¾Æº¸¾Ò´Ù. À§¿¡¼­ ¼³¸íÇßµíÀÌ ¾²·¹µå Ç®À̶õ °³³äÀûÀÎ ¿ä¼Ò¿¡ °¡±î¿òÀ¸·Î ¾î¶»°Ô ±¸ÇöÇÒÁö´Â »óȲ¿¡ µû¶ó¼­ ¸Å¿ì ´Þ¶óÁö°Ô µÇ¸ç, À§ÀÇ ¿¹Á¦´Â ±×·¯ÇÑ ¿©·¯°¡Áö »óȲÁß °¡Àå ±âº»ÀûÀÎ »óȲÀ» ¿¹·Î ÇØ¼­ ¸¸µé¾îÁø °ÍÀÌ´Ù. ¾î¶µç À§ÀÇ ¿¹Á¦¸¦ ÃæºÐÈ÷ ÀÌÇØÇÑ´Ù¸é ´Ù¸¥ »óȲÀ¸·ÎÀÇ ÀÀ¿ë¿ª½Ã º° ¾î·Á¿ò¾øÀ» °ÍÀ̶ó°í »ý°¢µÈ´Ù.

¾²·¹µå Ç®Àº º¸Åë ¸Å¿ì È¿À²ÀûÀÎ ¼º´ÉÀ» º¸ÀåÇØÁÖ´Â ¾îÇø®ÄÉÀ̼ÇÀÇ ÀÛ¼ºÀ» À§Çؼ­ »ç¿ëµÇ¾îÁüÀ¸·Î, °¡´ÉÇÑÇÑ ºü¸¥ ¾²·¹µå°£ ÀüȯÀÌ °¡´ÉÇϵµ·Ï °í¹ÎÇØ¼­ ÄÚµùÀ» ÇØ¾ß ÇÑ´Ù. À§ÀÇ °æ¿ì ¾²·¹µå°£ ÀüȯÀ» À§Çؼ­ multimap À» »ç¿ëÇϰí Àִµ¥, accept °¡ µé¾î¿ÔÀ»°æ¿ì ÇØ´ç Ŭ¶óÀÌ¾ðÆ®¿¡ ´ëÇÑ ¾²·¹µå ÇÒ´çÀº ¸Å¿ì ºü¸£´Ù°í º¼¼ö ÀÖÀ»°ÍÀÌ´Ù. ±×·¯³ª Á¾·áÇÒ°æ¿ì¿¡´Â multimap ÀÇ Ã¹¹øÂ° ¿ø¼ÒºÎÅÍ ¸¶Áö¸·¹ø ¿ø¼Ò±îÁö search ÇØ¾ß ÇÑ´Ù. À̰ÍÀº ¸Å¿ì ºñÈ¿À²ÀûÀÓÀ¸·Î °³¼±ÇÒ ¿©Áö°¡ ÀÖ´Ù. °¡Àå °£´ÜÇÏ°Ô »ý°¢ÇÒ¼ö ÀÖ´Â °ÍÀº multimap ÀÇ key °ªÀÌ 1ÀÎ ¿ø¼Ò³»¿¡¼­¸¸ °Ë»öÇÏ´Â °ÍÀÌ´Ù. ¿ì¸®´Â ¾²·¹µå Ç®ÀÇ Å©±â¿Í ÇöÀç ¿¬°áµÈ Ŭ¶óÀ̾ðÆ®ÀÇ ¼ö¸¦ ¾Ë°í ÀÖÀ½À¸·Î, multimap ÀÇ ¸î¹øÂ° ¿ä¼ÒºÎÅÍ key °ªÀÌ 1ÀÎÁö¸¦ °è»êÇØ ³¾¼ö Àֱ⠶§¹®ÀÌ´Ù. ÀÌ·¸°Ô ÇÒ°æ¿ì ¾à°£ÀÇ ½Ã°£´ÜÃàÈ¿°ú¸¦ ±â´ëÇÒ¼ö ÀÖÀ»°ÍÀÌ´Ù.
   1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  |0|0|0|0|0|0|0|0|1|1|1|1|1|1|1|
  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                  |             |
                  +-------------+ 
                      15 - 8 
		
ÀÌ ½Ã°£´ÜÃàÈ¿°ú´Â ¿¬°áµÈ Ŭ¶óÀ̾ðÆ®ÀÇ ¼ö°¡ Àüü POOL »çÀÌÁî¿¡ ºñ·ÊÇØ¼­ ÀÛÀ» ¼ö·Ï Ä¿Áú°ÍÀÌ´Ù.

³ª¸ÓÁö ¹æ¹ýÀº °¢ÀÚ °í¹ÎÀ» ÇØº¸±â ¹Ù¶õ´Ù. ¾Æ¸¶ ÀüÇô ´Ù¸¥ ÀڷᱸÁ¶¸¦ »ç¿ëÇÒ¼öµµ ÀÖÀ»°ÍÀÌ´Ù.