Linux Kernel(4.14) Hacks

rousalome.egloos.com

포토로그 Kernel Crash




[Linux][Kernel] preempt_disable()/preempt_enable() 주의 사항 Linux Kernel - Core Analysis

preempt_disable() 함수를 쓸 때 주의해야 할 점이 있습니다.
preempt_disable() 함수는 preempt_enable() 함수와 반드시 Pair로 써야 합니다.

preempt_disable() 함수를 호출한 다음 스케줄링 동작을 수행하는 함수를 쓰면 리눅스 시스템은 오동작합니다.

예를 들어 다음과 같은 드라이버를 초기화하는 코드를 예를 들겠습니다.
1 void configure_something_driver(void) 
2 {
3 preempt_disable();
4
5 do_something();
6 mdelay(100);
7 do_something();
8
9 preempt_enable();
10 }

5~7 번 코드가 실행할 때 Preemption이 되면 안된다고 판단했습니다.
그래서 3 번째와 9 번째 줄에 preempt_disable() 함수와 preempt_enable() 함수를 추가해서
5~7 번째 코드 구간에서 Preemption으로부터 보호한 것입니다.

위 코드를 실행하면 커널 패닉이 발생하거나 이상한 커널 로그를 출력합니다.
그 이유는 무엇일까요?

6 번째 줄 mdelay() 함수를 호출하면 schedule() 함수를 호출하기 때문입니다.

리눅스 커널 입장에서 다음 함수와 같이 해석할 수 있다는 것입니다.
1 void configure_something_driver(void) 
2 {
3 preempt_disable();
4
5 do_something();
6 schedule();
7 do_something();
8
9 preempt_enable();
10 }

위 코드는 다음과 같이 수정하면 문제가 발생하지 않을 것입니다. 
1 void configure_something_driver(void) 
2 {
3 preempt_disable();
4 do_something();
5 preempt_enable();
6
7 mdelay(100);
...
8 }

리눅스 커널 메일링 리스트에도 유사한 내용을 확인할 수 있습니다.
[출처: https://lkml.org/lkml/2010/5/13/638]
Sleeping in the kernel with preemption disabled is considered to be a
bug.  So the scheduler will print an error and a stack dump when this
happens.

In contrast, it is OK to do the following:

preempt_disable();
do_something();
preempt_enable();
schedule();
preempt_disable();
do_something_else();
preempt_enable();

preempt_disable() 함수를 호출해서 Preemption을 보류시키고 휴면에 들어가면 안된다는 내용입니다.



#Reference 시스템 콜


Reference(워크큐)
워크큐(Workqueue) Overview


덧글

댓글 입력 영역