PHP¸¦ ÀÌ¿ëÇÑ ´ÙÁß ¿¬°á ¼ÒÄÏ Åë½Å (2)

ÀÌÁø¿ì

ÇÁ¸®·£¼­
ÇÁ·Î±×·¡¸Ó

            
          


Â÷·Ê
1. ¼Ò°³
2. pcntl_fork() ÇÔ¼ö
3. PHP ÄÄÆÄÀÏ Çϱâ
4. ÇÁ·Î±×·¥ ÀÛ¼º
4.1. ¼­¹ö ¸¸µé±â
4.2. Ŭ¶óÀÌ¾ðÆ® ¸¸µé±â
4.3. ½ÇÇàÇϱâ
5. °á·Ð

À̹®¼­ÀÇ ¹èÆ÷´Â ÀÚÀ¯·Î¿ì³ª ÃÖ¼ÒÇÑ Á¦ÀÛÀÚÀÇ Á¤º¸´Â Á¦¿ÜÇÏÁö ¾Ê°í ¹èÆ÷ÇØ ÁÖ¼¼¿ä.

¹®¼­°¡ Á¸ÀçÇÏ´Â ¸ðµç°÷¿¡ ´äº¯À» µå¸±¼ö ¾øÀ¸¹Ç·Î Áú¹®Àº ȨÆäÀÌÁö(http://www.jinoos.com)¿¡¼­¸¸ ¹Þ½À´Ï´Ù.


1. ¼Ò°³

À̹ø°­Á¿¡´Â fork¸¦ ÀÌ¿ëÇØ¼­ »õ·Î¿î ÇÁ·Î¼¼½º¸¦ »ý¼ºÇÏ¿© »ý¼ºµÈ ÀÚ½Ä ¼­¹öÇÁ·Î¼¼½º°¡ Ŭ¶óÀÌ¾ðÆ®¸¦ ´ã´çÇÏ´Â ÇüŸ¦ ±¸¿¬ÇØ º¸°Ú½À´Ï´Ù.

PHP¿¡¼­ forkÇÔ¼ö·Î´Â Process Control ÇÔ¼öÀÇ pcntl_fork() ÇÔ¼ö°¡ ÀÖ½À´Ï´Ù. Process Control ÇÔ¼ö´Â ±âº»ÇÔ¼ö°¡ ¾Æ´Ï±â ¶§¹®¿¡ ÄÄÆÄÀϽà ¿É¼ÊÀ¸·Î Ãß°¡½ÃÄÑ¾ß ÇÕ´Ï´Ù.


2. pcntl_fork() ÇÔ¼ö

int pcntl_fork ( )

ÇÔ¼ö È£ÃâÈÄ ¸®Åϰª¿¡ 0À̸é ÀÚ½Ä ÇÁ·Î¼¼½ºÀ̸ç >0 ÀÌ¸é ºÎ¸ð ÇÁ·Î¼¼½º·Î ÀÚ½Ä ÇÁ·Î¼¼½ºÀÇ PID¹øÈ£¸¦ ¸®ÅÏ ¹Þ½À´Ï´Ù. error¹ß»ý½Ã¿¡´Â -1 °ªÀ» °¡Áý´Ï´Ù.

Æ÷Å© ÇÔ¼ö´Â Æ÷Å© ÇÔ¼ö¸¦ ½ÇÇàÇÑ ÇÁ·Î¼¼½º¿Í µ¿ÀÏÇÑ ÀÚ½Ä ÇÁ·Î¼¼½º¸¦ »ý¼ºÇÕ´Ï´Ù. µ¿ÀÏÇÑ ÀÚ½Ä ÇÁ·Î¼¼½º¶ó´Â Àǹ̴ ÇÁ·Î¼¼½º °èº¸»óÀÇ ±íÀ̸¸ ´Ù¸¦»Ó µ¿ÀÛÀº ¶È°°Àº ½ÖµÕÀ̸¦ ¸¸µå´Â °Í ÀÔ´Ï´Ù.

ÀÚ½Ä ÇÁ·Î¼¼½º´Â ºÎ¸ð ÇÁ·Î¼¼½ºÀÇ ¸Þ¸ð¸®¸¦ º¹»çÇØ¼­ Ŭ·ÐÀ» ¸¸µé°í ¸®¼Ò½º(ÆÄÀÏ Áö½ÃÀÚ, DB Ä¿³Ø¼Ç, ¼ÒÄÏ Ä¿³Ø¼Ç µî)Àº °øÀ¯ÇÕ´Ï´Ù.

°£´ÜÇÏ°Ô pcntl_fork() Äڵ带 »ìÆì º¸°Ú½À´Ï´Ù.
<?php
$i = 0;
$pid = pcntl_fork();

// error
if($pid == -1)
{
    echo "fork error";

// ºÎ¸ð ÇÁ·Î¼¼½º
}elseif($pid > 0)
{
    for(;$i<10;$i++)
    {
        echo "Parent Process \$i : $i\n";
    }

// ÀÚ½Ä ÇÁ·Î¼¼½º
}elseif($pid == 0)
{
    for(;$i<10;$i+=2)
    {
        echo "Child Process \$i : $i\n";
    }
}
?>
                    
ºÎ¸ð ÇÁ·Î¼¼½º´Â $i °ªÀÌ 1¾¿, ÀÚ½Ä ÇÁ·Î¼¼½º´Â $i °ªÀÌ 2¾¿ Áõ°¡ÇÏ´Â ÇÁ·Î±×·¥ ÀÔ´Ï´Ù. °á°ú´Â °¢ÀÚ ÇØº¸½Ã±â ¹Ù¶ø´Ï´Ù.


3. PHP ÄÄÆÄÀÏ Çϱâ

ù¹øÂ° °­ÁÂ(PHP¸¦ ÀÌ¿ëÇÑ ´ÙÁß ¿¬°á ¼ÒÄÏ Åë½Å (1)) ¿¡¼­ ¼ÒÄÏ ÇÔ¼ö¸¦ »ç¿ëÇϱâ À§ÇØ --with-sockets ¿É¼ÇÀ» ÁÖ¾î ÄÄÆÄÀÏ ÇÏ¿´½À´Ï´Ù.

¿À´ÃÀº ¼ÒÄÏ ÇÔ¼ö¿Í Process Control ÇÔ¼ö¸¦ Ãß°¡½ÃÄÑ ÄÄÆÄÀÏ ÇØº¸°Ú½À´Ï´Ù.

#] tar -zxvf php-4.3.1.tar.gz
#] cd php-4.3.1
#] ./configure --with-sockets --enable-pcntl
#] make

¿ª½Ã php ½ÇÇàÆÄÀÏÀÌ »ý¼ºµË´Ï´Ù.


4. ÇÁ·Î±×·¥ ÀÛ¼º

¿À´Ã ÀÛ¼ºÇÒ ¼­¹ö¿Í Ŭ¶óÀ̾ðÆ®ÀÇ ±¸Á¶´Â ¾Æ·¡¿Í °°½À´Ï´Ù.

                                ¦£¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¤            ¦£¦¡¦¡¦¡¦¤
                    ¦£¦¡(Fork)¦¡¦©Child Process ¦§¦¡(socket)¦¡¦©Client¦¢
                    ¦¢          ¦¦¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¥            ¦¦¦¡¦¡¦¡¦¥
¦£¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¤  ¦¢          ¦£¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¤            ¦£¦¡¦¡¦¡¦¤
¦¢Master Process¦§¦¡¦«¦¡(Fork)¦¡¦©Child Process ¦§¦¡(socket)¦¡¦©Client¦¢
¦¦¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¥  ¦¢          ¦¦¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¥            ¦¦¦¡¦¡¦¡¦¥
                    ¦¢          ¦£¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¤            ¦£¦¡¦¡¦¡¦¤
                    ¦¦¦¡(Fork)¦¡¦©Child Process ¦§¦¡(socket)¦¡¦©Client¦¢
                                ¦¦¦¡¦¡¦¡¦¡¦¡¦¡¦¡¦¥            ¦¦¦¡¦¡¦¡¦¥
Á»´õ ´Ü¼øÈ­ µÇ°í Á÷°üÀûÀ¸·Î Ç¥ÇöµÇ¾ú±º¿ä.

Child Process Çѳª°¡ Client Çϳª¸¦ µ¶¸³ÀûÀ¸·Î ¸¶Å©ÇÏ´Â ±¸Á¶ÀÔ´Ï´Ù.

¿¬°áÀÌ ²÷¾îÁø Child Process´Â ¹Ù·Î ¼Ò¸êµË´Ï´Ù. »õ·Î¿î Ŭ¶óÀÌ¾ðÆ®°¡ Âü¿©ÇÏ¸é ¹Ù·Î Master Process´Â pcntl_forkÇÔ¼ö¸¦ ÀÌ¿ëÇØ¼­ Child Process¸¦ »ý¼ºÇÏÁÒ.


4.1. ¼­¹ö ¸¸µé±â

¼­¹öÀÇ ±¸Á¶¸¦ °£´ÜÈ÷ »ìÆìº¸¸é
¼ÒÄÏ»ý¼º
¼ÒÄϹÙÀÎÆ®¹× ¸®½¼
while(»õ·Î¿î¿¬°á¼ö¶ô)
{
    Æ÷Å©
    if(ÀÚ½ÄÇÁ·Î¼¼½º)
    {
        while(¸Þ½ÃÁö¼ö½Å)
        {
            ¸Þ½ÃÁö ó¸®
            if(quit¸Þ½ÃÁö)
            {
                ¼ÒÄϴݱâ
                Á¾·á
            }
        }
    }
}
            
±¸Á¶ ÀÔ´Ï´Ù. ¸Þ½ÃÁö ó¸® ºÎºÐÀº Áö³­ °­ÁÂ(PHP¸¦ ÀÌ¿ëÇÑ ´ÙÁß ¿¬°á ¼ÒÄÏ Åë½Å (2))ÀÇ ¸Þ½ÃÁö ó¸® ºÎºÐ°ú µ¿ÀÏÇϸç selectó¸® ´ë½Å fork¸¦ ÀÌ¿ëÇÑ Ã³¸® ÀÔ´Ï´Ù.

#!/usr/local/bin/php -q
<?php
set_time_limit(0);

define("_IP",    "111.222.333.12");
define("_PORT",  "65000");

$sSock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);

