2016-10-13 4 views
1

리눅스 커널 대기열에서 wait_event을 사용하여 대기하는 방법과 깨우는 방법을 알고 있습니다.Linux 커널 : 여러 대기열에서 대기하는 방법?

이제 여러 큐에서 한 번에 대기하는 방법을 알아야합니다. 기본적으로 poll 또는 select과 비슷한 방식으로 여러 이벤트 소스를 멀티플렉싱해야하지만 이벤트 소스에 pollable file descriptor 형식이 없으므로 필자는 이러한 시스템 호출의 구현에 영감을 찾을 수 없었습니다. .

초기 생각은 wait_event 매크로에서 코드를 가져오고 DEFINE_WAITprepare_to_wait을 여러 번 사용하는 것이 었습니다.

그러나 주어진 방법은 prepare_to_wait입니다. 동일한 "웨이터"가 여러 번 추가되면 대기열의 내부 연결 목록이 손상 될 우려가 있습니다 (대기열이 하나의 대기열을 발생 시키지만 대기 할 경우 발생할 수 있음). 조건이 충족되지 않고 대기가 다시 시작됨). 여러 waitqueues에서 대기 가능한 시나리오

답변

2

하나 :

int ret = 0; // Result of waiting; in form 0/-err. 

// Define wait objects, one object per waitqueue. 
DEFINE_WAIT_FUNC(wait1, default_wake_function); 
DEFINE_WAIT_FUNC(wait2, default_wake_function); 

// Add ourselves to all waitqueues. 
add_wait_queue(wq1, &wait1); 
add_wait_queue(wq2, &wait2); 

// Waiting cycle 
while(1) { 
    // Change task state for waiting. 
    // NOTE: this should come **before** condition checking for avoid races. 
    set_current_state(TASK_INTERRUPTIBLE); 
    // Check condition(s) which we are waiting 
    if(cond) break; 
    // Need to wait 
    schedule(); 
    // Check if waiting has been interrupted by signal 
    if (signal_pending(current)) { 
     ret = -ERESTARTSYS; 
     break; 
    }    
} 
// Remove ourselves from all waitqueues. 
remove_wait_queue(wq1, &wait1); 
remove_wait_queue(wq2, &wait2); 
// Restore task state 
__set_current_state(TASK_RUNNING); 
// 'ret' contains result of waiting. 

주,이 시나리오는 wait_event 중 하나에서 약간 다른 것을 :

wait_event이 (DEFINE_WAIT로 만든) 대기 개체에 대한 autoremove_wake_function 사용합니다. 이 함수는 wake_up()에서 호출하여 대기열에서 대기중인 객체를 제거합니다. 따라서 에 다시 입력하여 대기열에있는 객체 각 반복.

그러나 대기 대기열이 여러 개있는 경우 알 수없는 대기 대기열이 있습니다. 따라서이 전략을 따르면 은 모든 반복 객체가 인 모든 대기 객체을 다시 추가해야하므로 비효율적입니다.

대신에 wait 객체에 default_wake_function을 사용하므로 wake_up() 호출에서 객체가 waitqueue에서 제거되지 않으며 대기 전에 한 번만 대기 객체를 대기열에 추가하면 충분합니다.