본문 바로가기
실습/리눅스 커널

커널에서 Blocking I/O

by 써드아이 2021. 2. 8.

[블로그 통합으로 이전해 온 자료] - 

 

 

1. "원자 문맥에서 수행 중(spinlock, seqlock RUC lock 등..)일
때에는 절대로 잠들어서는 안된다."

2. 인터럽트를 비 활성화 시켰을 때에도 잠들 수 없다.

3. semaphore를 보유한 동안 잠드는것은 이 semaphore를 기다리는
다른 프로세스도 잠들게 한다. (주의!!)

3. 잠들기 전에 기다리던 조건을 정말로 충족하는지 확인해야 한다.

4. 누군가 깨울것이라는 확인 없이 잠들어서는 안된다.


대기 큐 wait_queue_t

 <linux/wait.h>
 
 DECLARE_WAIT_QUEUE_HEAD( wq );
 
 wait_queue_head_t wq;
 init_waitqueue_head( &wq );


 condition 조건이 참 일때까지 잠든다는데.. 그러면 깨운다는 의미가 없지 않나?
 
 wait_event( wq, condition );
 wait_event_interruptible( wq, condition );   <-- 주로 사용
 wait_event_timeout( wq, condition, timeout );
 wait_event_interruptible_timeout( wq, condition, timeout );
 
 
 void wake_up( wait_queue_head_t *queue );
 void wake_up_interruptible( wait_queue_head_t *queue );

 DEFINE_WAIT( wait );
 
 wait_queue_t wait;
 init_wait( &wait );
 
 // 상호배제 대기를 설정하면 해당 항목은 대기 큐 맨 끝에 추가하고, 이 설정을 하지 않으면
 // 대기 큐 맨 앞에 추가한다.
 // wake_up() 상호배제 대기 설정을 한 첫 번째 프로세스만 깨운후 멈춘다.
 // wake_up() 은 동일한 함수를 사용.
 // state는 TASK_UNINTERRUPTIBLE 이거나 TASK_INTERRUPTIBLE이 된다.
 
 void prepare_to_wait( wait_queue_head_t *queue, wait_queue_t *wait, int state );
 void prepare_to_wait_exclusive( wait_queue_head_t *queue, wait_queue_t *wait, int state );
 void finish_wait( wait_queue_head_t *queue, wait_queue_t *wait );
 

 example>
 
 잠들 프로세스가 접근한 드라이버 코드
 
 prepare_to_wait( &wq, &wait, TASK_INTERRUPTIBLE ); // 혹은
 prepare_to_wait_exclusive( &wq, &wait, TASK_INTERRUPTIBLE );
 
 if ( condition )
  schedule( );
 
 finish_wait( &wq, &wait );
 
 if ( signal_pending( current ) )
  return -ERESTARTSYS;