본문 바로가기
IT/web

[PHP] 멀티 프로세스 교착 관리 / semaphore, 세마포어, sem_get()

by 어느해겨울 2022. 1. 21.

멀티 프로세스 교착 관리

세마포어와 뮤텍스는 이 포스팅을 보는 본인께서 더 잘 아실 거라 믿는다.

이번에는 php 프로세스 간 세마포어 제어를 다뤄볼 것이다.

 

인터프리터 주제에 세마포어..!? 라고 생각할 수도 있지만 모든 프로그램은 런타임에 메모리에 적재된 순간부터는 모두 같은 프로세스이기 때문에.. (본인은 php 데몬을 애용하는 편이다. 플랫폼 영향을 안 받기 때문)

php - php간, php - 외 native process 간 등 모든 상황에 공유 자원(e.g. file, I/O, db 등 접근 가능한 모든 대상)의 사용 시 교착(deadlock)에 빠질 수 있다.

그래서 php에서도 세마포어가 된다는 것을 알아보려한다.

 


소스코드

세마포어를 이용하기 위해선 sem_get() 을 사용해야 하는데 해당 함수의 인자를 살펴보면

sem_get(
    int $key,
    int $max_acquire = 1,
    int $permissions = 0666,
    bool $auto_release = true
)

- key

ipc에 등록할 세마포어 키 정보.

shell 에서 ipcs -s (ipc 세마포어만 조회) 명령을 했을때 이미 다른 프로세스가 사용하는 키와 겹치지만 않으면 된다.

물론 동일한 공유 자원의 접근 제어를 하려면 동일한 key를 사용하면 된다.

 

- max_acquire
세마포어를 동시에 획득할 수 있는 수를 의미한다. I/O가 분명하여 교착이 발생할 수 있는 상황이라면 1을 사용하자.

(대상을 읽기만 하는 등 공유자원의 상태를 변화시키지 않는 경우엔 복수개를 지정해도 된다.)

- permissions
세마포어 권한을 의미한다. 말 그대로 퍼미션이다. 

- auto_release
세마포어 락을 자동으로 해제하겠냐라는 의미이다.

<?php
    // 세마포어 설정 정보
    $key            = 0x7593;
    $max_acquire    = 1;
    $permissions    = 0666;
    $auto_release   = true;


    // sem_get() 세마포어 설정
    if( !($semaphore = sem_get($key, $max_acquire, $permissions, $auto_release)) ) {
        echo "sem_get() failed.\n";
        return ;
    }

    // 세마포어 동작
    while( true ) {
        echo "세마포어 획득 시도\n";
        sem_acquire($semaphore);
        echo "-> 획득\n";

        echo "텍스트 입력: ";
        $fp   = fopen("php://stdin", "r");
        $text = fgets($fp);
        fclose($fp);

        echo "입력된 텍스트 : {$text} \n";

        sem_release($semaphore);

		 if( strtolower(trim($text, "\n")) == "exit" ) {
            echo "끝\n";
            break;
        }
    }
?>

 

결과

세마포어를 다루는 예제인 만큼 다수의 창을 띄어놓고 결과를 볼것이다.

1. ipcs -s 를 통한 현재 세마포어 정보 확인

- 코드 상에서 지정한 0x7593은 없다. 아직 실행을 안했기 때문.

 

2. 세마포어를 사용하는 php 파일을 실행한다.

- 실행 후 ipcs -s 를 통해 세마포어 키가 생성됐는지 확인한다.

코드 상에서 지정한 0x7593이 생성된 것을 확인할 수 있다.

3. 동시에 동일한 php를 실행하여 동작을 확인한다.

- 한개의 프로세스에서 세마포어 키를 획득하여 밑에 있는 프로세스에서 획득 시도 상태로 대기하는 것을 확인할 수 있다.

 

4. 세마포어 획득 중이던 프로세스에서 텍스트 입력을 해서 세마포어를 넘겨보자.

- 기존에 세마포어를 잡고 있던 프로세스에서 텍스트를 입력받고 세마포어를 릴리즈하여 다른 프로세스가 획득 대기중이였다가 바로 키를 획득한 것을 확인할 수 있다.

 

끝으로 모든 세마포어를 사용하는 프로세스가 종료되었어도 세마포어 키는 남아있을 것이다.

 

불필요하거나 다른 용도로 사용하기 위해선 세마포어 키를 지우자.

ipcrm -S <key> 를 이용하여 세마포어 정보를 삭제한 것을 확인할 수 있다.

 

끝.

 

 

댓글