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 }
리눅스 커널 메일링 리스트에도 유사한 내용을 확인할 수 있습니다.
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(프로세스)
Reference(워크큐)
워크큐(Workqueue) Overview
'Core BSP 분석 > 리눅스 커널 핵심 분석' 카테고리의 다른 글
[리눅스커널][디버깅] 슬럽(슬랩) 캐시 오브젝트 T32로 메모리 디버깅하기 (0) | 2023.05.06 |
---|---|
[리눅스커널][디버깅] 유저공간 High Memory Zone 페이지 할당 과정 (0) | 2023.05.06 |
[라즈베리파이] 비트 처리 __test_and_set_bit() __test_and_clear_bit() 함수 동작 원리 (0) | 2023.05.06 |
[리눅스] printk 아규먼트 포멧 (0) | 2023.05.06 |
[C언어] 포인터 (p + 1) 연산 (0) | 2023.05.06 |