Post date: Nov 30, 2016 5:43:04 AM
이번엔 실행중 인 process가 잠자게( wait )될때 어떻게 runqueue에서 제거 되는지 살펴 보도록 하자
실행중인 process를 재우기 위해선 wait 관련 함수( wait_event(), wait_event_timeout(), wait_event_interruptible() , wait_event_interruptible_timeout() )를 사용하게 되는데 여기서 설명하는것은 함수 자체에 대한 설명보다는 이런 함수들이 어떻게 현재의 current를 runqueue에서 제거하는지를 촛점에 맞추었으며 이해를 돕기 위해 wait_event_interruptible() 를 기준으로 설명하도록 하겠다.
1. wait.h 에 있는 wait_event_interrupt를 호출하게 되면
1.1 DEFINE_WAIT 메크로를 호출하게 되는데. 이 매크로는 process의 wait_queue에 queue의 이름과 current를 등록하게 된다.
또한 func 항목에는 autoremove_wake_function()을 등록하여 차후 wake_up될때 호출 될수 있도록 하고 있다 ( 이부분은
다음 세미나에서 다룰 wake_up 부분에서 다시 한번 설명 하겠다 )
2. 다시 wait_event_interrupt에 돌아 와서 본격적인 busy wait를 처리 하게 되는데
wait_event_interrupt를 호출 할 때 조건이 만족하지 않거나 wak_up signal이 있을때 까지 loop를 돌며
2.1 wait.c에 있는 prepare_to_wait()함수를 호출하게된다.
prepare_to_wait()함수는 현재 process의 wait_queue가 wait_queue_head에 등록 되어 있지 않으면
wait_queue_head list에 등록하고 현재 current의 task_struct 상태를 TASK_INTERRUPTIBLE로 변경 해주는데
이는 차후 실제적으로 runqueue에서 삭제하기 위한 중요한 조건이 된다.
2.2 wake_up signal이 있을 때 까지sched.c 에 있는 scheduler()를 호출하게 되는데 2.1에서 설정한
TASK_INTERRUPTIBLE 때문에 아래 조건에 의해 deactivate_task가 호출 되어면 runqueue에서 제거 되게 된다.
if (unlikely((prev->state & TASK_INTERRUPTIBLE) && unlikely(signal_pending(prev))))
{
prev->state = TASK_RUNNING;
} else {
deactivate_task(rq, prev, 1);
}
<<이미지 클릭 시 확대 >