socket_bind($sSock, _IP, _PORT);
socket_listen($sSock);

pcntl_signal(SIGCHLD, SIG_IGN); 

while($sock = socket_accept($sSock))
{
    socket_getpeername($sock, $sockIp, $sockPort);
    msg("client connect : ".$sockIp.":".$sockPort."\n");

    $pid = pcntl_fork();
    msg("fork\n");
    if($pid == -1)
    {
        msg("fork failed\n");
        exit;
    // ÀÚ½Ä ÇÁ·Î¼¼½º À϶§ 
    }if($pid == 0)
    {
        while(1)
        {
            $buf = socket_read($sock, 4096);

            // Á¢¼Ó Á¾·á
            if(!$buf)
            {
                msg("client connection broken : ".$sockIp.":".$sockPort."\n");
                exit;
            }
            // ¸Þ½ÃÁö ¼ö½Å À̺¥Æ®
            else
            {
                msg("recive data : ".$buf."\n");
                $cmd = substr($buf, 0, 4);
                switch($cmd)
                {
                    // ½Ã°£Àü¼Û
                    case "time":
                        msg("client(".$sockPort.") time data request\n");
                        socket_write($sock, date("Y/m/d H:i:s"));
                        break;

                    // Á¾·á
                    case "quit":
                        msg("client(".$sockPort.") quit request\n");
                        socket_write($sock, "quit");
                        socket_close($sock);
                        exit;
                        break;
                    default:
                        msg("client(".$sockPort.") invalid command $cmd\n");
                        break;
                }
            }
        }
    }
}

