2009-06-10 2 views
2

(익명 뮤텍스 예제)에 따라 boost::interprocess::shared_memory_object을 사용하여 Linux에서 IPC를하고 있습니다.boost :: interprocess :: scoped_lock을 사용하는 동안 절전 모드를 해제하면 절대로 해제되지 않습니다.

서버 프로세스는 shared_memory_object를 작성하고 interprocess_mutexscoped_lock에 랩핑하여 보유하고 있습니다. 그리고 다른 하나가 쓴 것을 인쇄하는 클라이언트 프로세스 -이 경우 int입니다.

문제가 생겼다. 서버가 뮤텍스를 유지하면서 잠자면 클라이언트 프로세스는 결코 그것을 획득 할 수없고 영원히 기다린다.

버기 서버 루프 :

using namespace boost::interprocess; 
int n = 0; 
while (1) { 
    std::cerr << "acquiring mutex... "; 
    { 
     // "data" is a struct on the shared mem. and contains a mutex and an int 
     scoped_lock<interprocess_mutex> lock(data->mutex); 
     data->a = n++; 
     std::cerr << n << std::endl; 
     sleep(1); 
    } // if this bracket is placed before "sleep", everything works 
} 

서버 출력 :

acquiring mutex... 1 
acquiring mutex... 2 
acquiring mutex... 3 
acquiring mutex... 4 

클라이언트 루프 :

while(1) { 
    std::cerr << "acquiring mutex... "; 
    { 
     scoped_lock<interprocess_mutex> lock(data->mutex); 
     std::cerr << data->a << std::endl; 
    } 
    sleep(1); 
} 

클라이언트 출력 (영원히 대기) :

acquiring mutex... 

문제는 sleep 호출 전에 괄호를 줄에 놓으면 모든 것이 작동한다는 것입니다. 왜? 잠긴 뮤텍스로 잠자는 것은 뮤텍스가 영원히 잠길 것이라고 생각하지 않았습니다.

내가 가진 유일한 이론은 커널이 서버 프로세스를 깨우면 범위가 끝나고 뮤텍스가 해제되지만 대기 프로세스에는 실행할 기회가 주어지지 않는다는 것입니다. 그런 다음 서버가 잠금 장치를 다시 얻습니다.하지만 이는별로 의미가없는 것처럼 보입니다.

고마워!

답변

7

귀하의 이론은 정확합니다.

당신은 연결 기준의 익명 뮤텍스 예를 하단에 보면 우리가 볼 수 있듯이, 당신이

를 볼 수 있습니다, 뮤텍스는 데이터를 보호하는 데 유용하지만 다른 프로세스에 통지하지 이벤트.

이 기다리고 및 프로세스 그냥 깨어 있기 때문에, 그것은 거의 확실히 더 많은 작업을 수행 할 왼쪽의 스케줄링 양자의 많음을 가지고 할 수있는 것을 다른 사람에게 통보하지 않은 뮤텍스를 해제. 클라이언트가 뮤텍스 자체를 획득해야하는 첫 번째 기회 인 다시 잠자기하기 전에 루프를 돌고 뮤텍스를 다시 획득합니다.

sleep() 범위를 벗어난 서버 이동은 뮤텍스가 무료 인 동안 절전 모드로 전환됨을 의미하며 클라이언트가 뮤텍스를 실행하고 스스로 획득 할 수있는 기회를 제공합니다.

프로세서를 포기하고 여전히 범위에서 수면을 걸려면 sched_yield() (Linux에만 해당)으로 전화 해보십시오.sleep(0)도 사용할 수 있습니다.

+0

부스트는 스레드를 포기하는 자체 호출을 가지고 있습니다 (리눅스의 schedu_yield처럼) : boost :: this_thread :: yield() – teeks99

+0

고마워요. 'sleep (0)'이 효과가있어 이론을 확인합니다. 뮤텍스를 공개하는 행위가 최소한 시스템 호출과 그에 따른 일정 조정을 초래할 것이라는 인상하에 있었지만 잘못되었습니다. –

0

뮤텍스를 유지하면서 잠자는 것은 잘못되었습니다. 뮤텍스는 일부 데이터 (즉, 데이터 -> a)를 보호하며 범위는 해당 데이터의 읽기/쓰기를 최소화해야합니다.

+0

예, 감사합니다. 그러나 어쨌든 작동하지 않아야합니까? –

+0

나는 그것이 실제로해야한다고 생각했다; 스티브가 진짜 문제를 이해하는 데 더 나은 일을 한 것처럼 보입니다. – Andrey