Linux kernel v4.4에서 간단한 블록 장치 드라이버 만들어보기

wait-queue의 내부 구현

null_blk드라이버도 그렇고 블럭레이어에서도 마찬가지로 prepare_to_wait_event와 schedule, finish_wait함수가 프로세스를 잠들게하는 코드입니다. 그리고 wake_up함수가 프로세스를 깨웁니다. schedule은 간단하게 분석할 수 없으니 제외하고 나머지 함수들만 간단하게 읽어보겠습니다.

prepare_to_wait_event

함수의 인자는

  • wait_queue_head_t *q: wait-queue를 표현하는 구조체
  • wait_queue_t *wait: 현재 잠들 프로세스를 표현하는 구조체
  • int state: 잠들때 어떤 상태로 잠들 것인지

코드를 보면 다음과 같은 순서로 처리합니다.

  • wait->private = current 현재 프로세스의 task_struct 객체를 저장
  • wait->func = autoremove_wake_function 나중에 프로세스가 깨어날때 호출된 함수
  • wait_queue_head_t 객체의 스핀락 잡기
  • __add_wait_queue(q, wait): list_add함수와 동일합니다. wait_queue_t 객체의 task_list 노드를 wait_queue_head_t 객체의 리스트에 추가하는 것입니다.
  • set_current_state: 프로세스의 상태 수정
  • 스핀락 해지

wait_queue_head_t 객체에 프로세스를 추가하는게 코드의 전부입니다. 프로세스의 상태가 TASK_RUNNING이 아닌 TASK_INTERRUPTIBLE등의 잠든 상태로 바꿨으니 schedule함수가 호출되면 스케줄러가 알아서 프로세스를 잠재웁니다.

finish_wait

prepare_to_wait_event의 반대로 처리하겠지요. 프로세스의 상태를 TASK_RUNNING으로 바꾸고, wait_queue_head_t 객체의 리스트에서 프로세스를 제거합니다.

wake_up

wake_up은 __wake_up_common의 wrapper입니다. __wake_up_common은 wait_queue_head_t 객체의 리스트를 돌면서 wait_queue_t객체의 func 필드에 등록한 함수를 호출합니다. prepare_to_wait_event에서는 autoremove_wake_function 함수를 등록했습니다. autoremove_wake_function은 스케줄러의 try_to_wake_up함수를 호출합니다. 이때부터는 스케줄러의 영역이므로 더는 분석하지 않겠습니다만 wait_queue_t 필드의 private필드에 프로세스의 task_struct 객체가 저장되어있으므로, 스케줄러가 프로세스를 깨울 수 있다는 것만 알면 될것같습니다.

 

결국 전체적인 디자인을 보면 리스트를 만들어서 잠든 프로세스의 task_struct 객체를 보관하고, 자원을 해지하는 함수가 리스트를 돌면서 리스트에 있는 task_struct 객체를 스케줄러에게 깨워달라고 의뢰하는 방식입니다.

댓글

댓글 본문
작성자
비밀번호
버전 관리
gurugio
현재 버전
선택 버전
graphittie 자세히 보기