function msg($msg)
{
    echo "SERVER >> ".$msg;
}
?>            

¿ª½Ã server.php·Î ÀúÀåÇÏ°í ½ÇÇà±ÇÇÑÀ» ÁÝ´Ï´Ù.


4.2. Ŭ¶óÀÌ¾ðÆ® ¸¸µé±â

Ŭ¶óÀÌ¾ðÆ®´Â Áö³­ °­ÁÂÁö³­ °­ÁÂ(PHP¸¦ ÀÌ¿ëÇÑ ´ÙÁß ¿¬°á ¼ÒÄÏ Åë½Å (2))¿¡¼­ »ç¿ëÇÑ Å¬¶óÀÌ¾ðÆ® ÇÁ·Î±×·¥À» ¼öÁ¤¾øÀÌ ±×´ë·Î »ç¿ëÇÕ´Ï´Ù.


4.3. ½ÇÇàÇϱâ

server.php¸¦ ½ÇÇàÈÄ client.php¸¦ 3¹ø ½ÇÇàÇϰí ÇÁ·Î¼¼½º¿Í ÇÁ·Î¼¼½º Æ®¸®¸¦ È®ÀÎÇØº¸°Ú½À´Ï´Ù.

server.php ½ÇÇà È­¸é
#] ./server.php 
SERVER >> client connect : 111.222.333.12:38276         -- (1)
SERVER >> fork
SERVER >> fork
SERVER >> recive data : time
SERVER >> client(38276) time data request
SERVER >> client connect : 111.222.333.12:38396         -- (2)
SERVER >> fork
SERVER >> fork
SERVER >> recive data : time
SERVER >> client(38396) time data request
SERVER >> client connect : 111.222.333.12:38559         -- (3)
SERVER >> fork
SERVER >> fork
SERVER >> recive data : time
SERVER >> client(38559) time data request              -- (4)
SERVER >> recive data : quit
SERVER >> client(38276) quit request                   -- (5)
SERVER >> recive data : quit
SERVER >> client(38396) quit request                   -- (6)
SERVER >> recive data : quit
SERVER >> client(38559) quit request                   -- (7)

