인터럽트 중첩 관련

corone의 이미지

인터럽트 중첩 관련해서 몇가지 질문이 있습니다.

(1) 프로세스가 실행 중에 인터럽트가 발생하면
현재 CPU 레지스터들을, 지금까지 실행중이던 프로세스에 할당되어 있는 커널 스택(혹은 인터럽트 스택)에 저장하고
인터럽트 핸들러를 실행하잖아요.

서로 다른 인터럽트가 계속 떠서 인터럽트가 중첩되면
인터럽트 핸들러가 실행중일 때 레지스터들도 또 백업해놓아야 할 것 같은데
(처음에 실행중이었던) 인터럽트된 그 프로세스에 할당되어 있는 커널 스택에 계속 저장되나요?

프로세스가 실행중이던 상태(레지스터)를 백업해놓는 곳은 그 프로세스에 할당되어 있는 커널 스택인데
인터럽트가 실행중이던 상태(레지스터)를 백업해놓는 곳도 (인터럽트된) 프로세스에 할당되어 있는 커널 스택인가요?

다시 말하면,
A 프로세스 -> I 인터럽트 -> J 인터럽트 -> K 인터럽트
이렇게 중첩되었다면
A 프로세스가 중단될 시점의 레지스터 백업 데이터와
I 프로세스가 중단될 시점의 레지스터 백업 데이터와
J 프로세스가 중단될 시점의 레지스터 백업 데이터가
모두 A 프로세스에 할당되어 있는 커널 스택에 저장되는지 입니다.

커널 스택이 아니라 인터럽트 스택을 사용하는 경우와 사용하지 않는 경우가 다르면
구분해서 설명 부탁드립니다.

커널 스택은 프로세"스"마다 할당되어 있고 인터럽트 스택은 프로세"서"마다 할당되어 있는 거죠?

(2) 프로세스가 리스케줄링 되는 대표적인 경우는
프로세스가 이벤트를 기다리기 위해 프로세스 스스로 대기 상태로 진입하는 경우와
타이머 인터럽트 핸들러에서 스케줄링하는 경우죠?

그러면
A 프로세스가 실행 중일 때 I 인터럽트가 발생했고
I 인터럽트 핸들러가 실행 중일 때 타이머 인터럽트가 발생해서
I 인터럽트 핸들러가 실행을 중단하고 타이머 인터럽트 핸들러로 넘어갔습니다.
이 때, 스케줄링이 일어날 수 있나요?
스케줄링이 일어나서 다른 프로세스가 A 프로세스를 선점해버리면 안될 것 같은데
스케줄링이 일어나지 않도록 되어 있나요?

같은 맥락에서,
I 인터럽트 핸들러가 실행을 마치고 복귀할 때,
반드시 처음 인터럽트 되었던 A 프로세스로만 복귀하나요?
다른 프로세스로 복귀되는 경우가 없을까요?

감사합니다.

goforit의 이미지

>인터럽트가 실행중이던 상태(레지스터)를 백업해놓는 곳도 (인터럽트된) 프로세스에 할당되어 있는 커널 스택인가요?

인터럽트 전용 스택이 따로 있습니다.
OS 마다 구현에 차이가 있는데 일반적으로 IRQ Stack이 따라 있습니다. 이 것은 Process Stack 완전 별개의 메모리입니다.

IRQ Stack은 CPU 마다 전용으로 하나씩 있습니다. 그 냥 메모리에서 일부분 할당에 주는 것입니다.

bushi의 이미지

리눅스를 예로 들면, 얼마 전 까지는 IRQ stack 을 따로 쓰지 않았습니다. 지금은 따로 쓰는 지 모르겠습니다.
인터럽트 핸들러에서 스택을 과도하게 사용하면 context switch 할 때 백업 해 놓은 CPU 레지스터값등등이 망가져 죄없는 어플리케이션이 돌연사하는 경우도 있었죠.

+덧
오래 전에 lwn 에 올라왔던 irq stack 어쩌고하는 글을 읽기만 하고 넘겼는데 다시 찾아보니 arm64 linux 에 대한 얘기네요.
arm linux 가 늦는 편인 것 같고, 다들 일찌감치 irq stack 을 따로 운용하는 것 같습니다.

goforit의 이미지

그나 저나 Bushi님을 본지 몇십년이 지났네요.
항상 건강하실 빕니다.

AustinKim의 이미지

궁금한 점에 대해 조금 내용을 추가(주제/내용)해 업데이트 드립니다.

> 커널 스택이 아니라 인터럽트 스택을 사용하는 경우와 사용하지 않는 경우가 다르면
> 구분해서 설명 부탁드립니다.
>
> 커널 스택은 프로세"스"마다 할당되어 있고 인터럽트 스택은 프로세"서"마다 할당되어 있는 거죠?

1. 프로세스 스택 관련
1.1 프로세스 스택 생성
대부분 프로세스를 생성할 때 스택 공간을 할당해줍니다.

프로세스 생성 시 다음 함수 호출 흐름으로,

 
 ; _do_fork -> copy_process -> dup_task_struct -> alloc_thread_stack_node


alloc_thread_stack_node() 함수에서 스택를 할당해 줍니다.

 
[<a href="https://elixir.bootlin.com/linux/v4.19.30/source/kernel/fork.c" rel="nofollow">https://elixir.bootlin.com/linux/v4.19.30/source/kernel/fork.c</a>]
static unsigned long *alloc_thread_stack_node(struct task_struct *tsk, int node)
{
 ...	 
 	struct page *page = alloc_pages_node(node, THREADINFO_GFP,
					     THREAD_SIZE_ORDER);
 
	return page ? page_address(page) : NULL;


프로세스별 스택 사이즈는 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별로 공간이 있는 것입니다.

 
crash64> p irq_stack_ptr
PER-CPU DATA TYPE:
  unsigned long *irq_stack_ptr;
PER-CPU ADDRESSES:
  [0]: ffffffc13cf2b090
  [1]: ffffffc13cf42090
  [2]: ffffffc13cf59090
  [3]: ffffffc13cf70090
  [4]: ffffffc13cf87090
  [5]: ffffffc13cf9e090
  [6]: ffffffc13cfb5090
  [7]: ffffffc13cfcc090


< 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

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.