인터럽트 중첩 관련
인터럽트 중첩 관련해서 몇가지 질문이 있습니다.
(1) 프로세스가 실행 중에 인터럽트가 발생하면
현재 CPU 레지스터들을, 지금까지 실행중이던 프로세스에 할당되어 있는 커널 스택(혹은 인터럽트 스택)에 저장하고
인터럽트 핸들러를 실행하잖아요.
서로 다른 인터럽트가 계속 떠서 인터럽트가 중첩되면
인터럽트 핸들러가 실행중일 때 레지스터들도 또 백업해놓아야 할 것 같은데
(처음에 실행중이었던) 인터럽트된 그 프로세스에 할당되어 있는 커널 스택에 계속 저장되나요?
프로세스가 실행중이던 상태(레지스터)를 백업해놓는 곳은 그 프로세스에 할당되어 있는 커널 스택인데
인터럽트가 실행중이던 상태(레지스터)를 백업해놓는 곳도 (인터럽트된) 프로세스에 할당되어 있는 커널 스택인가요?
다시 말하면,
A 프로세스 -> I 인터럽트 -> J 인터럽트 -> K 인터럽트
이렇게 중첩되었다면
A 프로세스가 중단될 시점의 레지스터 백업 데이터와
I 프로세스가 중단될 시점의 레지스터 백업 데이터와
J 프로세스가 중단될 시점의 레지스터 백업 데이터가
모두 A 프로세스에 할당되어 있는 커널 스택에 저장되는지 입니다.
커널 스택이 아니라 인터럽트 스택을 사용하는 경우와 사용하지 않는 경우가 다르면
구분해서 설명 부탁드립니다.
커널 스택은 프로세"스"마다 할당되어 있고 인터럽트 스택은 프로세"서"마다 할당되어 있는 거죠?
(2) 프로세스가 리스케줄링 되는 대표적인 경우는
프로세스가 이벤트를 기다리기 위해 프로세스 스스로 대기 상태로 진입하는 경우와
타이머 인터럽트 핸들러에서 스케줄링하는 경우죠?
그러면
A 프로세스가 실행 중일 때 I 인터럽트가 발생했고
I 인터럽트 핸들러가 실행 중일 때 타이머 인터럽트가 발생해서
I 인터럽트 핸들러가 실행을 중단하고 타이머 인터럽트 핸들러로 넘어갔습니다.
이 때, 스케줄링이 일어날 수 있나요?
스케줄링이 일어나서 다른 프로세스가 A 프로세스를 선점해버리면 안될 것 같은데
스케줄링이 일어나지 않도록 되어 있나요?
같은 맥락에서,
I 인터럽트 핸들러가 실행을 마치고 복귀할 때,
반드시 처음 인터럽트 되었던 A 프로세스로만 복귀하나요?
다른 프로세스로 복귀되는 경우가 없을까요?
감사합니다.
일반적인 예
>인터럽트가 실행중이던 상태(레지스터)를 백업해놓는 곳도 (인터럽트된) 프로세스에 할당되어 있는 커널 스택인가요?
인터럽트 전용 스택이 따로 있습니다.
OS 마다 구현에 차이가 있는데 일반적으로 IRQ Stack이 따라 있습니다. 이 것은 Process Stack 완전 별개의 메모리입니다.
IRQ Stack은 CPU 마다 전용으로 하나씩 있습니다. 그 냥 메모리에서 일부분 할당에 주는 것입니다.
리눅스를 예로 들면, 얼마 전 까지는 IRQ
리눅스를 예로 들면, 얼마 전 까지는 IRQ stack 을 따로 쓰지 않았습니다. 지금은 따로 쓰는 지 모르겠습니다.
인터럽트 핸들러에서 스택을 과도하게 사용하면 context switch 할 때 백업 해 놓은 CPU 레지스터값등등이 망가져 죄없는 어플리케이션이 돌연사하는 경우도 있었죠.
+덧
오래 전에 lwn 에 올라왔던 irq stack 어쩌고하는 글을 읽기만 하고 넘겼는데 다시 찾아보니 arm64 linux 에 대한 얘기네요.
arm linux 가 늦는 편인 것 같고, 다들 일찌감치 irq stack 을 따로 운용하는 것 같습니다.
추가
그나 저나 Bushi님을 본지 몇십년이 지났네요.
항상 건강하실 빕니다.
IRQ 스택와 인터럽트 발생 시 스케줄링에 대해서...
궁금한 점에 대해 조금 내용을 추가(주제/내용)해 업데이트 드립니다.
> 커널 스택이 아니라 인터럽트 스택을 사용하는 경우와 사용하지 않는 경우가 다르면
> 구분해서 설명 부탁드립니다.
>
> 커널 스택은 프로세"스"마다 할당되어 있고 인터럽트 스택은 프로세"서"마다 할당되어 있는 거죠?
1. 프로세스 스택 관련
1.1 프로세스 스택 생성
대부분 프로세스를 생성할 때 스택 공간을 할당해줍니다.
프로세스 생성 시 다음 함수 호출 흐름으로,
alloc_thread_stack_node() 함수에서 스택를 할당해 줍니다.
프로세스별 스택 사이즈는 32비트 아키텍처는 4K(0x2000), 64 비트 아키텍처는 8K(0x4000)입니다.
1.2 인터럽트 스택
제 블로그에 포스팅한 글을 참고하면 좋을 것 같습니다.
http://rousalome.egloos.com/9966360
ARM64 아키텍처의 경우 IRQ 스택 커밋은 다음과 같습니다. ARM 사의 전문가인 Mark Rutland 님의 패치입니다.
https://patchwork.kernel.org/patch/9886071/
크래시 유틸리티로 IRQ 스택인 irq_stack_ptr percpu 타입 전역 변수를 확인하면 다음과 같습니다. (CPU가 8개입니다.)
per-cpu 변수니 CPU별로 공간이 있는 것입니다.
< A 프로세스가 실행 중일 때 I 인터럽트가 발생했고
< I 인터럽트 핸들러가 실행 중일 때 타이머 인터럽트가 발생해서
< I 인터럽트 핸들러가 실행을 중단하고 타이머 인터럽트 핸들러로 넘어갔습니다.
< 이 때, 스케줄링이 일어날 수 있나요?
< 스케줄링이 일어나서 다른 프로세스가 A 프로세스를 선점해버리면 안될 것 같은데
<스케줄링이 일어나지 않도록 되어 있나요?
2. 인터럽트 핸들러와 스케줄링 관련
2.1 인터럽트 핸들러에서 스케줄링을 할까?
인터럽트 핸들러나 인터럽트 핸들러 서부 루틴에서 스케줄링을 할 수 없습니다.
만약 스케줄링 관련 함수를 호출하면 커널은 크래시를 유발합니다.
님이 말씀하시는 스케줄링은 선점 스케줄링입니다.
1> 인터럽트 벡터 실행
2> 인터럽트 핸들러 실행
3> 다시 인터럽트 벡터 복귀
4> 선점 스케줄링 시도
위 4번 단계에서 선점 스케줄링을 시도합니다.
2.2 프로세스가 선점되지 않으려면?
preempt_disable() 함수를 써서 특정 코드 구간 실행 시 선점 스케줄링을 지연시킬 수 있습니다.
세부 내용은 다음 포스팅을 참고하세요.
http://rousalome.egloos.com/9991105
(개인블로그)
http://rousalome.egloos.com
댓글 달기