client´Â (1), (2), (3)¿¡¼­ 3¹ø ½ÇÇàÇÏ¿© µ¿ÀÏÇÏ°Ô time ¸Þ½ÃÁö¸¦ ¼Û½Å ¹× µ¥ÀÌŸ¸¦ ¼ö½ÅÇϰí Çϰí quit Çß½À´Ï´Ù.
#] ./client.php 
CLIENT >> socket connect to 111.222.333.12:65000
CLIENT >> Enter command time or quit : time
CLIENT >> Input command : time
CLIENT >> recived data : 2003/05/21 16:18:34
CLIENT >> Enter command time or quit : quit
CLIENT >> Input command : quit
#] 

¾Æ·¡´Â (3),(7)½ÃÁ¡¿¡¼­ µÎ¹ø ÇÁ·Î¼¼½º ÇöȲÀ» È®ÀÎ(ps, pstree)ÇÑ °á°ú ÀÔ´Ï´Ù.
#] ps -xa | grep server.php
30947 pts/3    S      0:00 /usr/local/bin/php -q ./server.php
31203 pts/3    S      0:00 /usr/local/bin/php -q ./server.php
31287 pts/3    S      0:00 /usr/local/bin/php -q ./server.php
31372 pts/3    S      0:00 /usr/local/bin/php -q ./server.php
31467 pts/7    S      0:00 grep server.php
#] pstree
init-+-crond
    ...
    ...
     |-sshd-+-sshd---bash---server.php---3*[server.php]
     |      |-3*[sshd---bash---client.php]
     |      `-sshd---bash---pstree
    ...
    ...
     `-xinetd
#]
#] ps -xa | grep server.php
30947 pts/3    S      0:00 /usr/local/bin/php -q ./server.php
31521 pts/7    S      0:00 grep server.php
#] pstree           
init-+-crond
    ...
    ...
     |-sshd-+-sshd---bash---su---bash---server.php
     |      |-3*[sshd---bash]
     |      `-sshd---bash---pstree
    ...
    ...
     `-xinetd
#]          
(3) ½ÃÁ¡¿¡´Â fork 3¹ø ½ÇÇàÇÑ ¼ø°£À̹ǷΠºÎ¸ð ÇÁ·Î¼¼½º¿Í ÀÚ½Ä ÇÁ·Î¼¼½º 3°³, ÃÑ 4°³ÀÇ ÇÁ·Î¼¼½º°¡ ½ÇÇàµÇ°í Àִ°ÍÀ» È®ÀÎÇÒ¼ö ÀÖ½À´Ï´Ù.

pstreeÀÇ °æ¿ì´Â server.php---3*[server.php]ó·³ Master Process ÇѰ³¿Í Child Process 3°³·Î Ç¥ÇöµÇ¾î ÀÖ½À´Ï´Ù. ¹®·Ð ¸Þ½ÃÁöµµ Àß Àü¼Û µÇ¾ú±¸¿ä.. ^^


5. °á·Ð

¿À´ÃÀº PHPÀÇ Process Control FunctionÀ» ÀÌ¿ëÇÏ¿© ´Ù¼öÀÇ Å¬¶óÀÌ¾ðÆ® ¿äû󸮸¦ ÇØº¸¾Ò½À´Ï´Ù.

fork¹æ½ÄÀº select¹æ½Äº¸´Ù °£´ÜÇÑ ±¸Á¶·Î ±¸ÇöÇϱ⠰£ÆíÇÏ´Ù´Â ÀåÁ¡µµ ÀÖÁö¸¸, ´ÙÁß ÇÁ·Î¼¼½º ±¸Á¶¶ó ÇÁ·Î¼¼½º°£ Åë½ÅÀ» À§Çؼ­ ºÎÂ÷ÀûÀÎ IPC¸¦ ±¸ÇöÇØ¾ß ÇÒ »óȲÀÌ »ý±æ¼öµµ ÀÖ´Ù´Â Á¡ÀÌ ´ÜÁ¡À̶ó ÇÒ¼ö ÀÖ½À´Ï´Ù.

´ÙÀ½ °­Á¿¡´Â mysql°ú Áö±Ý±îÁö ¹è¿î ¼ÒÄÏ Åë½ÅÀ» °¡Áö°í °£´ÜÇÑ Ã¤ÆÃ Ŭ¶óÀ̾ðÆ®/¼­¹ö¸¦ ¸¸µé¾î º¸°Ú½À´Ï´Ù.