리눅스의 선점형과 비선점형을 아주 간단하게 한마디로 말하자면

sisbn의 이미지

-> [ 스케줄러의 호출 시점 ]

비선점형 : 인터럽트의 발생에 상관없이 실행중인 유저 프로세스

가 끝나면 스케줄러를 호출한다.

선점형 : 인터럽트가 발생을 하면 유저 프로세스로 넘어가기

바로전의 인터럽트 루틴을 마친후에 스케줄러를 호출

을 한다.

넘 단순하게 생각하는건가요?? 부족한 부분은 짚어주세요.^^

댓글

익명 사용자의 이미지

sisbn wrote:
-> [ 스케줄러의 호출 시점 ]

비선점형 : 인터럽트의 발생에 상관없이 실행중인 유저 프로세스

가 끝나면 스케줄러를 호출한다.

선점형 : 인터럽트가 발생을 하면 유저 프로세스로 넘어가기

바로전의 인터럽트 루틴을 마친후에 스케줄러를 호출

을 한다.

넘 단순하게 생각하는건가요?? 부족한 부분은 짚어주세요.^^

선점형 OS 와 비선점형 OS 의 차이를 기술하려는거라면.. 기준이 조금 틀린것같네요. 꼭 인터럽트의 처리에 따라서 나누어지는건 아니니까요. 전 간결하게..

특정 프로세스가 CPU 를 독점하는것이 가능(프로세스가 스스로 CPU 점유를 포기해야만 다른 프로세스가 실행)하면 비선점형,
특정 프로세스가 CPU 를 독점하는것이 불가능(운영체제가 강제로 프로세스의 CPU 점유를 제어)하면 선점형

이라고 설명한 어떤 책의 내용이 이해하기 쉽더군요.

익명 사용자의 이미지

시스템콜이 중간에 짤릴수 있는지 없는지로 구분하면 좋을듯합니다.

선점형 커널 구현방법에 따라 다르겠습니다만..

일반적으로 선점형 커널은 시스템콜 수행도중에 일정포인트마다

인터럽트를 확인해서 인터럽트 수행을 우선시 합니다.

일반적인 비선점형 커널은 일단 시스템콜 수행도중에는

인터럽트처리루틴으로 빠져나가지 않고 시스템콜 수행후에

인터럽트를 처리합니다.

기본적으로는 선점형 커널이 응답성이 좋다고 볼수 있습니다만..

선점형 커널의 루틴 구현이 복잡해지기 때문에

응답성의 향상 이외에 퍼포먼스의 향상은 기대하기 어렵습니다.

jika의 이미지

몇가지 오류에 대해서 지적하고 싶군요...

어떤 프로세스도 cpu를 독점적으로 사용할수 없습니다.

우선순위에 의해 CPU 자원을 할당하며

인터럽트 디스에이블 걸오놓지 않는한 인터럽트는 어떤경우에도 유저프로세스 보다는 우선입니다.

다만 유저가 시스템콜을 호출해서 커널모드로 동작할때는

비선점형의 경우는 시스템 콜 처리후에 인터럽트를 처리하고

선점형의 경우에는 시스템 콜 처리도중에 인터럽트를 처리한다는

차이가 생깁니다.

익명 사용자의 이미지

꼭 시스템호출로만 얘기하면 아니되고,...
어떤 user process에서
...
while(1) // 무한루프
;
...

* 비선점형
결코 다른 프로세스가 수행될 수 없습니다.
- 스케쥴링 발생시기 : 주로 user process에서 시스템호출을 수행할때 한다.
- 예: Windows 3.1

* 선점형
다른 프로세스도 수행가능
- 스케쥴링 발생시기 : 보통 시스템호출을 수행할때, 타이머에의해
- 예: 현재 대부분 운영체제...

익명 사용자의 이미지

* 아~ windows 3.1은 운영체제라 칭하기에는 좀 아햏햏하군요.

jika의 이미지

비선점형 커널에서 무한루프 동작하는 프로세스가

CPU를 나눠주지 않는다는건 말이 되지 않습니다.

시분할 시스템에서 타임슬라이스와 테스크 우선순위에 따라

프로세스별로 cpu 자원을 할당하죠

그래서 컨텍스트 스위치가 일어나구요.

님 말씀대로라면 비선점형 커널에서 무한루프 도는 프로세스가

한개라도 발생하면 컴퓨터는 아무것도 할수 없습니다.

windows 에서나 리눅스 비선점형커널에서

무한루프 도는 프로그램 하나 컴파일해서 돌린다고

시스템이 죽어버리던가요?

criny333의 이미지

지당하신말씀

익명 사용자의 이미지

저 말을 2가지로 사용하는 것으로 알고 있습니다.

1. process 의 cpu 사용에 따라서
선점형 OS : OS 가 강제로 context switching 을 수행하므로 한 process가 cpu를 독점할 수 없음
비선점형 OS : process 가 cpu 를 양보하지 않는 한, 다른 process 로 context switching 이 일어나지 않음

2. kernel 의 interrupt 처리에 따라서
선점형 kernel : kernel mode 에서 다른 interrupt 실행 됨.
비선점형 kernel : kernel mode 에서 다른 interrupt 실행 불가.

글타래를 보니 2가지가 섞여서 언급되고 있네요.

익명 사용자의 이미지

선점형 OS : windows 95 이후, linux 등
비선점형 OS : windows 3.1

선점형 kernel : linux kernel 2.6 이후 (optional)
비선점형 kernel : linux kernel 2.4 이전

jika의 이미지

비선점형 OS process 가 cpu 를 양보하지 않는 한, 다른 process 로 context switching 이 일어나지 않음

이말은 좀 틀린 표현입니다.

비선점형 커널에서 프로세스가 자발적으로 블럭되지 않을때에도

타임슬라이스가 만료되면 컨텍스트 스위치는 발생합니다.

몇몇분들이 스케줄링 폴리시와 선점형 비선점형 구분을 혼동하시는데요.

선점형 비선점형 커널의 구분은 스케줄링 폴리시와는 별 연관이 없습니다.

다만 시스템콜과 인터럽트 간의 우선순위 배분에 따른 차이입니다.

유저스페이스에서 돌고 있는 유저프로세스의 cpu 배분에는 아무런 영향이 없습니다.

다시 정리하면

비선점형 인터럽트 >= 시스템콜(커널모드) > 유저프로세스(유저모드)

선점형 인터럽트 > 시스템콜 > 유저프로세스

비선점형에서 인터럽트와 시스템콜 간에 우선순위를 >= 으로 표시한것은

인터럽트가 시스템콜보다는 우선순위가 높지만 시스템콜 수행도중에는

인터럽트를 처리할수 없기 때문에 >= 으로 표시했습니다.

선점형에서는 시스템콜 수행도중에도 인터럽트 루틴을 처리하므로

인터럽트 > 시스템콜 이라고 할수 있겠죠.

유저프로세스간의 우선순위나 시스템콜과 유저프로세스 간의 우선순위차이는

선점형이건 비선점형이건 영향을 주지 않습니다.

익명 사용자의 이미지

jika wrote:

...
그래서 컨텍스트 스위치가 일어나구요.

이미 선점형이군요.
jika wrote:

님 말씀대로라면 비선점형 커널에서 무한루프 도는 프로세스가

한개라도 발생하면 컴퓨터는 아무것도 할수 없습니다.


예 맞습니다.
jika wrote:

windows 에서나 리눅스 비선점형커널에서

무한루프 도는 프로그램 하나 컴파일해서 돌린다고

시스템이 죽어버리던가요?


윈도우 3.1써보셨나요?

각설하고,...
음 아마도, 커널내부의 선점형과 착각하신듯합니다.
1. 사용자 프로세스들(n개)+커널의 관점에서 선점형이 의미하는 바로 preemtive scheduling을 먼저 이해하고 선점/비선점

2. 커널의 디바이스드라이버 수준의 선점형(사용자 프로세스를 배제한, 드라이버간의...)에 대해 나눠서 이해하시는게 옳습니다.
일반적으로 선점형은 1을 의미하며, 2는 좀더 심화된 얘기로 봐야합니다.

2에 대해 관심이 많으신것 같은데, 다음 참고사이트를 참고하시기 바랍니다.
http://kelp.or.kr/korweblog/stories.php?story=03/12/17/1060745

익명 사용자의 이미지

글을 읽고 보니 cyk님이 잘 정리해 주셨군요.

jika의 이미지

회사에서 이런글 쓰고 있으려니까 좀 그렇긴 한데요..

제가 커널 관련분야에서 종사하고 있고

학위도 스케줄링에 관계된 것이어서 그냥 지나가기가 그렇네요.

뭐 앞에서 많은 이야기를 했기에

같은 이야기를 반복하기는 그렇고

비선점형 커널과 선점형 커널에 대한 배경이야기를 좀 하겠습니다.

인터럽트는 말그대로 "만사 제처두고 이것부터 처리해달라" 입니다.

커널 내부적으로는 인터럽트간에도 우선순위가 있습니다만

그건 무시하고 인터럽트를 처리하는 시점은

CPU가 유저스페이스에 있을때는 항상이구요.. 바로 즉시 입니다.

커널 모드에 있을때는 프레그에 세팅해놓고 커널모드에서

벗어나기 직전에 인터럽트 확인해서 처리합니다.

이런 방식이 일반적인 비선점형 커널입니다.

일반적으로 시스템콜의 구현은 간결해야 합니다. 비선점형 커널에서는 특히 그렇습니다.

시스템콜 루틴이 길어지면 시스템전체의 응답성을 매우 떨어뜨리는데요.

시스템콜 수행중에 인터럽트가 밀려있기 때문에 그렇습니다.

이 문제를 해결하기 위해서는

시스템콜을 간결하게 만들거나 시스템콜 수행도중에 중간중간

에 프리엠션 포인트를 넣어서 처리해야할 인터럽트가 있는지

확인하고 있다면 인터럽트 서비스루틴으로 점프를 합니다.

이것을 선점형 커널이라고 부릅니다.

자꾸 다른이야기를 하시는 분들이 많은데

지금 리눅스 시스템의 90% 이상은 비선점형 커널로 동작합니다.

본인의 필요에 의해서 선점형커널로 컴파일 하지 않는한

대부분 비선점형 커널로 동작합니다.

무한루프 도는 코드 넣어서 컴파일해서 돌리시고

다른 유저로 접속하거나 다른 데몬들 동작유무를 확인 하십시요.

그렇게 밖에는 더 설명을 못하겠네요..

anfl의 이미지

선점형 비선점형을 interrupt로만 국한시키는 것은 맞지 않습니다.
interrupt가 발생했을때 바로 수행될수 있다는 이야기는 kernel이 선점 가능한 코드로 구현되었기 때문에 생기는 하나의 현상이지
그 현상을 보고 선점형 커널이다 아니다라고 말하는것은 옳지 않습니다.

선점형은 위에분 말씀대로 프로세스의 자발적 양보없이 언제든지 커널에게 선점당할수 있다는것을 의미합니다.


purluno의 이미지

처음에 질문하신 분은 리눅스의 선점형과 비선점형이 어떤 것을 의미하냐고 물으셨고 그것은 jika님의 말씀이 맞습니다.

선점형/비선점형 커널의 의미가 혼용되는 것 같으니 선점형/비선점형 멀티태스킹이라는 용어로 분리해보자면 선점형/비선점형 멀티태스킹의 구분은 스케쥴링 정책쪽에 해당하는 문제입니다. 윗분께서 말씀하신 선점형/비선점형 OS라는 것은 이것을 의미할 것입니다. 운영체제 책 'Operating Systems : Internals and Design Principles (Fifth Edition), William Stallings 저'를 참고해보면 이것을 스케쥴링 정책의 decision mode라고 부르고있고 정확히 Nonpreemptive(비선점)과 Preemptive(선점)라는 용어를 사용하고 있습니다. 대표적인 비선점형 스케쥴링 방식으로는 FCFS(First-Come-First-Served)가 있고, 선점형 스케쥴링 방식으로는 Round-Robin이 있습니다.

리눅스 커널은 선점형 멀티태스킹을 하고, 2.4 이하는 비선점형 커널, 2.6은 선점형 커널과 비선점형 커널을 선택할 수 있습니다.

MS윈도우즈3.1은 비선점형 멀티태스킹을 합니다. 한 어플리케이션이 시스템콜 호출, 입출력 사용 등의 방법으로 CPU를 운영체제에 넘겨주지 않으면 혼자서 프로세서를 독점합니다. 인터럽트와 시스템콜의 문제는 MS-DOS의 커널에 의존할 것 같습니다.

anfl의 이미지

Quote:

선점형/비선점형 커널의 의미가 혼용되는 것 같으니 선점형/비선점형 멀티태스킹이라는 용어로 분리해보자면 선점형/비선점형 멀티태스킹의 구분은 스케쥴링 정책쪽에 해당하는 문제입니다. 윗분께서 말씀하신 선점형/비선점형 OS라는 것은 이것을 의미할 것입니다.

제가 말씀 드린내용은 단순히 스케줄링 정책과 관련된 내용이 아닙니다.
kernel을 구현하는데 있어 코드상에서 선점 가능하게 되어있나 가능하지 않게 되어있나를 말씀드린겁니다.

리눅스 2.6이 kernel mode 상에서 선점 가능한 이유는 kernel을 구현하는데 있어서 모두 재진입 가능 함수로 재 작성되었기 때문에 가능한 것입니다.
일반적으로 재진입 가능 함수를 작성하기 위해서는 전역적인 자료구조의 접근에 대해서 모두 atomic하게 접근해야 합니다.
기존의 2.4 kernel은 이러한 atomic한 접근을 하기 위해 kernel mode 상에서 선점 불가능하게 작성함으로써 가능했습니다.
하지만 kernel 2.6에 와서는 모든 함수를 재진입 가능하게 작성하였습니다.

선점 가능하다 가능하지 않다는 말은 이렇게 kernel의 구현에 있어서 선점 가능한 코드로 작성되었나 되지 않았나로 구분을 해야지 kernel mode 상에서 interrupt 발생 유무로 판단하는것은 맞지 않습니다.


jika의 이미지

프로세스의 자발적 양보없이 언제든지 커널에게 선점당할수 있다는것을 의미합니다.

라고 말씀하셨는데요..

그런식의 해석은 지나치게 사전적으로 해석하신것이구요..

제가 쓴글의 내용을 조금 살펴보시면 되겠습니다만..

비선점형커널이 비자발적인 상황에서 CPU를 빼았기지 않는것은 아닙니다...

cpu 한개의 시스템에 비선점형 커널 커널이 동작한다고 가정합시다.

무한루프로 동작하는 프로세스를 만들면 이 프로세스에는

자발적으로 CPU를 반납하지 않지만 비선점커널은 다른프로세스로

일정한 규칙(스케줄링정책) 에 의거 CPU자원을 넘깁니다.

그럼 여기까지의 과정에서 과연 선점형 커널과 비선점형 커널에

무슨 차이가 있습니까?

오랜동안 몇가지의 커널 소스들을 직접 분석하고 공부했지만

여기까지 과정에서는 선점형 비선점형 커널간 구분은 의미가 없습니다.

인터럽트 처리 이외에 커널함수로의 재진입을 하는 케이스가 있나 싶습니다.

제 기억엔 없는듯한데...

바로 윗 글에 한해서는 결국 같은이야기를 서로 다르게 했다는 생각도 드는군요..

purluno의 이미지

anfl wrote:
제가 말씀 드린내용은 단순히 스케줄링 정책과 관련된 내용이 아닙니다.
kernel을 구현하는데 있어 코드상에서 선점 가능하게 되어있나 가능하지 않게 되어있나를 말씀드린겁니다.

jika wrote:
비선점형 OS : process 가 cpu 를 양보하지 않는 한, 다른 process 로 context switching 이 일어나지 않음

이말은 좀 틀린 표현입니다.


제가 스케쥴링 이야기를 꺼낸 것은 jika님의 위 말씀에 대해서 cyk님의 글 중 1번의 의미가 스케쥴링 쪽에서의 선점/비선점을 의미하기 때문에 용어가 애매한 것일 뿐 틀린 표현으로 보기 어려움을 말하고자 했던 것입니다. anfl님께서 쓰신 글과는 상관이 없습니다.
linuxgood의 이미지

예전에 들었던 기억이 나는데, 이런거죠.

상황 : 한병의(CPU or Process 라고 가정) 술을 나누어 주는데

- 선점형 : 바텐더가 제어권을 가지고 술을 원하는 사람에게 나누어준다. 만약 그사람이 다운되어도 술은 계속 나누어 줄수 있다.

- 비선점형 : 바텐더가 아니고 1병의 술을 각자가 돌아가면서 따라준다. 이럴경우 술을 가진 1명이 다운되면 다른사람도 덩달아 술을 못마시게 된다는...

이런 이야기 입니다.

Linux는 앞의 것에 해당되지 않을까 합니다.
수고하세요.

anfl의 이미지

Quote:

cpu 한개의 시스템에 비선점형 커널 커널이 동작한다고 가정합시다.

무한루프로 동작하는 프로세스를 만들면 이 프로세스에는

자발적으로 CPU를 반납하지 않지만 비선점커널은 다른프로세스로

일정한 규칙(스케줄링정책) 에 의거 CPU자원을 넘깁니다.

그럼 여기까지의 과정에서 과연 선점형 커널과 비선점형 커널에

무슨 차이가 있습니까?

무언가 큰 오해를 하고 계시군요. linux kernel이 선점형 kernel이다 비선점형 kernel이다라고 말하는 것은 user mode 상의 프로세스의 선점 유무로 판단하는 것은 아닙니다.

linux kernel이 선점형 kernel이다 비선점형 kernel이다라고 말하는 것은 kernel mode 상에서 선점되는가 선점되지 않는가에 따라 판단합니다.

그건 이전에도 말씀드렸듯이 kernel을 이루는 모든 코드가 선점 가능하게 작성되어야만 가능합니다.

무한 루프를 도는 kernel 모듈을 작성하셔서 2.4 kernel과 2.6 kernel에 각각 올려보십시요. 어떠한 현상이 벌어지나...
2.4 kernel은 시스템이 멎어버리는데 반해 선점 옵션으로 컴파일한 2.6 kernel은 insmod한 해당 프로세스만 멈추고 나머지 프로세스는 계속 동작할것입니다.

Quote:

오랜동안 몇가지의 커널 소스들을 직접 분석하고 공부했지만

여기까지 과정에서는 선점형 비선점형 커널간 구분은 의미가 없습니다.

저 역시 리눅스를 포함하여 몇가지 kernel을 분석하였고 또한 1개의 GPOS와 1개의 비상용 RTOS를 개발하였고 그리고 지금은 상용 RTOS를 개발하고 있습니다.
분명히 말씀드리건데 선점형 kernel과 비선점형 kernel간에는 구분이 있습니다.

PS.
죄송합니다. 글을 다쓰고 난후에 보니깐 위에 쓰신 내용 추가되었군요. 저 역시 두분의 의견에 관점의 차이에 의해서 그런것이지 크게 다르지 않음을 말씀드리고 싶습니다.


lovewar의 이미지

제가 현재 보고 있는 문서가 이 주제와 관련이 있을지는 모르겠습니다.

문서는 인쇄를 했는데, 읽는 힘이 약해서 먼지만이 쌓여가고 있습니다.

여기에 보면 3가지로 process를 구분하더군요.

아직 스케줄링하는 부분을 읽지 못했으므로, 여기까지 쓰도록하겠습니다.

Different books on operating systems define a "process" in different ways, starting from "instance of a program in execution" and ending with "that which is produced by clone(2) or fork(2) system calls". Under Linux, there are three kinds of processes:

* the idle thread(s),
* kernel threads,
* user tasks.

-- 덧붙이는 글 --
참고가 되었으면 좋겠습니다.

http://www.faqs.org/docs/kernel_2_4/lki-2.html

채영구의 이미지

 +-- 선점형 OS (linux) ------- 선점형 kernel (kernel 2.6 이후 optional)
 |                       |
 |                       +-- 비선점형 kernel (kernel 2.4)
 |
 +-- 비선점형 OS (windows 3.1)

어떤 분은 상위 트리에서 이야기하고 (손님)
어떤 분은 하위 트리에서 이야기하고 (질문자, jika님, anfl님)
전체 트리에서 잘 말씀하시는 분도 있고 (purluno님)

익명 사용자의 이미지

다들 내공이 대단하십니다. 마침 오늘 아침에 OS concepts 책에서 선접형과 비선점형 부분을 읽었는데.. 아무리 봐도 이상해서 궁금해 하던 찰나에 이 쓰레드를 읽고나서 조금 감이 잡혔네요..

책에서 읽은것을 요약해 보면
---------------------------------
1. Linux 는 user level 프로세스에 한해서만 preempt를 프로세스가 커널 모드에서 돌아가는 동안에는 preempt 당하지 않는다.

2. 리눅스커널은 user-level 코드에 의해 선점되지 않는다는 사실도 기억해야 한다. 커널이 이미 다른 프로세스를 위한 시스템 콜을 실행 중일때, 실시간 프로세스를 위한 인터럽트가 도착하면 그 실시간 프로세스는 현재 실행 중인 시스템 콜이 완료되거나 블록될 때까지 기다려야만 cpu 차지할수 있다.

3. 선점형 커널은 real-time 컴퓨팅을 위해서 쓰이는거 같습니다. 그런데 리눅스 같은 경우, 어떤 프로세스로 문맥교환 하려고 할때 그 프로세스는 system call 을 완료하거나 I/O blocking 이 발생하기를 기다려야 한다고 합니다. 그러면 dispatch 지연이 길어질수 있기 때문에 시스템 호출이 preemptive 되는 것을 허용할 필요가 있습니다.

3-A. 이것을 구현하기 위해서, system call 에 preemption point 를 삽입 하고, 그 호출이 높은 우선순위의 프로세스가 실행할 필요가 있는지 검사하도록 합니다.
만약 더 높은(즉, 더 급하게 처리해야 할 ) 프로세스가 있다면 문맥교환이 이루어 지고나서 system call 을 마저 처리합니다.

3-B. 다른 방법은 커널 전체를 선점가능하도록 하는 것입니다. 커널 자료구조가 꼬이는 것을 방지하기 위해서 동기화 메커니즘을 사용하여 자료구조를 일관되게 보존하면 됩니다.

p.s 저도 2~3년전에 OS,RTOS 수업을 들었고 리눅스 커널도 공부좀 했는데.. 머리가 나빠서 그런지 지금은 하나도 모르겠네요;; 흑

익명 사용자의 이미지

다들 말씀들을 잘 해주시네요...

그런데, 제가 알고 있기로는 Linux Kernel의 경우

Kernel Mode 동작 시점에 Interrupt Handler에의한

Kernel Control Path의 중첩은 얼마든지 일어날 수 있습니다.

즉, 예를 들자면 Kernel Module에서 무한 루프를 돌고 있다고

가정한다면, Context Switching은 결코 일어나지 않겠지만

Interrupt의 처리는 가능하다는 것이지요...

sisbn의 이미지

일단, 스케줄러는 타이머 인터럽트에 의해서 호출이 되는것으로 알고 있습니다.


만약에,

process A에서 fork() 시스템 콜을 수행 도중에,

timer interrupt가 발생을 한 경우,

비선점형인 경우엔, timer interrupt 핸들러는 fork()를 다 마친후에,

수행이 되겠죠?

반면에, 선점형인경우엔, timer 인터럽트 핸들러 처리를 하고, 스케줄링을

해버리게 되면, 일단, 다른 프로세스(process B)로 스위칭이 되고, 아까

process A의 fork()의 수행을 마친후에, process B를 수행을 하게 되는것인

가요??

부족한 부분있으면 조언 부탁드립니다.

jika의 이미지

오늘 하루에만 이쓰레드에 글이 참 많이 달리네요..

질문하신분의 마지막 글에 대한 답변입니다.

유저 프로세스에서 시스템콜 호출한 이후에

시스템콜 수행 도중에 인터럽트가 발생하는 상황을 전재로

선점형 커널인 경우 인터럽트 처리후 시스템콜로 복귀하고

비선점형 커널인 경우에는 일단 시스템콜을 먼저 수행한후에

인터럽트를 처리합니다.

유저모드 프로세스는 시스템콜과 인터럽트의 처리가 모두 끝난후에야만

수행될수 있다는 점은 선점형 비선점형 커널인 경우 모두 같습니다.

주제랑은 좀 동떨어진 이야기지만..

스케줄러의 호출에 관한 이야기를 좀 하자면

커널은 시스템콜이나 인터럽트 처리가 끝나면 스케줄러를 호출할지를 결정하는데...

needresched 라는 플레그를(리눅스의 경우입니다.) 확인해서 플레그가

세팅된 경우에만 스케줄러를 호출합니다.

플레그는 현재 수행중인 최우선순위의 태스크보다 더 급하고 중요한 유저테스크가 새롭게 존재하거나 타임슬라이스가 만료됬을때 세팅됩니다.

이런 이유로 스케줄러가 매 클럭인터럽트 마다 호출되는것은 아닙니다.

물론 그렇게 구현할수도 있겠지만..

클럭인터럽트 루틴은 시스템마다 틀리지만 1/100 초 내지 수만분의 1초마다 발생하기 때문에

클럭인터럽트마다 뭔가 작업을 복잡하게 하면 시스템 오버헤드가 엄청나게 증가합니다.

고로 일반적인 경우 클럭인터럽트 서비스 루틴은 그저 틱 값만 하나 증가시키고 종료됩니다.

타임슬라이스 세팅에 따라서 다르겠지만 10틱이 타임슬라이스로

세팅된 상태라면 클럭인터럽트가 10번 수행될때

스케줄러가 호출되겠지요..

아니 정확하게 말하면 해당 플레그가 세팅되고 결국 스케줄러가

호출된다고 해야겠습니다.

그 사이에 그보다 더 급한일이 있으면 그일을 해야 하기때문에

이러한 약간 복잡해 보이는 방식으로 스케줄링을 처리 합니다.

응답성을 높이기 위해서라고 하면 적당하겠군요...

언제든지 더 중요한 잡이 생겼을때 즉시 수행할수 있도록

최소한의 인터럽트 수행시간을 유지하는것이

커널 관련 프로그래밍의 기초라고 할수 있겠습니다..

forhopes의 이미지

jika wrote:

{비선점형에서 인터럽트와 시스템콜 간에 우선순위를 >= 으로 표시한것은

인터럽트가 시스템콜보다는 우선순위가 높지만 시스템콜 수행도중에는

인터럽트를 처리할수 없기 때문에 >= 으로 표시했습니다.
}

kernel mode에서 인터럽스가 처리가 안 된다면,

cli()와 save_cli()는 왜 불리는거라고 생각하십니까 ? ^^

jika의 이미지

질문인지 딴지인지 의견표시인지는 모르겠습니다....

cli 를 이야기하시는것 보니

인터럽트 디스에이블이 뭔지 몰라서 질문하시는것 같지는 않은데..

제글이 인용되있어서...

제 글이 좀 이상했는지 모르지만

비선점형 커널에서 시스템콜 수행도중에는 인터럽트를 처리할수

없습니다. 시스템콜이 끝나야만 비로써 인터럽트 서비스루틴으로

점프가 가능해집니다....

만약 처리할수 있다고 생각하신다면 논리적으로 설명해주세요...

프리엠션 포인트 없는 시스템콜 루틴에서 cpu 제어권이 어떻게

인터럽트 서비스 루틴으로 넘어가는지 설명해주시면 제가 좀 생각해보겠습니다.

익명 사용자의 이미지

jika wrote:
질문인지 딴지인지 의견표시인지는 모르겠습니다....

cli 를 이야기하시는것 보니

인터럽트 디스에이블이 뭔지 몰라서 질문하시는것 같지는 않은데..

제글이 인용되있어서...

제 글이 좀 이상했는지 모르지만

비선점형 커널에서 시스템콜 수행도중에는 인터럽트를 처리할수

없습니다. 시스템콜이 끝나야만 비로써 인터럽트 서비스루틴으로

점프가 가능해집니다....

만약 처리할수 있다고 생각하신다면 논리적으로 설명해주세요...

프리엠션 포인트 없는 시스템콜 루틴에서 cpu 제어권이 어떻게

인터럽트 서비스 루틴으로 넘어가는지 설명해주시면 제가 좀 생각해보겠습니다.

시스템 콜 수행중에도 (보통 top half 라고 생각하면 되겠지요?)
interrupt 요청이 들어오면 interrupt 처리를 먼저 하게 되어
있습니다. (interrupt라는 이름이 붙여진 이유이기도 합니다.)
그렇기 때문에 bottom half와의 shared data를 접근할 때에는
인터럽트를 off하여 synchronization을 보장합니다.
여기에 대해서는 위의 손님께서 언급하신 내용이 가장 정확한
거 같습니다.

손님 wrote:

그런데, 제가 알고 있기로는 Linux Kernel의 경우

Kernel Mode 동작 시점에 Interrupt Handler에의한

Kernel Control Path의 중첩은 얼마든지 일어날 수 있습니다.

즉, 예를 들자면 Kernel Module에서 무한 루프를 돌고 있다고

가정한다면, Context Switching은 결코 일어나지 않겠지만

Interrupt의 처리는 가능하다는 것이지요...

제가 이해하고 있는 preemptive/non-preemptive 커널의
차이점은, 커널 모드를 수행중에도 스케줄러에 의한
non-voluntary context switching 이 일어날 수 있는가의
여부입니다. non-preemptive 커널의 경우에는, 한 프로세스가
커널 모드로 수행중일 때는 그 프로세스 스스로 sleep하는 경우
외에는 프로세스의 스케줄링이 다시 일어나지 않습니다.

다시 말하면 커널 모드에 있을 경우는 voluntary context
switching 만이 허용됩니다. 즉, priority가 더 높은 프로세스가
있더라도, 만일 어떤 프로세스가 커널 모드에서 수행중이라면,
커널 모드를 수행중이던 낮은 priority의 프로세스의 실행이
끝나기 전에는 (또는 sleep하기 전에는) context switching이
일어나지 않는다는 것입니다.

단, interrupt service routine은 프로세스 context를 가지지
않기 때문에 물론 수행은 됩니다. 그러나 interrupt 처리 후에는
다시 이전에 실행되던 프로세스로 돌아오게 되죠.

즉 앞에서 나온 'non-preemptive 커널에서, 무한 루프를 도는
커널 모듈'의 경우에는, interrupt service routine은 물론
수행될 수 있겠지만, 그 커널 모듈의 루틴을 실행하는 프로세스
외에 다른 프로세스로 context switching 을 일어나게 할 방법이
없기 때문에, 시스템이 죽었다고 말할 수 있는 것입니다.

preemptive 커널이라면 시간이 지남에 따라 무한루프를 도는
프로세스의 priority가 낮아질 것이고, 더 높은 priority를 가진
프로세스에 의해 '선점(preempt)' 될 것입니다. (context switch
가 일어납니다.) 따라서 시스템은 다른 일을 계속 수행할 수 있겠죠.

forhopes의 이미지

jika님.
딴지를 걸려고 한건 아니구요.
그냥 의견표시였습니다.

그리고, jika님뿐만 아니라 많은 분들이

kernel mode에서는 interrupt가 처리되지 않는다는 커다란 논리적 오류에 빠져 있는 듯해서,

kernel mode에서 interrupt가 우선적으로 처리된다는 증거를 가장 손쉽게 증명할 수 있는 함수인

cli()를 언급했습니다.

바로 위에 쓰신 손님이 가장 잘 정리해주신거 같습니다.

jika의 이미지

forhopes 님 "kernel mode에서는 interrupt가 처리되지 않는다는 "

제글 어디에 저런 말이 있나요..

제글 표현 하나하나 신경써서 읽어주시기 부탁드립니다.

시스템콜 "수행도중" 에 인터럽트를 처리할수 없다 라고

분명하게 그것도 여러번 적시 했습니다.

커널은 분명 인터럽트처리를 최 우선으로 처리해야 합니다.

당연한 이야기 이죠..

그걸 몰라서 장대한 댓글들을 달고 있는게 아니라는걸 알아주셨음 합니다.

그리고 위에 윗글에서 손님 아이디 사용하시는분은

비자발적 컨텍스트 스위치 이야기를 하셨는데요..

전체적으로 틀린 이야기 입니다.

시분할 시스템에서 커널모드에서 비자발적 컨택스트 스위치가 일어나지 않는 경우는 없습니다.

유저프로세스의 스케줄링과 선점형 커널 비선점형 커널 구분에는 영향이 없다는

설명 누차 했는데..

선점형 커널의 프리엠션 포인트 관련된 코드들을 좀 살펴 보시면 명확해지리라 생각합니다.

아울러 비선점형 커널에서 커널모드시 비자발적 컨텍스트가 일어나지 않는

커널을 지적해주시면 좋겠습니다.

스케줄링 정책과 선점 비선점형 커널의 구분은 연관이 없습니다.

forhopes의 이미지

jika님!

정확하게 기술하신 내용이 이해가 잘 안가서,

질문 좀 하겠습니다.

"일반적인 비선점형 커널은 일단 시스템콜 수행도중에는

인터럽트처리루틴으로 빠져나가지 않고 시스템콜 수행후에

인터럽트를 처리합니다. "

이렇게 글을 쓰셨는데,

이 말씀의 뜻은,

시스템콜의 시작과 끝 사이에는 인터럽트가 처리가 안 되고,

유저모드로 돌아간 후에 인터럽트가 처리된다는 뜻인가요 ?

시스템콜이라는 것은 유저모드에서 커널모드로 들어가는 것이고,

시스템콜의 끝은 커널모드에서 유저모드로 돌아간다는 뜻으로 쓰신 건가요 ?

정확한 의미를 알려주시면 의견 교환에 도움이 될 것같습니다.

그럼.

jika의 이미지

비슷한 이야기를 자주 반복하려다 보니까 본의 아니게 어조가 좀 강해지고 격해지는것 같습니다.

차분한 마음으로 다시한번...

forhopes 님..

비선점형 커널에서..유저모드에서 인터럽트를 처리하는것이 아니고요.

시스템콜을 처리하고 리턴프럼 시스템콜 할때 인터럽트가 들어와 있는지 확인해서 수행합니다.

(영어를 쓰는게 아니라 함수이름을 그냥 쓰는거니까 재수없게 생각은 말아주세요.. )

다시 말해서 시스템콜 수행후 유저모드로 돌아가기 직전에 수행한다고 하면 맞겠습니다.

익명 사용자의 이미지

선점형OS, 비선점형OS와 선점형Kernel, 비선점형Kernel 사이에서 용어혼란이 있는듯 싶군요.

forhopes의 이미지

저는 preemptive/non-preemptive kernel 이야기를,

jika님은 preemptive/non-preemptive OS 이야기를 하시는 듯합니다.

Linux 2.4까지는 non-preemptive kernel 이며 preemptive OS입니다.

Linux 2.6은 preemptive kernel 이며 preemptive OS입니다.

여기까지 맞나요 ?

linux 커널이 시스템콜에서 리턴 될 때만 인터럽트가 처리된다면,

cli()를 커널코드 작성시 사용할 이유가 없어집니다.

하지만, 실제로 linux kernel 소스를 보면 cli()를 무진장 씁니다.

cli()는 인터럽트 처리를 막도록 하는 함수입니다.

즉, 리눅스 커널에서는 강제가 인터럽트를 막지 않는한 시스템콜 처리중에도 처리된다는 뜻입니다.

저의 의견은 이러합니다.

jika의 이미지

조금만 노력하시면 자신의 의견을 검증하실수 있으실텐데요..

소스인사이트 같은걸로 리눅스 소스 검색해보면 님 말씀처럼

cli( 찿으면 수백개 나옵니다.

그중에 시스템콜이 있는지 비교해보세요..

시스템콜은 아래 문서에 요약되어있습니다.

http//tiger.la.asu.edu/Quick_Ref/Linux_Syscall_quickref.pdf

솔찍히 조금 짜증스럽군요..

익명 사용자의 이미지

딴지는 아니고요.

forhopes wrote:

...

Linux 2.6은 preemptive kernel 이며 preemptive OS입니다.
...

보다 정확히,
Linux 2.6은 Non-preemptive kernel 이지만, 커널 커피그레이션 설정을 통해 커널 컴파일시 선택적으로 preemptive kernel 로 만들수 있는 preemptive OS입니다.

익명 사용자의 이미지

jika wrote:

...
스케줄링 정책과 선점 비선점형 커널의 구분은 연관이 없습니다.

Scheduling Policy 및 Algorithms에서 preemtive, non-preemtive를 빼버리면, 전산학(특히, 운영체제)의 많은 부분을 새로 써야 할것 같은데요?

jika의 이미지

선점형 커널이라는 단어와 선점형 OS 라는 단어를 구분해서 전체를 정리해주시려는 분들이 많군요..

두 용어를 구분하는건 제가 생각하기에는 적절치 않은듯 합니다.

굳이 구분하자면 선점형 커널 혹은 OS VS 선점형 멀티테스킹 혹은 선점형 스케줄링으로 구분해야 합니다.

두가지는 분명 다른 개념입니다.

후자의 개념 즉 선점형 멀티테스킹( 선점형 스케줄링은 ) 이라는 용어는

10~20년 전에 만들어진 개념이죠

당시에 시분할 시스템이 처음 도입되기 시작할때쯤 아마 이런 구분이 필요했을듯도 합니다.

하지만 현재 사용되는 임베디드 운영체제같은 자그만 OS 도 전부 다 시분할 시스템입니다.

비선점형 멀티테스킹을 한다는것 자체가 스케줄링을 거의 포기한것이나 다름없는데다가

응답성을 전혀 기대할수 없기 때문입니다. 수행되는 테스크의 수도 지나치게 많은 현실이구요..

그래서 현용하는 거의 전부의 운영체제는 시분할 시스템입니다.

다시 말해서 선점형 멀티테스킹 혹은 선점형 스케줄링을 말합니다.

고로 비선점형 멀티테스킹이니 비선점형 스케줄링이니 하는말은

50~60대의 나이드신 교수님이나 옜날책 가지고 컴퓨터 역사를 공부하는 학생들 한테나

의미가 있는 말이지 쓸모가 거의 없어진 개념입니다.

이 쓰레드 처음 만드신 질문자도 역시 이 개념을 기반으로 질문하신게 아닙니다.

여기에 올라오는 글들은 많은 분들이 오랜 시간동안 참고로 합니다.

저역시 이곳에서 좋은 정보를 많이 얻어가구요...

답글중에 전혀 사실과 다른내용이 있어서 정정하려 수차례 글들을 남기는데..

이과정에 좀 제가 잘난척한 꼴이 됬습니다.

죄송합니다.

여기 쓸만한 내용은 아니지만 커널관련 개발자가 이땅에서 격는 어려움이

어떤건지 아마 모르시는 분들이 많을겁니다.

sangwoo의 이미지

로그인을 깜박하고 2005년8월11일 2:45 에 손님으로
글을 썼던 sangwoo입니다. :-)
jika님이 쓰신 글을 인용해서 이야기를 나누는 편이
명확할 거 같아서 그렇게 하겠습니다. 양해부탁드립니다.

jika wrote:

forhopes 님 "kernel mode에서는 interrupt가 처리되지 않는다는 "

제글 어디에 저런 말이 있나요..

제글 표현 하나하나 신경써서 읽어주시기 부탁드립니다.

시스템콜 "수행도중" 에 인터럽트를 처리할수 없다 라고

분명하게 그것도 여러번 적시 했습니다.

커널은 분명 인터럽트처리를 최 우선으로 처리해야 합니다.

당연한 이야기 이죠..


시스템콜 수행도중이라면 당연히 커널 모드입니다.
프로세스 컨텍스트이고, 커널 모드죠.

jika wrote:
조금만 노력하시면 자신의 의견을 검증하실수 있으실텐데요..

소스인사이트 같은걸로 리눅스 소스 검색해보면 님 말씀처럼

cli( ㅤㅊㅏㅊ으면 수백개 나옵니다.

그중에 시스템콜이 있는지 비교해보세요..

cli가 system call 구현 안에 없는 이유는, interrupt가
일어났을 때, interrupt handler에 의해 수정되는 data
structure가 없기 때문이라고 생각됩니다만.

리눅스 커널 2.4.29의 sysinfo() syscall의 구현을
보시면 cli()가 있음을 알 수 있습니다.
그리고 수많은 device driver의 character device의 ioctl
루틴 역시 syscall의 구현이고, 아시다시피 수많은
cli()/sti()가 있습니다.

(참고로, 2.5부터는 SMP 향상을 위해 cli()/sti()는
사양길로 접어들었고, 다른 인터페이스가 권장되고
있으니, 논외로 하겠습니다. 잘 모르기도 하고.. :oops:
이 주제에 대해서는
http://imada.sdu.dk/~svalle/courses/dm14-2005/assignments/man/cli-sti-removal.txt
를 보시는 것도 좋을 듯 합니다.)

그리고 보통 context switching이라고 할 때는
프로세스(커널 쓰레드 포함)간의 context 를 언급하는
경우가 많습니다. 리눅스처럼 interrupt가 process context
를 가지지 않는 경우에, interrupt context로 바뀌는 경우는
context switching이라고는 하지 않는 거 같던데요.

(참고로 FreeBSD 5이후부터는 interrupt가 process
context를 가집니다. spl()/splx()
(interrupt를 끄고 켜는 겁니다. 리눅스의 cli()/sti()와 비슷)
콜들을 없애고, mutex로만 synchronization을 통일하기 위해서입니다.
synchronization의 간편화/단일화라는 측면에서는
FreeBSD가 Linux보다 앞서 있다고 생각합니다. :-)
잠깐 딴소리였구요.

Quote:

그리고 위에 윗글에서 손님 아이디 사용하시는분은

비자발적 컨텍스트 스위치 이야기를 하셨는데요..

전체적으로 틀린 이야기 입니다.

시분할 시스템에서 커널모드에서 비자발적 컨택스트 스위치가 일어나지 않는 경우는 없습니다.

유저프로세스의 스케줄링과 선점형 커널 비선점형 커널 구분에는 영향이 없다는

설명 누차 했는데..


non-preemptive커널에 대한 논의에 약간 부연을 하면,
제가 깜박하고 있던 부분은 interrupt 루틴이 끝나고 나서
프로세스들이 reschedule된다는 거였습니다. 이 부분을
지적해주신 점 감사드립니다. :-)

하지만 만일 이전에 interrupt되었던 프로세스가
커널 모드에 있었다면, 그 프로세스가 우선순위가
(당연히) 가장 높기 때문에 다시 스케줄됩니다.
커널모드에서 무한루프를 돌고 있었고, non-preemptive
커널이라면 당연히 이 루프를 빠져 나갈 방법이 없겠죠.

=======

원래 질문을 하셨던 분께...
User preemption, Kernel preemption은 구분되는
것이구요, 단지 '리눅스가 선점형인가 아닌가?'라는
질문은 여러 가지로 해석될 여지가 많습니다.
이 주제에 대해서는
Robert Love씨가 쓴 "LInux Kernel Development (2nd ed.)"
의 chapter 4의 user preemption과 kernel preemption항목을
보시는 것이 가장 명확하게 정리가 될 것 같습니다.
Robert Love씨가 Linux (2.6)의 Fully-preemptive kernel
을 구현한 사람이니까요. :-)

----
Let's shut up and code.

jika의 이미지

차분해지려고 했다가 다시 흥분했다가 오늘 정신병자된 기분이네요..

"시스템콜 수행중에는 인터럽트를 처리할수 없다"
"커널모드에서는 인터럽트를 처리할수 없다"

이 두 말에 차이를 이해 못하시면 대화가 곤란합니다.
커널 함수들 중에서 시스템콜이 차지하는 비중은 아주 작습니다.

인터럽트 헨들러와 시스템 콜을 혼용 하시는데요..

인터럽트 헨들러도 넓은 의미에서는 일종의

시스템콜이라고 할수도 있겠지만 상위에서 하위로 불러드린다는 개념에서는...

제가 두단어를 동시에 사용해왔기 때문에 두가지는 다른 개념으로

이해해 주셔야 합니다.

sysinfo() 에서 cli() 호출 한다고 하시는데 제가 그버전은 없어서

확인을 못해보지만 제가 확인한 커널에서는 2.6.11.10 에서는

cli() 호출하는 구문도 없고 그에 대응하는 다른 구문도 없습니다.

물론 님이 확인하신게 잘못됬다 이야기는 아니구요.

개인적으로 리눅스소스에서 불필요한 락이나 함수 호출을 수도 없이 봤기 때문에

저는 그정도로 이해하고 있습니다만 이 부분 가지고 님을 이해해시켜 드리지는 못할듯 합니다.

마지막으로

"커널 모드에 있었다면, 그 프로세스가 우선순위가
(당연히) 가장 높기 때문에 다시 스케줄됩니다. "

이부분도 틀린 말입니다. 아니 그렇게 구현하면 그렇게 될수 있겠지만

우선 리눅스가 그렇치 않고 다른 운영체제라도 그렇게 만들어서 좋을 이유가 없습니다.

정확하게 설명하면 커널 모드에 들어와 있는 동안에

더 중요하고 급한놈이 들어왔다면 니드 리스케드라는 프레그가

세팅 되어있을겁니다.

그런 경우를 대비해서 커널모드에서 벗어날때는 해당프레그를 확인해서

더 중요하고 급한놈이 생겼다면 해당 테스크로 컨텍스트 스위치 하고

그렇치 않다면 이전 테스크로 컨텍스트 스위치 합니다.

위에 이미 한번 설명한 내용입니다.

이 쓰레드에서 통용될수 있는 가장 핵심적인 단어는

응답성이네요... 쓰레드 답글 올라오는 속도도 빠르구요

sangwoo의 이미지

이 글이 이 쓰레드에서의 저의 마지막 글입니다.

저는 원래 글로 누구를 이긴다거나 그런 생각 없이
단지 하신 말씀이 제가 알고 있던/있는것과 달라서
확인차 글을 남긴 것입니다. 어차피 이건 가치관이
들어가는 류의 논쟁도 아니고, 사실관계가 명확한
이야기이니 기분상해 하실 필요는 없을 것 같습니다.
저도 이 쓰레드 읽으면서 많이 배웠구요.

제가 말씀드린 것 이상으로 저는 제 생각을 설명드릴
능력이 없습니다. 제 능력의 부족 탓이겠지요. 아까
언급했던 Robert Love씨의 책에서 두 섹션만 발췌해서
번역해 적어 볼까 합니다.
(저작권 관련 문제가 있으면, 통지해주시면 삭제하도록
하겠습니다.)

Chapter 4. Process scheduling
o User Preemption
커널이 user-space로 return하려고 할 때
need_resched 가 세팅되어 있으면 스케줄러가 실행(invoke)
되고, 이때를 User preemption이 일어난다고 말한다.
커널이 user-space로 return하고 있다는 것은 커널의
상태가 (자료구조나 뭐 등등..) 안전하고 고요하다는
것이다. 다시 말하면, 현재의 task (프로세스나 thread에
해당하는 entity를 linux에서는 task라고 하더군요?)를
계속 수행하기에 안전한 상황이라는 것은 다른 task를
골라서 실행하는데도 안전하다는 것이다. 결과적으로,
커널이 user-space로 return하려고 준비할 때는, 그게
interrupt였든 system call이었든 간에 need_resched의
값이 체크된다. 그리고 만일 need_resched가 체크되어
있다면, 스케줄러는 새로운 프로세스를 골라서 실행한다.
<중략>
간단히 말해서, user preemption은
- system call로부터 user-space로 return할 때
- interrupt handler로부터 user-space로 return할 때
일어날 수 있다.

o Kernel Preemption
Linux 커널은 대부분의 다른 Unix variant를 비롯한
많은 다른 운영체제와는 달리 fully preemptive kernel이다.
non-preemptive 커널에서는 커널 코드는
수행이 완료될 때까지 실행된다.
(kernel code runs until
completion)
따라서, 스케줄러는 어떤 task가 커널 모드에 있을 때는
reschedule을 수행할 수가 없다.
커널 코드는 선점적이 아니라, 협동적으로 스케쥴된다.

(kernel code is scheduled cooperatively, not preemptively)
커널 코드는 그 코드가 끝날 때까지(즉, user-space로
return할 때까지) 또는, 명시적으로 block할 때까지
(제가 이전에 언급했던 voluntary context switching에
해당합니다.) 실행된다.
그러나 버전 2.6에 이르러서 linux kernel은 선점식으로
되었다. (became preemptive) 이제는 커널이 reschedule
하기 안전한 상태이기만 하면 어떤 task를
어느 시점에서도
preempt할 수 있다.
그러면, 과연 언제가 reschedule하기 안전한 시점인가?
커널은 어떤 task가 lock을 hold하지 않는 한
커널에서 실행되는 그 task를 preempt 할 수 있다.

<중략>
Kernel preemption은
- 인터럽트 핸들러가 exit하고, kernel-space로 return하기 직전
- 커널 코드가 다시 preemptible 해 졌을 때
- 커널에서 실행되고 있는(== 커널 모드의) task가 schedule()을 call했을 때
- 커널에서 실행되고 있는 task가 block할 때 (결국 schedule()을 call하도록 된다.)
이런 경우에 일어날 수 있다.

User preemption과 Kernel preemption을 혼동하고
계신 분이 누구신지 잘 생각해 보셨으면 좋겠습니다.

----
Let's shut up and code.

jika의 이미지

윗분 인용하신책내용중에 첫번체 페러그렙은 제가 설명한 부분과 다르지 않은데

두번째 페러그렙은 제가 이 쓰레드에서 계속 해온 이야기와는 다른 이야기네요.

번역상의 문제인지 제 이해력이 부족한건지 모르겠습니다만..

실시간 프로세스를 제외하고 모든 유저프로세스는 커널 프로세스보다

우선순위가 낮습니다. 리눅스를 포함해서 대부분의 운영체제가 그렇쵸..

당연한 이야기 아닌가요?

그런데 커널모드에서 커널 프로세스 수행이 끝나지 않은 상황에서

일정 프리엠션 포인트마다 확인해서 유저프로세스로의 컨텍스트 스위치가 어떻게 일어날수 있다는건지 모르겠습니다.

그렇게 해서 얻을수 있는 이익도 없구요..

원칙적으로 인터럽트 수행이 밀리는것을 방지하기 위해서

프리엠션 포인트마다 인터럽트 수행여부를 확인하는것이 운영체제의

응답성 증대를 위한 페러다임에 부합하는 개념이라고 생각합니다.

더이상 이부분가지고 논쟁하고 싶지는 않구요..

윗분이 인용하신 두번째 페러그레프는 제가 잘못 이해한거라 생각하고 다른분들 판단에 맞기겠습니다.

본의 아니게 논쟁 비슷하게 되버렸는데요..

우리가 하는 일이 크게 보면 공대를 졸업해서 IT 관련업종에 종사하지만

모두가 다 똑같은 분야에서 메이저리티를 가지고 있는것은 아닙니다.

대학원 실험실에서도 그리고 지금 종사하는 회사의 연구소에서도..

수많은 사람이 있지만 다 서로 서로가 하는일이 다르고 잘하는 일이 다릅니다.

80여명정도 되는 작은규모의 연구소인데 서로가 서로 하는 일에 세미나라도

해주려 치면 크게 크게 넘어가지 않는한 세세하게 들어가면 이해시키기가 어려운 경우가 많습니다.

제가 커널 관련분야에 종사하다보니 하드웨어 하는 분들이나 제 윗단에서

작업 하는 분들하고 이야기 나눌때 답답한면이 많은데요..

물론 그분들도 저를 이해시키려고 힘들게 노력하십니다만...

가장 크게 문제가 되는게 책이나 문서를 보고 공부하는 경우와

소스코드를 분석하면서 공부를 하는 경우에서 오는 차이입니다.

누구나 자기의 주전공분야? 에서는 코드에 기초해서 공부하고 이해하고

내용을 만들어 나갑니다.

하지만 그 주변분야에 관해서는 책이나 문서로 채우지요..

잘못된 책이나 문서를 참조해서 문제가 되는 경우도 있겠지만

더 많은 경우에 책이나 문서를 만든사람의 뉘앙스와 그 책을 읽고 이해하는사람이 느끼는

뉘앙스가 다르다는 겁니다. 그런데도 불구하고 사람들은 문서와 책에서 본내용을 맹신 하거든요..

이쓰레드에 몇가지 잘못된 인용들이 그런 경우라고 생각합니다.

다행이 윗분이 인용하신 책은 용어사용이나 내용을 보아 좋은 책이라 생각됩니다만

그래도 역시 코드를 살펴보면서 이해하는것 하고는 다를수 있습니다.

물론 제가 모든운영체제의 소스코드를 다 외는것도 아니고 합니다만

이런 이야기를 하는 이유는 두가지 경우에 차이점이 분명이 있다는걸 말씀드리고자 함 입니다.

본의 아니게 남이 써놓은 이글 저글들에서 틀린 부분만 잔뜩 지적하고 갑니다만

서로 서로가 갖은 전문 지식을 서로나눈다는 본래 취지에서 크게 벗어난것은

아니니 너그러이 이해바랍니다.

sangwoo의 이미지

본의아니게 거짓말을 한 셈이 되었습니다만, 시간이 갑자기
좀 생겨서 글을 올립니다. :-)

jika님의 글 잘 읽어 보았습니다. 좋은 말씀 감사드리구요.
저는 사실 Linux 커널을 살펴본 경험은 별로 없습니다만,
FreeBSD의 내부 구조에 대한 paper들과 문서들은 꽤 많이
읽어 보았습니다. 그렇다고 우려하신 것처럼 문서만 읽은
것은 아니구요, 이전에 다니던 회사에서 커널 프로그래밍의
경험도 있고, 현재에도 취미삼아서 디지틀 카메라를 위한
FreeBSD용 디바이스 드라이버를 작성중입니다. 제가
써 놓은 글들을 몇개 읽어 보시면 아시겠지만, 저도
코드를 보고 쓰는 사람입니다. :-)

어쨌든 제가 언급한 Robert Love의 책은 한번 꼭 읽어
보시길 권하고 싶습니다. 읽기 쉽게 쓰여져 있고, 여느
커널 책처럼 어이없이 두껍지도 않고요.. 그리고 pseudo code
가 아닌 실제 2.6.X의 소스를 갖고 설명을 합니다.

그리고 마지막으로 논의하던 내용 중 하나만 언급하자면,
Bach의 책을 비롯한 여러 OS나 컴퓨터구조 서적에도
언급되어 있듯이 (분명 인텔 CPU매뉴얼에도 있으리라
생각됩니다. 이건 집에가서 제가 확인하도록 하겠습니다.)
인터럽트 서비스 루틴은 절대로 시스템 콜 막바지까지
밀려서, 모았다가 실행되는 게 아니라, 발생 즉시 곧바로
실행됩니다. 그리고는 원래 컨텍스트로 복귀합니다.

FreeBSD 4->5로의 전환시에 성능이 엄청 떨어졌던 게
바로 이 이유 때문입니다. 자세한 내용은 다음 기회에
말씀드리기로 하구요. 어쨌든 이것만 다시 한번 확인해
주셨으면 좋겠습니다.

좋은 밤 보내세요. :D

----
Let's shut up and code.

jika의 이미지

"인터럽트는 발생 즉시 수행한다"

이런 문장 아마 수도 없이 많은책에 언급되어있을겁니다.

모두들 그렇게 믿죠.. 우상처럼...

그리고 그렇게 틀린말도 아닙니다.

하지만 개발자 입장에서 봤을때 저 말은 레절루션이 아주 낮은 상태에서만

맞는말이 됩니다.

보다 높은 레절루션에서 생각하면 저말은 아주 모호한 말이 됩니다.

전제가 아주 많이 붙어야 정확한 말이 되는거죠.

지금 잠시 언듯 생각해봐도 두세줄 이상 전제조건을 달아야만

정확한 표현이됩니다.

정확하게 이해하려면 특정 인터럽트 서비스 루틴을 콜하는 구문을 다 찾아서 살펴보면 됩니다.

좀 양은 많겠습니다만 여러가지 툴들을 이용하면 별로 어렵지 않게 찾을수 있습니다.

인터럽트 서비스 루틴이 무슨 전지전능한 신도 아니고 코드에서 콜하지 않았는데 수행될리 없습니다.

커널은 하드웨어를 쥐고 유저모드의 프로세스에 cpu 타임을 배정합니다.

인터럽트중에 비교적 우선순위가 높은 클럭인터럽트 수행을 (수정하지 않았다면 1/100초) 커널은 수행합니다.

클럭인터럽트 수행이후에 남는 CPU시간을 커널은 유저모드 프로세스에 할당합니다.

그런의미에서 인터럽트는 클럭인터럽트 발생주기보다 빠른 시간안에 반응 할수 없습니다..

여기에 사용되는 개념이 클럭인터럽트 레절루션입니다.

실시간 응답이 중요한 시스템에서는 클럭인터럽트 발생주기를 짧게해서

응답성을 높입니다.

CPU 성능에 따러서 다릅니다만 리눅스같이 덩치 큰 커널은 몇만분의 1초

이상 해상도를 높이면 클럽인터럽트를 오버헤드 때문에 시스템이 동작하지 않습니다.

클럭인터럽트를 수행하는 도중에 또 클럭인터럽트를 발생해야 하는 시점이 되서

결국 클럭인터럽트를 수행하지 못하고 까먹게 되는거죠..

덩치가 좀 작은 커널인 경우에는 수십만분의 1초 까지도 해상도를 높일수 있습니다.

그냥 제가 논문 쓰던때가 생각이 나서 끄적여 봅니다.

익명 사용자의 이미지

* preemption이란, 강력한 절대자가 있어서( 그 무엇보다 권위, 우선순위가 높은), CPU를 내놓지 않아도 강제로 방빼게 하는 것을 의미합니다. 이와 상대적인 것을 cooperative 스케쥴링(리눅스 2.4의 커널만 봤을때, 유저프로세스말고)이라고 부릅니다.

* preemption은 실시간 운영체제의 스케쥴링에서는 필수적인 요소입니다. 그러나, preemption을 구현했다고 실시간 운영체제가 되는 것는 아닙니다. 단지, preemption은 실시간 스케쥴링 전략을 구현하는 도구중 하나일뿐.

* 구지 실시간운영체제까지 갈필요없이, 운영체제 fundamental 수준에서 preemption은 또 다른 의미로 설명할 수 있습니다. 바로 데드락이 발생할 필요조건인데요. 아래 A,B,C,D가 A and B and C and D라는 얘기지요.
A. mutual exclusion
B. hold and wait
C. non-preemption
D. circular wait
데드락을 발생하지 않게 하려면?
이중 하나만 깨면 됩니다. 즉, 하나만 false로 만들면 deadlock은 절대로 발생하지 않는다는 것이지요. 이중 Not C는 preemption이 되겠군요. 특정 user process에서 무한루프에 빠졌다고 해도 돌 수 있는 것은 granularity를 높게 봐서 스케쥴링 단위를 커널(K), U1, U2,...Un으로 볼때, 임의의 Ui가 CPU를 점유하고 있을때, K가 이를 Preemption할 수 있다면 시스템은 무한루프/데드락으로 볼 수 없겠습니다. 그러나 K가 무한루프/데드락에 빠졌다면?...그리고, 이 일이 빈번할 수 있다면? 이런 커널이 있는가? 제가 보기에는 리눅스(2.4, 모듈들..!)가 딱이었습니다.

* 개인적으로 리눅스( 2.6.X)가 커널 레벨에 preemtive scheduling을 구현한 이유는 리얼타임시스템을 목표한다기 보다는, 커널모듈(디바이스 드라이버)의 오픈시스템 추구로 인한 부작용을 최소화하기 위함이라고 봅니다. 물론, 리눅스에 기반한(그러나, 손을 좀 많이 보는....) 실시간 운영체제들도 여럿 있고,
(비/실시간)마이크로커널, (비/실시간)나노커널등에서도 리눅스를 자신의 고유커널에 포팅하고자 한 노력들이 많이 있었습니다.

익명 사용자의 이미지

인터럽트에 대해 많이 아시는데, 그럼 다음을 정리해 주시지요.
1. S/W Interrupt
2. H/W Interrupt
- maskable interrupt
- non-maskable interrupt
3. Exception
- trap
- fault
- abort
4. defered interrupt

chaos4chaos의 이미지

jika 님 말씀에 수긍이 갑니다.

실제로 시스템 클록의 레졸루션은 대단히 낮지 않나요...

일반 오에수 교재에서 언급하는 말들은 이상적인 가정,

즉, 인터럽트의 발생 시점을 아날로그적인 해상도로 간주했을 때 이야기인것 같습니다.

시스템 클록의 레졸루션 한계로 인하여 인터럽트의 중첩 및 대기는 필수적으로 발생한다고 생각합니다...

FOREVER_Ch@oS

chaos4chaos의 이미지

아참 그리고 이 이야기는

제 생각이 아니고, advanced operating system concepts에서 나온 이야기 입니다.

거시기 실바스까츠가 쓴 책말입니다.

정확히 인터럽트의 대기에 관해서는 언급이 없지만, 시스템 클록의 낮은 해상도는 명확히 문제삼고 있습니다.

FOREVER_Ch@oS

chaos4chaos의 이미지

그리고, 이 스레드에서 정말 많은 걸 배웠쓰미다..

특히 클럭 레졸루션에 관한 jika 님 설명은 제가 도무지 찾을 엄두를 못내고 있었는데... 너무 쉽게 설명해 주셔서... 감사드립니다..

FOREVER_Ch@oS

hwandori의 이미지

정말 내공들이..^^; 많은걸 배우고 갑니다...

전 공부가 부족하지만 제가 알고있는건 sangwoo님 의견이랑 같긴 하네요..

익명 사용자의 이미지

*주제랑 관련없지만, 클락뿐 아니라, 네트워크 디바이스(Giga....)에서도 유사한 문제가 있습니다. 이로 인해 인터럽트 대신 폴링이 그 전략으로 가기 시작한지 어언 10여년입니다. 리눅스도 이를 최근(?)에는 채택한것으로 알고 있습니다.

익명 사용자의 이미지

interrupt가 바로 실행되지 않는다면,

polling이지 그게 interrupt입니까 ?

tiffang의 이미지

맞습니다.. 누군가 시스템 콜 중에 interrupt handler 는 수행되지 않는 다고 말했던 것 같군요..

sangwoo의 이미지

또 약속을 깨고 다시 씁니다. 죄송합니다. (__)

jika wrote:

인터럽트 서비스 루틴이 무슨 전지전능한 신도 아니고 코드에서 콜하지 않았는데 수행될리 없습니다.

제가 아는한 Interrupt-driven 하드웨어 (x86등)에서는
명시적으로 커널이 interrupt service routine을 call하지
않습니다. 다만, 부팅 초기에 interrupt handler를 설정해
둘 뿐이죠. 그리고 해당 하드웨어가 interrupt를 보내오면
CPU는 현재 컨텍스트에 transparent하게 interrupt
service routine으로 점프하는 걸로 알고 있습니다.
(interrupt handler와 interrupt service routine은 모두
같은 뜻입니다.)

Quote:

커널은 하드웨어를 쥐고 유저모드의 프로세스에 cpu 타임을 배정합니다.

인터럽트중에 비교적 우선순위가 높은 클럭인터럽트 수행을 (수정하지 않았다면 1/100초) 커널은 수행합니다.

클럭인터럽트 수행이후에 남는 CPU시간을 커널은 유저모드 프로세스에 할당합니다.

그런의미에서 인터럽트는 클럭인터럽트 발생주기보다 빠른 시간안에 반응 할수 없습니다..


??? 잘 이해가 안되는데, 그렇다면 clock interrupt 이외의
다른 interrupt들의 service routine은 clock interrupt
service routine에서 call한단 말씀이신가요?

만일 위의 내용이 사실이라면
1. 어째서 그게 인터럽트 메커니즘이겠습니까? polling이죠 :-)
2. Clock interrupt routine은 누가 call 해 줄 수 있을까요?
3. Interrupt masking에 의한 interrupt의 loss라는 개념
자체가 필요가 없어지지 않습니까? 어쨌든 모았다가
한번에 처리하면 되는데..

clock interrupt도 network이나 다른 device와 같은
인터럽트일 뿐입니다. timer device가 보내오는
(물론 interrupt priority는 매우 높고, device마다 다르죠.)

Quote:

여기에 사용되는 개념이 클럭인터럽트 레절루션입니다.

실시간 응답이 중요한 시스템에서는 클럭인터럽트 발생주기를 짧게해서

응답성을 높입니다.


Clock interrupt resolution을 높임으로 해서 얻는 효과는
스케줄링을 더 자주 이루어지게 하는 것입니다. 물론
high-priority *procss*의 응답성이 높아지겠죠.
www.cs.princeton.edu/courses/archive/fall03/cs518/papers/clock.ps
를 보셔도 좋겠습니다. (google 만세!)
그러나 이것은 interrupt의 응답성을 높이는 것과는
상관이 없습니다.

참고로, clock interrupt resolution이 너무 높으면
시스템이 작동하지 않는 이유는, 더 낮은 priority의
interrupt service routine (네트워크나 ata 등등..)
의 interrupt를 실행할 시간이 없어지기 때문입니다.
계속해서 clock interrupt를 처리해야 하기 때문이죠.
interrupt driven arch의 숙명인 livelock으로 보시면
되겠습니다.

Quote:

CPU 성능에 따러서 다릅니다만 리눅스같이 덩치 큰 커널은 몇만분의 1초

이상 해상도를 높이면 클럽인터럽트를 오버헤드 때문에 시스템이 동작하지 않습니다.

클럭인터럽트를 수행하는 도중에 또 클럭인터럽트를 발생해야 하는 시점이 되서

결국 클럭인터럽트를 수행하지 못하고 까먹게 되는거죠..

덩치가 좀 작은 커널인 경우에는 수십만분의 1초 까지도 해상도를 높일수 있습니다.

그냥 제가 논문 쓰던때가 생각이 나서 끄적여 봅니다.


FreeBSD는 작년인가 재작년에 clock interrupt를 1000Hz
로 높였습니다. 펜티엄 I 200MHz 정도만 되어도
1000Hz로 작동시키는데 아무 문제가 없다고 하더군요.
(그 이전에는 말씀하신대로 100Hz였습니다.)
http://groups.google.co.kr/group/mailing.freebsd.hackers/browse_frm/thread/411fda864396da60/476105ade0153606?tvc=1#476105ade0153606
제 기억에는 위의 쓰레드 이후 얼마 지나지 않아서
-CURRENT에서 1000Hz가 기본값이 되었습니다.
Linux도 비슷한 관련글을 보긴 했었는데.. 출처는
기억이 잘 나질 않는군요. (확인해 보니 2.6으로 넘어오면서
1000Hz가 디폴트가 된 것 같습니다.)

----
Let's shut up and code.

익명 사용자의 이미지

sangwoo님 말씀에 몰표!!

굳이 몰아서 처리할꺼면, 복잡하고 Interrupt Service Routine를 따로 구현할 필요가 없죠.

이건 1시간만 프로그램짜서 테스트해봐도 쉽게 결론을 얻을 수 있을 듯합니다.

예를 들면,

디바이스 드라이버를 짜면 돼죠.

그 디바이스의 read함수에 10초가 kernel mode에 멈춰있도록 하고, 그 드라이버에 read함수의 진입부에 printk한줄, 리턴하기 바로 전에 printk한줄 넣어줍니다.

이 디바이스 드라이버의 read함수를 호출하는 application을 하나 작성 합니다. 즉, 이 read함수는 System call이되는 거죠.

그리고, 오랠리책 Linux Device Driver같은 책에 나와 있는 간단한 인터럽스 서비스 루틴을 추가합니다. 눈으로 확인을 위해서 인터럽트 서비스 루틴에 printk문하나 집어 넣어주는 센스~!!

코드를 이렇게 작성하고,

위의 어플리케이션을 실행해서 디바이스 드라이버 read함수를 호출하게 하고, 동시에 인터럽트를 발생시켜서

아마도, read함수의 시작부분과 리턴전의 부분에 집어넣은 print문 사이에 인터럽트 루틴의 print문이 출력 되겠죠....

이럼 증명이 될까요 ? sangwoo님

익명 사용자의 이미지

sangwoo님 말씀에 몰표!!

굳이 몰아서 처리할꺼면, 복잡하게 Interrupt Service Routine를 따로 구현할 필요가 없죠.

이건 1시간만 프로그램짜서 테스트해봐도 쉽게 결론을 얻을 수 있을 듯합니다.

예를 들면,

디바이스 드라이버를 짜면 돼죠.

그 디바이스의 read함수에 10초간 kernel mode에 멈춰있도록 하고, 그 드라이버에 read함수의 진입부에 printk한줄, 리턴하기 바로 전에 printk한줄 넣어줍니다.

이 디바이스 드라이버의 read함수를 호출하는 application을 하나 작성 합니다. 즉, 이 read함수는 System call이되는 거죠.

그리고, 오랠리책 Linux Device Driver같은 책에 나와 있는 간단한 인터럽스 서비스 루틴을 추가합니다. 눈으로 확인을 위해서 인터럽트 서비스 루틴에 printk문하나 집어 넣어주는 센스~!!

코드를 이렇게 작성하고,

위의 어플리케이션을 실행해서 디바이스 드라이버 read함수를 호출하게 하고, 동시에 인터럽트를 발생시켜서

아마도, read함수의 시작부분과 리턴전의 부분에 집어넣은 print문 사이에 인터럽트 루틴의 print문이 출력 되겠죠....

이럼 증명이 될까요 ? sangwoo님

chaos4chaos의 이미지

Quote:

??? 잘 이해가 안되는데, 그렇다면 clock interrupt 이외의
다른 interrupt들의 service routine은 clock interrupt
service routine에서 call한단 말씀이신가요?

만일 위의 내용이 사실이라면
1. 어째서 그게 인터럽트 메커니즘이겠습니까? polling이죠
2. Clock interrupt routine은 누가 call 해 줄 수 있을까요?
3. Interrupt masking에 의한 interrupt의 loss라는 개념
자체가 필요가 없어지지 않습니까? 어쨌든 모았다가
한번에 처리하면 되는데..

clock interrupt도 network이나 다른 device와 같은
인터럽트일 뿐입니다. timer device가 보내오는
(물론 interrupt priority는 매우 높고, device마다 다르죠.)

인용:

여기에 사용되는 개념이 클럭인터럽트 레절루션입니다.

실시간 응답이 중요한 시스템에서는 클럭인터럽트 발생주기를 짧게해서

응답성을 높입니다.

Clock interrupt resolution을 높임으로 해서 얻는 효과는
스케줄링을 더 자주 이루어지게 하는 것입니다. 물론
high-priority *procss*의 응답성이 높아지겠죠.

Sangwoo님 흉내함 내봅니다.
시르바스까쓰(공룡커피마시는 책) 한 구절 옮기겠습니다.
...
The Operating system can suppot more timer requests
than the number of timer hardware channerls
by simulating virtual clocks.
Under This scheme,
the kernel maintain a list of interrupts wanted by its own routines and by user requests, sorted in earliest-time-first order.
...
이전 이후 문단은 이와 관련된 clock resolution 문제를 언급하고 있습니다.
이 한 문장으로도 Sangwoo님 께서 안된다는 이유 제시한 거는 대충
해결되는거 같은데요...

제 공력이 짧아서 jika님이나 sangwoo님 말씀을 제대로 이해하고나 글을 쓰는건지 의심이 들기는 합니다만...

조금 추가하자면, 인터럽트가 분명히 두가지로 나뉘어서 논의되지 않기 때문에 일어난 토론 같습니다만... clock res.에 의존하는 인터럽트와 그렇지 않은 인터럽트... 쩝...
예를 들면, 스케줄링 역시 인터럽트를 발생하지만, 그것은 전적으로 클록 해상도에 의존하므로, 이러한 인터럽트들은 해상도에 맞추기 위해서 모았다 처리된다... 정도가 아닐까 싶은데요....

물론 이러한 유형의 인터럽트들은 트랩으로 분류할 수 없는 것들(하드웨어 적이며, 비동기적인....)을 대상으로 이야기 하는 것입니다.

FOREVER_Ch@oS

정태영의 이미지

jika wrote:
비선점형 커널에서 시스템콜 수행도중에는 인터럽트를 처리할수 없습니다. 시스템콜이 끝나야만 비로써 인터럽트 서비스루틴으로 점프가 가능해집니다....

만약 처리할수 있다고 생각하신다면 논리적으로 설명해주세요...

프리엠션 포인트 없는 시스템콜 루틴에서 cpu 제어권이 어떻게 인터럽트 서비스 루틴으로 넘어가는지 설명해주시면 제가 좀 생각해보겠습니다.

.
.

"인터럽트는 발생 즉시 수행한다"
이런 문장 아마 수도 없이 많은책에 언급되어있을겁니다. 모두들 그렇게 믿죠.. 우상처럼... 그리고 그렇게 틀린말도 아닙니다.

하지만 개발자 입장에서 봤을때 저 말은 레절루션이 아주 낮은 상태에서만 맞는말이 됩니다.

보다 높은 레절루션에서 생각하면 저말은 아주 모호한 말이 됩니다.

.
.

인터럽트 서비스 루틴이 무슨 전지전능한 신도 아니고 코드에서 콜하지 않았는데 수행될리 없습니다.

뒷부분만 보고 서로 다른 용어가 일치하지 않은 듯 했는데... 앞 부분까지 봤더니 그게 아닌 듯 하군요...

인터럽트 벡터를 초기화 시켜놓고... 하드웨어 인터럽트 플래그를 세팅해놓은 것만으로... 인터럽트가 들어오는 즉시 인터럽트 벡터에서 해당 인터럽트를 처리하는 루틴(interrupt handler)의 주소를 찾아서 jmp 를 합니다... 끝나는 즉시 다시 원래 컨텍스트로 return 을 하구요... 프리엠션 포인트가 없더라도 억지로 인터럽트 플래그를 마스크하지 않는 이상은 충분히 인터럽트 핸들러를 call 하는 것이 가능합니다...

제가 그동안 공부하고 사용해봤던 마이크로 CPU 에서는 분명 저렇게 동작하고 있었고... x86 은 혹시나 다른가 해서 intel 의 x86 메뉴얼을 찾아봤습니다... 1권의 6-10 을 보면 인터럽트와 익셉션에 대한 설명이 나옵니다... 플래그가 마스크된 인터럽트가 아니라면야... 전지전능한 신이 맞는거 같습니다 :evil:

Quote:
The processor responds to interrupts and exceptions in essentially the same way. When an interrupt or exception is signaled, the processor halts execution of the current program or task and switches to a handler procedure that has been written specifically to handle the interrupt or exception condition. The processor accesses the handler procedure through an entyu in the interrupt descriptor table(IDT). When handler has completed handling the interrupt or exception, program control is returned to the interrupted program or task

interrupt 는 I/O 에 의해 발생하는 것이고... exception 은 코드를 수행하다가 발생하는 것이라고 되어있군요 (trap 이라던가 devide by 0 등의 경우요)

sangwoo wrote:
제가 아는한 Interrupt-driven 하드웨어 (x86등)에서는 명시적으로 커널이 interrupt service routine을 call하지 않습니다. 다만, 부팅 초기에 interrupt handler를 설정해 둘 뿐이죠. 그리고 해당 하드웨어가 interrupt를 보내오면 CPU는 현재 컨텍스트에 transparent하게 interrupt service routine으로 점프하는 걸로 알고 있습니다.

(interrupt handler와 interrupt service routine은 모두
같은 뜻입니다.)

상우님이 말하시는 인터럽트가 하드웨어 인터럽트라면 정확하게 일치하는군요... :)

jika wrote:
"시스템콜 수행중에는 인터럽트를 처리할수 없다"
"커널모드에서는 인터럽트를 처리할수 없다"

이 두 말에 차이를 이해 못하시면 대화가 곤란합니다. 커널 함수들 중에서 시스템콜이 차지하는 비중은 아주 작습니다.

인터럽트 헨들러와 시스템 콜을 혼용 하시는데요.. 인터럽트 헨들러도 넓은 의미에서는 일종의 시스템콜이라고 할수도 있겠지만 상위에서 하위로 불러드린다는 개념에서는... 제가 두단어를 동시에 사용해왔기 때문에 두가지는 다른 개념으로 이해해 주셔야 합니다.

인터럽트 핸들러가 일종의 시스템 콜이라기 보다... trap 등을 통해 인터럽트를 발생시키고... 호출할 시스템 콜 번호를 확인한후 시스템콜 벡터를 이용해서 원하는 시스템 콜을 수행하는 것이라고 알고 있습니다 ...

시스템 콜이나 인터럽트 처리 외에 커널 모드에서 코드가 수행되는 일이 어떤 게 있는지는 잘 모르겠군요...

(실제 코드를 보거나 작성해본 적은 없습니다만... 이론적으로 제가 아는 내용에 한해서 좀 이상한 부분이 있어서 답글달아봤습니다)

오랫동안 꿈을 그리는 사람은 그 꿈을 닮아간다...

http://mytears.org ~(~_~)~
나 한줄기 바람처럼..

익명 사용자의 이미지

인터럽트의 발생소스에 대해서만 간략히 정리해 봅니다.
* 소프트웨어 : x86의 경우 어셈블리로 int [x]하면 발생하는 경우, 프로그래머/컴파일러가 int [x]라는 어셈블리코드를 생성한 경우에 발생합니다. 시스템호출을 구현하는 기본이 된다는..
* 하드웨어 : CPU외부에 있는 장치가 CPU와 연결된 선(지네발?)으로 즉, CPU의 INTR핀이나, NMI핀으로 신호(시그널,전압 high)가 발생한 경우에, CPU의 플래그레지스터의 인터럽트 인에이블 플래그 비트가 인터럽트 허가인경우에 발생, 디스에이블되어 있으면, 그 어떠한 외부 하드웨어도 인터럽트를 요청 불가. 클락, 랜카드등 외부 하드웨어가 대빵이 아니라, 소프트웨어로 디스에이블시키면 어떤 외부(CPU기준) 하드웨어도 인터럽트 불가(단, NMI 핀으로 오는 인터럽트는 그 CPU플래그와 상관없이 수행/무조건 수행이라는...) : 마치 웹서버 앞단의 파이어월에서 " 내부점검등의 이유로" 모든 인바운드트래픽차단하면, 그아무리 높은양반도 접속불가임. 그러나, 내부관리자가 콘솔에서 (중간에 차단장치없는..)연결하면 무조건 웹서버접근됨, 그러나, 하드웨어가 적절히 인터럽트 걸게 허가해 주는 미덕이 있게 프로그램 만들면 좋겠지....특히, 범용시스템이라면 더더욱 그래야 할것이고, 특정분야에 국한된 embeded라면 프로그래머가 설정한 맘대로...
* CPU : 클락이나, IO장치등등 외부하드웨어와는 다르게, CPU 내부에서 발생시킴. 이를 exception이라고 보통 부르기도 함(또는 전체 인터럽트를 exception이라고 해석하기도 함) 예를 들어, CPU연산을 하는데 0으로 나눈경우 발생, VM 메모리 mov을 하는데 메모리가 없음(페이지폴트->폴트핸들러가 메모리를 로딩후 다시 mov명령을 수행;폴트는 ...핸들러후..방금전 명령을 다시수행)등.

* x86의 경우 위 종류중 임의의 인터럽트/exception가 발생하면, 인터럽트 번호*x를 수행해서 지정된 메모리 번지로 프로그램이 점프됨(이는 사전에 미리 그 번지에 핸들러를 달아놔야한다는 얘기임)그리고는 인터럽트 수행시(int 머신명령에 각종 레지스터 저장/복구하게 되어있음; 이를 위한 머신 사이클이 길어-모든 머신 명령에 비해 가장 길다는..- 인터럽트가 자주뜨면 별로 안좋다는... ) 저장해두었던 프로그램의 컨텍스트를 복귀시키고(스택에서 꺼내서) 그 코드로 다시 복귀.

* 명령의 수행방식에 따른 분류
trap : 특정 명령 n번째를 수행시 발생-핸들러-n+1번째 명령수행
fault : 특정 명령 n번째를 수행시 발생-핸들러-n번째 명령 다시 수행
abort : 중단.

jika의 이미지

이야기가 프리엠티브 커널에서 인터럽트 처리로 넘어왔군요..

인터럽트가 바로 즉시 처리되는건 아니라는 제 말에 오류가 있었는지 모르겠습니다만...

제말을 검증할수 있는 분들이야.. 알아서 판단하실듯 하고..

이글을 읽을지도 모르는 몇몇 학생들의 이해를 돕기 위해서 간단한 글을 남깁니다.

단일cpu 에서 cpu 처리 흐름은 한개입니다.

단지 우리는 아주 짧은 시간으로 그 처리흐름을 나누어서 쓰니까 cpu가 동시에

여러가지 일을 하는듯 보입니다만...

물론 cpu 내부적으로야 파이프라이닝도 하고 그렇습니다만 그이야기 하는것 아니니까 그런쪽으로 딴지 걸진 말아주세요..

인터럽트 이야기로 다시 돌아가겠습니다.

cpu의 처리 흐름이 하나라는 가정해서 cpu의 처리속도에 한계가 있습니다.

빠르건 느리건 그렇습니다. 한계는 있는거지요..

그런데 인터럽트가 마구 발생합니다. 수십 수백 수천개의 인터럽트가 마구 발생하는 상황을 가정합시다.

이 모든 인터럽트 서비스 루틴이 때론 간단한일을 때론 복잡한 일을 수행합니다.

그런데 저 모든것이 실시간적으로 수행된다고 생각하시면 곤란합니다.

물론 목표는 그걸 목표로 합니다...

하지만 현실에 그걸 다 커버 할수 없는 상황이 있을수 있기 때문에

운영체제는 인터럽크 우선순위를 세부적으로 결정해 놓습니다.

살펴 본지가 오래되서 기억이 가물 가물 하지만

가장 우선순위가 높은것은 시스템이 따운되는 상황에서 처리해야 할 루틴들이고

그다음으로 클럭인터럽트 처리 루틴이고

맨 마지막에 소프트웨어 인터럽트들이 가장 낮은 우선순위로 배정됩니다.

예를들어 낮은 우선순위의 인터럽트를 처리한다 칩시다..

그순간 더 높은 인터럽트가 발생하면 해당 인터럽트 서비스루틴의 처리를 종료하지 않고

더 높은 우선순위의 인터럽트 서비스루틴을 처리합니다.

그리고 돌아오려면 돌아오는데 이때 또 더 높은 우선순위의 인터럽트가 계속

발생하면 낮은 우선순위의 인터럽트는 처리가 지연되고 밀려 있게 됩니다.

얼핏 보니 제가 사용한 시스템콜과 윗분들중에 몇분이 사용하신 시스템콜의

용어정의 범위가 다른듯 합니다.

제가 사용한 시스템콜이라 함은 리눅스 내부에 구현되어있는 함수들입니다.

다른분들은 저보다는 더 큰 의미로 시스템콜이라는 단어를 사용하시는데

제가 그걸 잘 모르고 있었던듯 합니다.

그리고 마지막으로 상우님이 글쓰신 말미에..

HZ 이야기를 하셨는데..

리눅스 내부적으로 클럭인터럽트 발생주기는

100*HZ/1000 인가 그렇습니다.

버전별로 바뀐적 없구요..

커널 컴파일할때 물론 수정가능합니다만 디폴트값이 버전별로 바뀐적은 없구요..

HZ는 CPU클럭이 아닌 아키텍처에 디펜던트한 상수입니다.

i386 은 1000 입니다.. 다른 종류의 cpu 들은 arch 폴더 및에 정의된 파일들이 있습니다.

서한석의 이미지

HZ의 정의가 1초에 몇번(?) 진동을 주느냐? 이런것입니다.

100HZ 라면 1초에 100번입니다.

1초에 100개의 클럭인터럽트가 발생한다는 이야기 입니다.

리눅스의 기본은 100HZ로 잡혀있습니다.

linux/include/asm-i386/param.h
에 가면
#define HZ 100

최근 linux-2.6.15(이걸 지금 확인하고 있어서..ㅋㅋ)

default가 250으로 되어 있네요 (make menuconfig 에서 확인)

===============
i386은 1000 입니다. 저부분에 대한 이해를 못해서 끄적여 봅니다.

아~ 저는 HZ을 확인하는 시스템콜// 기타 방법을 찾을려고 검색중입니다.

감사합니다.

sisbn의 이미지

제가 워낙 초보라 jika님의 마지막 글에 대해 궁금한점이 있습니

다.

제가 정확히 이해를 못한것일수도 있지만 jika님 글을 읽어보면,

높은 우선순위를 갖고 있는 인터럽트가 수행중에, 낮은 우선순위를

갖는 인터럽트가 걸리게 되면, 바로 낮은 우선순위를 갖는 인터럽

트 핸들러가 수행이 되지 않는다고 이해를 했거든요.

그렇다면 이런 과정을 거쳐야하지 않을까요?

모든 인터럽트들이 걸릴때마다 바로 해당 인터럽트 루틴을 호출하

는것이 아니라, 각각의 인터럽트 루틴이 호출되기전에 공통으로 거

는 루틴이 있어서, 그 루틴내에서 낮은 우선순위에 대한 인터럽트

같은 경우엔, 표시를 해놓고 있다가 높은 우선순위가 끝나면 해당

인터럽트 핸들러를 호출해주는 방식으로 말이죠.


그리고 또하나,

비선점형은 낮은 우선순위를 갖는 시스템콜 수행중에,

설혹 높은 우선순위를 갖는 인터럽트가 걸려도, 시스템콜 처리를

다 하고, 해당 인터럽트를 처리하는 것을 말씀하신거 맞나요?

저 생각이 틀렸다면, jika님의 말씀을 이해하는데 더 큰 혼란이..;

do_IRQ()함수가 공통으로 먼저 불리는 그런 역할을 하는 함수

아닌가요..? 한수 부탁드립니다.

정태영의 이미지

예전에도 말했지만 jika 님과 다른 사람들 사이에 용어가 맞지 않고 있는 듯 합니다...

http://kldp.org/KoreanDoc/html/EmbeddedKernel-KLDP/start.kernel.sched.html
이 문서를 보면 약간 아귀를 맞춰볼 수도 있지 않을까 싶습니다...

Top Half 에서... 인터럽트 플래그를 unset 시키고 간단하고 빠르게 처리할 수 있는 부분을 처리합니다 ... 아직 처리가 남은 부분은 bottom half 에 할 일이 있다고 표시만 해놓고 인터럽트 플래그를 다시 set 시킵니다...

그러다 나중에 좀 여유가 생기면 bh 를 처리합니다... bh 를 처리함에 있어선 나름대로 우선순위를 가지구요

나름대로 이 포스트에 주렁주렁 달린 굴비들로 인해 레벨업 한 분들이 참 많을 듯합니다 ... 감정적으로 틀렸다 맞았다를 얘기하려는건 아니니 ... 니가 틀렸다 내가 맞다 식의 답글은 이제 그만 달렸음 합니다 :)

리눅스에서의 bh th 관련해서 더 자세히 보고 싶으시면

http://kldp.org/Translations/html/The_Linux_Kernel-KLDP/tlk11.html
이 문서를 참고하면 좋을 듯 하군요

p.s) 예전 VT 시절을 생각나게 하는 "가로 길이 약 80 자 선에서 엔터 두방 방식" 보다... 연관된 내용은 그냥 길게 연결해서 "패러그래프 단위로 엔터두방" 방식으로 써주시면 내용을 보는데 좀 덜 힘들 거 같다는 생각을 해봤습니다...

오랫동안 꿈을 그리는 사람은 그 꿈을 닮아간다...

http://mytears.org ~(~_~)~
나 한줄기 바람처럼..

익명 사용자의 이미지

한가지 덧붙이자면,

리눅스에서 하드웨어 인터럽트, 즉 do_IRQ() 함수에 의하여 처리되는 인터럽트에는 명시적인 우선순위는 존재하지 않습니다. 모두 같은 우선순위를 지니고, 인터럽트 핸들러 내부적으로 sti, cli 등을 이용하여 하드웨어 인터럽트에 대한 제어를 하는 것이지요. 오히려 인터럽트 우선순위는 각 H/W Interrupt Controller에서 담당하고 있다고 하는 것이 옳겠죠... 물론 S/W상에서 Kernel 이 Bottom Half, Tasklet등을 이용하여 우선순위를 조정할 수는 있겠지만, 물리적으로 발생한 Interrupt 신호에 대한 처리는 각 Peripharal Device 별로 우선순위가 존재하지 않는 것이지요. do_IRQ() Code를 참고하시면 될 듯 합니다.

chaos4chaos의 이미지

Quote:
예전에도 말했지만 jika 님과 다른 사람들 사이에 용어가 맞지 않고 있는 듯 합니다...

제 생각에는 그다지 크게 용어가 다르게 사용되고 있지는 않다고 생각합니다. 쓰레드의 처음부분에서는 스케줄링과 커널을 각기 뭉뚱거리고 이야기하셔서들 약간의 혼동이 있긴 했지만요... 두 분 모두 정확히 서로를 이해해가시면서 대화하셨다고 생각합니다. 도중에 몇 분이 전체글을 다 읽지 않고 말씀하셔서 내용이 와전된 부분이 보이기는 하는군요.
물론 약간의 용어 차이가 있긴 하지만 논점에는 크게.... 영향이 없는 듯....

Quote:
... 감정적으로 틀렸다 맞았다를 얘기하려는건 아니니 ... 니가 틀렸다 내가 맞다 식의 답글은 이제 그만 달렸음 합니다.

저는 태영님께서 바라보시는 시각과는 약간 다른데요... 제가 무지해서인지도 모르겠지만, 실제로 대부분의 전산하시는 분들이 이 주제에 대해 각기 다른 생각을 가지고 계시는 걸 무척 많이 보아왔습니다. 물론 여기서도 보구 있구요. 감정적으로 틀렸다 맞았다 말씀하시는 거는 안보이고 jika님과 sangwoo님의 간결한 요약이 두드러지는 스레드라고 생각합니다.

제 생각에 이 주제의 특징은 선점과 비선점, 인터럽트의 아키텍쳐 별 차이, 용어의 범위 차이, 운영체제의 구현 차이 등으로 인해 사람들마다 조금씩 이해의 차이가 있다는 것이지요....
하지만, 이 곳에서 여러가지가 모두 한 번씩 언급되는 토론을 보아서 무척 재미있게 보고 있습니다. 물론 역시나 태영님, 지카님, 상우님, 손님 :D 을 포함해서 자존심과 내공이 느껴지는....

하지만, 분명 두 분의 의견은 용어 차이가 아니라고 생각합니다.
제 생각에는 두 분 의견의 차이는 아마 이런게 아닐까 한 번 여쭈어 봅니다.

즉,
아무리 하드웨어 인터럽트건 소프트웨어 인터럽트건 무시기가 걸리더라도 플래그 확인하여야 하는 순차까지는 진행해야 하지 않겠느냐... 그럼 그 간격(레졸루션) 사이에 시스템 콜은 몇 개의 명령어나 수행될 수 있을까?
수만개일 수도 있고 수천 개일 수도 있으니 어찌 인터럽트가 즉시 수행된다고 말씀하리오....
게다가 그 수천 개의 진행동안에, 설령 즉시 실행하려고 기다리던 인터럽트와 충돌이 일어날지도 모르는 자료구조를 시스템 콜이 건드려버리면(재진입가능하지 않은 코드의 커널) , 이건 설상 가상으로다가 조금 더 기다려라.... 인터럽트여.... 내가 쓰던거 마져써야겠다........
또한, 2.6 커널처럼 완전히 선점형으로 작성된 커널에서도, 이 간격(레졸루션) 사이에 수천개의 명령을 진행해버린 시스템 콜과 그 막간의 시간 지연으로 인해 인터럽트는 대기한다고 할 수 있으며, 설상가상으로 그 막간에 또 다른 인터럽트가 발생했다 하면 더더구나 이게 대기가 아니고 무엇이리오...
아나로그적인 즉시라면 이 막간 사이에 두 인터럽트의 순서가 구분될 터이니 인터럽트가 인터럽트를 당하는 한이 있더라도 일단 실행은 될터인데... 아쉽게도 우리 컴퓨터는 디지털이구료.....
이렇게 말씀하신게 jika님 의견인 것 같습니다.

반면, 상우님 께서 말씀하신 좀더 개념에 가깝지 않았나 생각합니다.
락으로 점유되어 있지 않는한 어디서건 인터럽트가 가능하니까(선점 커널 2.6). 이건 즉시로 이야기 해야지.... 대기라고 표현하는 것 자체가 개념의 모순을 가져오지 않겠느냐? 재진입가능한 선점 코드에서 명령어 단지 몇 개의 차이는 언급할 필요가 없다. 왜냐하면, 이는 명령어 1개 혹은 100 개가 수행되었건 어디서든 선점 가능하다라는 조건이 해결해 주니까... 쩝..
솔직히 상우님 말씀은 제가 이해한 것과는 약간의 차이가 있어서 요약을 쉽게는 못하겠습니다.
물론 지카님 말씀을 제대로 이해했다고도 생각하지 않습니다.

그럼 뭐할러 요약을 했을까요....쩝... :P

Quote:
나름대로 이 포스트에 주렁주렁 달린 굴비들로 인해 레벨업 한 분들이 참 많을 듯합니다

제가 이 쓰레드에 관심이 많아서 오랜만에 들락날락 좀 했습니다. 태영님 글도 재밌게 보았구요... 그런데... 위 말씀은 지금까지 보아오던 태영님의 글솜씨와는 조금 차이가 있어보이는 군요... 너무 냉기가 흐른다고나 할까요...

처음에는 그런가보다하고 지나쳤는데... 허걱
이 스레드에 관심가지고 사족다신분들은 거의 손님이고 제 아바타만 유독 눈에 띄는군요... 지카님과 상우님은 메인이시니...
아~~ 쩍팔려... 쓰잘데기 없는 말만...

절 두고 하신 말씀이라 생각하고
답변드립니다.
저 레벨업에 관심없거든요... :lol: :lol:

FOREVER_Ch@oS

vajna의 이미지

스케쥴링 관련 글타래가 순식간에(연휴라 그런가??) 길어지는 군요.
정리겸, 저도 의견을 제시해봅니다.

분명히 하고 넘어가야 할 것은
일단 인터럽트는 선점형/비선점형 스케쥴링(또는 kernel preemption)의 개념과는 관련이 없고,
구현상에서 인터럽트 관련 수행이 달라지는 국소적 현상을 가지고 있을 뿐입니다.

일단 선점/비선점 스케쥴링은 모두 알고 계시듯이 "태스크의 흐름"을 시간에 따라 바꾸어 줍니다.
선점 스케쥴링은 태스크가 suspend 되는 시점, 즉, time_delay(or sem_wait, mutex_lock..)
이전에도 'time slice 또는 ISR 종료후' 스케쥴링 프로시저에 더 높은 우선순위의 태스크가 ready일때는
context switching을 수행합니다.
여기서 말하는 "태스크의 흐름"은 일반 프로시저와 시스템 콜이 시간적으로 혼합되어 있습니다.
비선점 커널 컴포넌트(선점과 비교해서 비선점 커널)에는 이러한 태스크들이 여러개들이 있을때
커널 컴포넌트로서 시스템 콜 수행중에 태스크간 스케쥴링이 막혀야 할 부분들이 있고,
이를 위한 한 방법으로 context switching을 수반하는 인터럽트 프로시저를
lock하는 방식이 사용되었습니다.(재진입 불가, 공유자원 보호)

일단 위의 방식으로 시스템 콜은 보호되었으나,
OS전체적으로 실시간성을 떨어트리는 원인이 되기 때문에(시스템 콜의 일부 수행도중 더 높은
우선순위의 작업을 할 수 없다 -> 응답시간은 실시간 시스템(주로 임베디드)에서 치명적입니다.),
시스템 콜 수행중에도 최대한 context switching가능하도록 선점형 커널이 고안된 것이고,
비선점형 커널보다 더많은 작업(재진입 가능등..)이 되어있는 시스템이 되겠지요.

머나먼 땅으로 우리 동무가 이제 떠나간다네.
고향의 바람이 불어와 동무 뒤를 따르고
사랑스러운 도시가 푸른 이내 속에서 사라지네.
정든 집, 푸른 동산, 부드러운 눈길도...

정태영의 이미지

chaos4chaos wrote:
절 두고 하신 말씀이라 생각하고
답변드립니다.
저 레벨업에 관심없거든요...

아 그런건 아니었고 약속이 있어서 나가야 했는데 ... jika 님이 쓰는 용어가 OS 와 컴구조 등에서 배운 내용가 차이가 있기 때문에 서로 의사소통에 문제가 있다고 생각했었습니다... 시스템 콜은... 유져 프로세스에서 콜게이트를 통해 커널모드로 돌아가서 어떤 작업을 하는 방법이라고 배웠고... "하드웨어" 인터럽트는... 플래그를 확인하는 작업등이 필요한게 아니라... 발생하는 즉시 (하드웨어적으론 플래그를 확인하지만... 소프트웨어적으로 확인하는 게 아니기 때문에 한 클럭안에 바로 jmp 를 하게 되겠죠) 인터럽트 핸들러로 점프를 하게 되는 것이라고 알고있었는데...

bottom half 라면 모를까 그냥 하드웨어 인터럽트를 얘기하는 것이라면 용어를 잘못 사용하고 있다고 생각했습니다... 그 때문에 토론이 좀 꼬였다고 생각했구요 :evil: ... 뭐 자존심 같은걸 얘기하기엔 전 너무 아는게 없군요 ㅠ_ㅠ

하튼 이 쓰레드는 참 재밌게 관찰하고 있기는 하지만... 역시나 오늘도 술을 많이 먹고 들어온지라 :evil: 정신이 없어서 이 정도로 줄이도록 하겠습니다 ...

하튼 결론은... kldp 만세 입니다!!

오랫동안 꿈을 그리는 사람은 그 꿈을 닮아간다...

http://mytears.org ~(~_~)~
나 한줄기 바람처럼..

ed.netdiver의 이미지

헉, Q/A코너에 있는 걸 읽기 시작했는데, 어줍잖게 글 달아보려고 새창에서 열었더니 어느새 이곳으로 이동되었네요.
잘못 이해하고 껴들지나 말아야 할텐데, 아 살떨~^^;
음. preemptive하다는 것에 대한 정의때문에 주제넘게 껴듭니다.
제가 알고 있는 내용을 검증하기 위한 용도일 뿐이니 너무 괴념치들 마시길^^;

priority 정책은 기본적으로 상위 우선이 됩니다.
상황은 높은 우선순위의 작업이 수행되고 나서 스케줄링에 의해 낮은 우선순위의 작업이 수행중에 있습니다. 이때 다시 높은 우선순위의 task가 정상적으로 수행중인 낮은 순위 task를 제치고 자기 일을 볼 때, preemptive하다고 하는 것으로 알고 있습니다.

interrupt resolution과 관련한 immediate 처리 여부가 잠시 논의되었지만, interrupt처리는 즉시 처리될수도 있고 pending될수도 있다고 하는 편이 맞습니다.
굳이 polling스럽게 몰아서 처리한다는 것이 아니라, nesting, masking이 존재한다는 것입니다.
이때 preemption특성과 관련이 있는것은 nesting입니다.
낮은순위 interrupt가 assert되어 해당 ISR이 처리되는 중간에 높은순위 int가 치고들어왔을때 낮은순위 isr이 pending는 상황을 nesting되었다고 하고, 그렇게 nesting가능한 구조가 preemptive하다고 하는 것으로 알고 있습니다.

정리하면 연장자가 언제든지 새치기가능하면 preemptive하다. :D

--------------------------------------------------------------------------------
\(´∇`)ノ \(´∇`)ノ \(´∇`)ノ \(´∇`)ノ
def ed():neTdiVeR in range(thEeArTh)

R의 이미지

Preemptive - 우선 순위가 높은 다른 프로세스가 CPU를
빼앗아 사용가능한 스케줄링 기법

선점이 가능하도록 일정 시간 배당에 대한 인터럽트용 타이머클럭
이 필요하다.

NON-Preemptive - 이미 할당된 CPU를 다른 프로세스가 강제로
빼앗아 사용할 수 없는 스케줄링기법

:)

philossh의 이미지

저는 커널에 관련된 코딩을 해보진 않았지만..
이 쓰레드의 수많은 글타래들을 읽어보니 windows도 리눅스와 거의 비슷한 로직으로 구현된 듯 해서얼마전 공부한
windows의 선점형 스케줄링부분에서 몇자 발췌해 봤습니다..

IRQL (Interrept Request Level) : 윈도에서 정한 논리적의미의 하드웨어적 우선순위
// 하드웨어적인 우선순위
31 [ High]
30 [Power failure]
29 [프로세서간의 인터럽트]
28 [ Clock]
27 [프로파일]
26
| [device]
3

// 소프트웨어적인 우선순위
2 [ DPC/dispatch] // 커널(?)
1 [ APC]
0 [Passive]
//유저 level

윈도에서는 타이머 인터럽트가 발생되면(Clock level) 현제 쓰레드의 퀀텀(CPU사용을 위해 할당된 양)값을 3감소시키고
만약 0보다 작아지면 스케줄링을 위한 루틴을 DPC큐에 넣게 되고 모든 하드웨어적 인터럽트 루틴이 끝난 뒤
DPC큐에 포함되어진 루틴들이 하나씩 수행되어 진다.(DCP level)

언제나 우선순위가 높은 인터럽트가 모두 수행된 후에 낮은 인터럽트가 수행 될 수 있는 것에서 미루어 볼때..

쓰레드에 대한 스케줄링 및 다른 쓰레드로의 스위칭을 위한 초기화 작업은 DPC level에서 이루어 지는데,
이는 실행되고 있는 쓰레드가 DPC level보다 아래에 있을 때에만 쓰레드의 스위칭이 가능하다는 이야기가 되기도 한다.

...........
뭐 대충 이런 내용이 있군요..

CPU의 인터럽트 플래그가 enable되어 있는 동안에는 하드웨어적인 인터럽트는 항상 우선적으로 처리되어지고..
스케줄링에 관련된 루틴은 그 다음에 이루어지며..
스케줄링 루틴이 실행될때 프로세스나 쓰레드들에 대해 스케줄링이 가능하다 라는 의미가 되겠군요...
(스케줄링 우선순위 큐는 IRQL과는 무관하며 서로 다른것임)

이 내용들이 windows에 대한 내용이라도 리눅스와 그리 다르지는 않을 것이라 생각됩니다..
(운영체제의 기본 concept으로 보면 당연한일일지도)

To be or not to be.
That is the question.

mach의 이미지

philossh wrote:

...
CPU의 인터럽트 플래그가 enable되어 있는 동안에는 하드웨어적인 인터럽트는 항상 우선적으로 처리되어지고..
...

맞습니다. enable되어 있는 동안 하드웨어적인 인터럽트가 항상 우선이라기 보다는 우선순위가 높은 인터럽트 우선이겠지요.
...
그러나, 하드웨어 인터럽트에 대한 ISR도 프로그래머가 작성하게 되어 있습니다.
하드웨어 인터럽트의 경우, 인터럽트 발생으로 인해 이를 호출하는 것은 하드웨어 메카니즘에서 이뤄지지만(프로그래머가 콜하지 않음/int [h/w 인터럽트벡터번호] 해서 하드웨어가 발생시킨것처럼? ISR을 호출할 수 있겠지만 논외로 하고), 이에 대한 핸들러는 프로그래머(특히, 커널 프로그래머)가 작성해서 그 ISR의 시작주소를 보통 시스템초기화시에 등록해줍니다. 하드웨어 인터럽트 번호*특정 수=ISR의 위치로 되며, 그 번지에는 핸들러가 있어야 마땅합니다. 아니면, 이상한? 상태로 빠지게 되겠지요.

핸들러를 등록했고,....
만일, 하드웨어에서 인터럽트가 발생한다면, 이는 인터럽트 콘트롤러에게 전달되고(하드웨어 인터럽트 우선순위에 의해) 인터럽트 콘트롤러는 CPU에게 인터럽트를 콜해도 되냐고 물어봅니다. CPU의 인터럽트 플래그레지스터값에 따라, 인터럽트가 허용/비허용되겠습니다. 비허용이면 임의의 하드웨어는 인터럽트를 할 수 없습니다.(NMI빼고)
허용이라면 말씀하신대로 무조건적으로 그 루틴으로 일단 등록된 번지로 점프(각종 레지스터 저장하고...)하고, 등록된 루틴을 수행하게 됩니다. 이 루틴안의 코딩은? 프로그래머가 합니다.
즉, 인터럽트야 하드웨어가 발생시켜 호출(점프)까지는 CPU가 해줬지만, 그에 대한 실제처리 루틴은 프로그래머가 한다는 얘기입니다.
가정을 해봅니다. 원래 X라는 인터럽트에 대해 A라는 처리를 해야하는게 보통이지만, 그 ISR내에서 조건부 처리를 할 수도 있겠습니다. 당연히 가능하겠지요? 이를 테면 카운트값만 증가시키고, 특정 플래그(fake 플래그, 프로그래머가 정의한)만을 세팅한 후 해당 ISR에서 리턴할 수 있겠습니다. (이때, 하드웨어(호출한 임의의 곳)에서 ISR에서 뭔가 처리하고 port등을 통해 ACK를 받을 수 있다면, 소위 블록상태로 처리대기 할 수 있다면, 물론 그렇지 않아도 이렇게 할 수 있습니다.)
그리고, 그 플래그를 참조하여 다른 루틴에서 뭔가 새로운 처리도 가능하겠습니다. 이를테면, 하드웨어의 포트에서 실제 데이터를 읽는다/쓴다던지... 등등.. 이때 특정 하드웨어는 타이밍이 중요하여 그 처리가 고정시간(상수시간)내에 이뤄지지 않으면, 그 시점의 데이터가 깨질 수도 있으니 유의해서 코딩해야 합니다.

소프트웨어 인터럽트는 하드웨어와 유사하게 동작하지만, 프로그래머가 인위적으로 발생시키는 것입니다. 명시적으로 INT명령으로 호출해 주어야 합니다.

주제는 preemption에 관한, 특히, 리눅스의 특히, 커널의,..였는데, 각자 바라보는 주관심사의 시각차로 인해 (자존심적인?) 논쟁이 되었고, 일부 부정확한 얘기/검증되지 않은 얘기들을 참조하기도 했다고 봅니다.
제가 보기에는 인터럽트가 그 중 오해를 살만한 얘기의 대상중 하나였다고 보았습니다. 그래서, 오랜(?) 기억속을 더듬어 써봅니다.

* 발전적인 논쟁이 지속되길 기대합니다.

------------------ P.S. --------------
지식은 오픈해서 검증받아야 산지식이된다고 동네 아저씨가 그러더라.

chaos4chaos의 이미지

현대적인 운영체제... 즉, 인터럽트가 끌고가는 현재 컴터 구조하에서만
발생할 수 있는 문제가 선점과 비선점 커널의 문제 아니던가요?
인터럽트가 없는데 과연 선점이 가능한지, 또는 선점, 비선점의 구분이 필요한 지에 대해서는..... :shock:

즉, 인터럽트의 시점 및 대기 유무가 예측가능하다면, 애당초 선점, 비선점에 대한 고려조차도 필요 조차가 없겠지요...

제 생각에는 커널의 선점, 비선점에 대한 논의는 곧 인터럽트(이하 하드웨어 인터럽트)의 대기 여부를 논하는 문제로 동등하게 환원된다고 생각합니다. 위에 mach님께서 설명해주셨듯이 핸들러 역시 자료구조이며 로직에 불과하니까요(로킹이 가능하며 언제든지 비일관적인 상태에 놓일 수 있는...)... :?

물론 몇몇 패닉 수준의 이벤트를 알리는(또는 지시하는) 인터럽트라면,
그 다음의 작업의 순차열 및 일관성에 관심을 두지 않으므로 논의할 필요가 없겠지요...
이러한 경우에 한해서는 즉시(아무 생각없이, 그냥 막무가내로, 플래그 유무로만 판단하고) 인터럽트가 처리된다는 표현이 크게 이상하지 않은것 같습니다.

그 이외의 경우, 즉 작업의 순서(타이밍)나 커널 자료의 일관성을 유지하면서 정상적인 처리가 필요한 경우,
과연 인터럽트가 즉시 실행될 수 있는가는 상당히 중요한 문제라고 생각합니다.

특히, 이를 단순히 로킹 또는 인터럽트 마스킹(또는 ipl 포함)을 이용해서 처리하고자 했던 것이 이제 슬슬 문제시되는 환경(다중 처리기)으로 바뀌어가는 추세이므로 인터럽트의 대기 문제가 좀 더 정확히 이해가 안된다고 해야하나.. 무어라고 해야...중얼중얼...

흐흐흐... 궁금한게 있어서 질문을 남기려다 말이 길어져서리... 그만..
이 스레드를 읽은 다른 어떤 녀석과 기나긴 대화로 티격태격하다가 그만, 둘 사이의 근본적인 차이에 눈을 뜨게 되었습니다.
즉, 인터럽트 사이클로 빠지기전에 명령어가 몇 개나 진행하느냐는 문제였습니다.
저는 페취 사이클, 익스큐션 사이클이 적절한 타이밍 설정으로 인해 또한 적당히 반복하다가, 즉 조금 많은 명령을 실행하다가 특정 시점(설정한)이 되면 인터럽트 사이클로 빠진다고 알고 있었습니다만, 그 분(?)께서는 명령어 하나 페취 - 익스큐션 - 인터럽트의 각 사이클이 반복된다고 주장합니다.

흐음...
페취 사이클과 익스큐션 사이클은 정녕 단 하나의 명령어만 실행하고 인터럽트 사이클로 빠지는지...........
궁금증 좀 해결해 주셨으믄...... 합니다...

현재 제가 접근 가능한(?) 웬만한 참고서에는 전부 단일 명령어 페치-실행-인터럽트 사이클로 묘사되어 있네요....
이론이론....쩝....
아닌거 같은데....

FOREVER_Ch@oS

philossh의 이미지

Quote:
현재 제가 접근 가능한(?) 웬만한 참고서에는 전부 단일 명령어 페치-실행-인터럽트 사이클로 묘사되어 있네요....

제가 알기로도 이렇게 알고 있는데요..

페치-실행-인터럽트사이클(인터럽트 플래그가 enable 되어있으면 )..
NMI(마스크할수없는, 정전등)와 같은 인터럽트는 시피유를 거치지 않고 전용라인(?) 으로 바로 인터럽트가 처리되구요..

To be or not to be.
That is the question.

mach의 이미지

음 , 이 경우에는 외부요인에 의한 인터럽트보다는 CPU내부적인 인터럽트로 얘기를 풀어가는게 좋겠습니다.

*한번에 여러개 명령을 실행하고, 인터럽트 사이클로 간다면,
0으로 나눈경우(DIV명령), 오버플로우(ADD명령)등은 즉시 검사하지 않고, 명령어 몇개 더해보고 하겠다는 얘기로도 통하는데......

* 혹시나, 다수명령후 인터럽트 사이클을 수행하게 CPU를 만들었다고 가정할때, CPU는 부가적으로 몇개(?) 중 어느 명령이 인터럽트를 유발했는지, 아니면 복합적으로 발생했는지? 아니면 외부요인인지? 를 알아내는 방법이 필요할 것입니다.

*따라서, 매 명령어 수행마다(fetch, indirect, execute, interrupt) 인터럽트 사이클은 준수되어야 할 것입니다.

------------------ P.S. --------------
지식은 오픈해서 검증받아야 산지식이된다고 동네 아저씨가 그러더라.

kldpdais의 이미지

cyk 님의 답변이 이 주제의 가장 정확한 답이라고 판단 됩니다.
(저의 생각 입니다.)

그런데 윈도우 3.1이 정말 운영체제인가요? ^^

sisbn의 이미지

(커널모드) 선점형과 비선점형의 차이를 간략하게 요약하자면,

인터럽트 컨텍스트(hardware interrupt)이든 프로세스 컨텍스

트(system call) 이든,

그것들이 수행되는 중간에 타이머 인터럽트에 의해서 혹은,

다른 인터럽트에 의해서 (예를들면 가장 우선순위가 높은 프로세

스가 외부 입력을 기다리다가 입력이 들어오면서 인터럽트가 걸리

게되는 순간)스위칭이 일어날 수 있는지 없는지로 구분된다고 합니

다.

단지 어느 시점에서 인터럽트가 걸릴수 있는지 없는지가 아니라,

덧붙여서, 스위칭의 가능여부가 함께 고려되어야한다는거죠.

ed.netdiver의 이미지

interrupt는 CPU에게 있어, 혹은 OS에게 있어 미뤘다 말다 하는 능력 밖에 있습니다.
single instruction에 대한 이야기가 있는데, 그것은 단지 memory혹은 register에 strobe된 data가 온전히 latch되기를 기다리는 시간인것뿐입니다.
왜냐하면 instruction 수행과정에서 register에 저장한다는 명령어를 수행해놓고, 즉 PC는 다음 instruction point로 옮겨지고 정작 register에는 저장되기 전에 interrupt에 의해 vector jump해버리면 그 ISR을 수행하고 되돌아간 지점에서는 program이 malfunction해버릴것이기 때문입니다.(물론 normal mode에서 interrupt mode로 change하는데는 이밖에도 신경써야할 것들이 있어서 CPU hardware적으로 interrupt assert순간 즉시 vector table로 뛰지 않는것일뿐, 이것은 software적으로 어떻게 회피하거나 지연시킬수 없습니다. (당연히 해당 interrupt는 unmask되어있을때겠죠?^^; )
그럼 interrupt가 지연된다는건 무슨 말이냐하면, interrupt vector table로 jump하는건 CPU hardware적으로 이루어지지만, 일단 그렇게 비선형동작이 이루어진 다음, 즉 interrupt service routine으로 넘어가서는 software맘대로가 되기 때문에 가능한 말입니다.
예로 priority high인 H isr이 있다고 하고, low인 L isr이 있다고 했을때,
L쪽에 map된 irq가 assert되면 당연히 L isr이 수행되겠죠.
그러면, L isr은 선택을 할수가 있습니다.
우선 모든 irq를 masking해버리고 자기자신의 루틴이 수행완료될때까지 cpu를 혼자 독점할수가 있습니다. 그러곤 자기자신 루틴의 끝에서 normal mode로 걍 전환해버리는 가장 간단한 예가 있을수 있겠죠.
이건 다른 irq를 생까버리는 동시에 L irq에 연동되는 process에게 우선권을 준달지 함으로써 irq assert직전에 수행하던 process보다 먼저수행하게하지 못하는 효과를 냅니다.
이걸 개선하고자, L isr의 말미에 context switching을 넣습니다. 그러면, L isr이 수행되고 나서 현재 대기중인 process를 priority에 따라 rescheduling하게 되어 L irq라는 resource를 기다리던 다른 process가 먼저 수행되도록 만듭니다. 개선이 이루어진것 같습니다.
다음으로는, L isr로 진입하면서 irq를 masking하지 않습니다. 한참 신나게 L isr이 수행되고 있는데, 중간에 H irq가 assert됩니다.
그러면 CPU는 바로 H irq에 map된 vector table point로 뛰겠죠? 그러면 H isr은 L isr이 수행되던 그 point는 stack해두고, 자신의 routine을 수행합니다. 왜? 자기가 더 priority가 높으니깐 새치기를 할수 있는 것입니다.
그렇게 nesting된 interrupt는 H 입장에서야 바로 수행된 꼴이지만 L입장에선 억울하게도 pending된것입니다.
그리곤 말미엔 여지없이 context switching을 통해 대기중이던 process도 새치기등의 순서 바꿔치기가 일어납니다.

preemptive하다는 것은 위에서 이야기한 새치기가 가능하다는 것을 의미합니다. 그리고 그것이 가능하기 위한 interrupt nesting mechanism과 context switching을 통한 rescheduling이 요구됩니다.

과연 그럴듯하게 헛소리를 지껄인것일까...(먼산...) :D :D :D

--------------------------------------------------------------------------------
\(´∇`)ノ \(´∇`)ノ \(´∇`)ノ \(´∇`)ノ
def ed():neTdiVeR in range(thEeArTh)

graduallyConquer의 이미지

ed군 wrote:

그리곤 말미엔 여지없이 context switching을 통해 대기중이던 process도 새치기등의 순서 바꿔치기가 일어납니다.

ed 군님 말씀 잘들었습니다.

그런데 한가지 좀더 명확했으면 하는 부분이 있어서 이렇게 글을

올립니다.

요기 위해서, 그리곤 "말미엔" 바로 여기 말미엔의 의미가,

nested되었떤 모든 인터럽트의 수행을 마치고, scheduler가 호

출이 된다는 말씀이신가요??? 커널 모드 선점형에서요?

hjfirst의 이미지

이런 류의 질문의 논쟁거리가 되기 쉬운 모양입니다.
전에도 비슷한 류의 논쟁(?)이 있었던 기억이 있는 데...

http://bbs.kldp.org/viewtopic.php?t=349&highlight=%BC%B1%C1%A1%C7%FC
찾아보니 2년도 넘게 지난 글이 네요.

하여간 제 생각에도 상우님이 거의 맞게 설명하신 게 아닌가 합니다. 덧붙여 말하고 싶지만 실력이 안되므로... :oops:

ed.netdiver의 이미지

graduallyConquer wrote:
ed군 wrote:

그리곤 말미엔 여지없이 context switching을 통해 대기중이던 process도 새치기등의 순서 바꿔치기가 일어납니다.

ed 군님 말씀 잘들었습니다.

그런데 한가지 좀더 명확했으면 하는 부분이 있어서 이렇게 글을

올립니다.

요기 위해서, 그리곤 "말미엔" 바로 여기 말미엔의 의미가,

nested되었떤 모든 인터럽트의 수행을 마치고, scheduler가 호

출이 된다는 말씀이신가요??? 커널 모드 선점형에서요?

흐, 낚이셨군녀^^;
전 사실 잘 이해가 되지 않습니다. 커널 space외에 선점이란 말이 쓰이는데가 있는지도 모릅니다. 쓰나요?
제가 적어본 글은 제가 저렇게 만들어서 쓰고 있다는 거지, 저게 정석이란 말이 아닙니다. 하긴 일반론적으로는 맞는 말 아니겠습니까?
그러니 언급하신 말미에 scheduler를 호출하건, process queue를 scramble하건, lookup table entry를 박살내건 그건 만드는 사람 맘인거지 어때야 한다는 공식이란건 없다는 겁니다.

윗분께서 말씀하신대로 이론적인 부분에서 저는 상우님 의견에 동의합니다. 그걸로 되었다고 생각해서 괜시리 끼어들지 않으려고 하다가 자꾸 이야기가 지엽적이고 피상적으로 흐르는것 같아서 이렇게 생각하는 넘도 있다는 정도, 혹은 대애충 만들어 써도 대충 그냥 돌고 쓸만하니 책 내용가지고 넘 얽매이지 않는게 좋지 않겠냐는 어줍지않은 어중이가 되본겁니다.

그렇다고 이런 논쟁이 무가치하다고 생각하지는 결코 않기 때문에,
소모적인 논쟁인양의 뉘앙스가 느껴지는듯하게 적으신 윗분의 말씀은 서운스럽긴하네요. 뭐 이렇게 생각하는 사람도 있고 저렇게 생각하는 사람도 있으니깐...

고꼬마데!

--------------------------------------------------------------------------------
\(´∇`)ノ \(´∇`)ノ \(´∇`)ノ \(´∇`)ノ
def ed():neTdiVeR in range(thEeArTh)

anfl의 이미지

Quote:

요기 위해서, 그리곤 "말미엔" 바로 여기 말미엔의 의미가,

nested되었떤 모든 인터럽트의 수행을 마치고, scheduler가 호

출이 된다는 말씀이신가요??? 커널 모드 선점형에서요?

보충해서 말씀드린다면 scheduler 호출이 interrupt nesting이 다 풀린후 호출을 하든 ISR 에서 바로 호출하든 그건 정말 만든사람 마음입니다.
하지만 빠른 ISR 완료를 요구하는 상황이라면 당연히 interrupt nesting이 다 풀린후에 scheduler를 호출하는게 맞습니다.

그리고 구조적으로 scheduler를 ISR에서 호출할수 없는 상황이 있을수도 있습니다.
그건 IRQ를 어떤 stack에서 처리하느냐가 문제인데 IRQ 처리를 task의 stack에서 처리한다면 ISR 내에서 scheduler를 호출하여도 무방합니다.
이런 경우에는 ISR 처리에 clock이 많이 소모되기 때문에 좋지 않은 방법입니다.

그리고 전용 IRQ stack을 사용하여 IRQ를 처리 할수 있습니다.
전용 IRQ stack을 사용하여 IRQ를 처리한다면 nested 된 ISR 수행이 모두 끝난후 본래 task의 stack으로 stack을 바꾼후 scheduler를 호출해야 합니다.

선점형 kernel에서 nested되었던 모든 인터럽트의 수행을 마치고, scheduler가 호출되는 것인지를 질문을 하셨는데.....
ISR 내에서 scheduler 호출이 가능하게 되려면 선점형 kernel이라는 전제 조건이 있어야 가능합니다.
하지만 nested된 interrupt가 모두 처리되고나서 scheduler를 호출하는 구조에서는 선점형 kernel이든 비 선점형 kernel이든 가능하죠.

선점형 kernel의 의미가 점점 모호해져 가고 있는데 이렇게 생각하시면 간단하실껍니다.
선점형 kernel은 kernel 모드에서 interrupt 혹은 scheduler 호출에 의해 수행중인 task 들의 atomic한 요소가 파괴되지 않게 설계된 kernel을 말합니다.
이것도 역시 지켜져야할 몇가지 대전제는 있지만 만드는 사람 마음입니다.

반대로 비선점형 kernel은 이러한것들을 보호해주지는 않죠. 그렇기 때문에 비선점형 kernel에서는 precess의 자발적 양보없이 kernel이 강제적으로 task를 바꾸는 일은 불가능하게 됩니다. (물론 kernel 모드에서 말이죠.)


ed.netdiver의 이미지

anfl wrote:
Quote:

요기 위해서, 그리곤 "말미엔" 바로 여기 말미엔의 의미가,

nested되었떤 모든 인터럽트의 수행을 마치고, scheduler가 호

출이 된다는 말씀이신가요??? 커널 모드 선점형에서요?

보충해서 말씀드린다면 scheduler 호출이 interrupt nesting이 다 풀린후 호출을 하든 ISR 에서 바로 호출하든 그건 정말 만든사람 마음입니다.
하지만 빠른 ISR 완료를 요구하는 상황이라면 당연히 interrupt nesting이 다 풀린후에 scheduler를 호출하는게 맞습니다.

그리고 구조적으로 scheduler를 ISR에서 호출할수 없는 상황이 있을수도 있습니다.
그건 IRQ를 어떤 stack에서 처리하느냐가 문제인데 IRQ 처리를 task의 stack에서 처리한다면 ISR 내에서 scheduler를 호출하여도 무방합니다.
이런 경우에는 ISR 처리에 clock이 많이 소모되기 때문에 좋지 않은 방법입니다.

그리고 전용 IRQ stack을 사용하여 IRQ를 처리 할수 있습니다.
전용 IRQ stack을 사용하여 IRQ를 처리한다면 nested 된 ISR 수행이 모두 끝난후 본래 task의 stack으로 stack을 바꾼후 scheduler를 호출해야 합니다.

선점형 kernel에서 nested되었던 모든 인터럽트의 수행을 마치고, scheduler가 호출되는 것인지를 질문을 하셨는데.....
ISR 내에서 scheduler 호출이 가능하게 되려면 선점형 kernel이라는 전제 조건이 있어야 가능합니다.
하지만 nested된 interrupt가 모두 처리되고나서 scheduler를 호출하는 구조에서는 선점형 kernel이든 비 선점형 kernel이든 가능하죠.

선점형 kernel의 의미가 점점 모호해져 가고 있는데 이렇게 생각하시면 간단하실껍니다.
선점형 kernel은 kernel 모드에서 interrupt 혹은 scheduler 호출에 의해 수행중인 task 들의 atomic한 요소가 파괴되지 않게 설계된 kernel을 말합니다.
이것도 역시 지켜져야할 몇가지 대전제는 있지만 만드는 사람 마음입니다.

반대로 비선점형 kernel은 이러한것들을 보호해주지는 않죠. 그렇기 때문에 비선점형 kernel에서는 precess의 자발적 양보없이 kernel이 강제적으로 task를 바꾸는 일은 불가능하게 됩니다. (물론 kernel 모드에서 말이죠.)

에... 좀 이해가 안되서 anfl님이 이 글타래에 남기신 다른 글들을 우선 읽어보았습니다. 또 괜한 뻘소리하면 안되니깐녀^^; (이미 했나?ㅎㅎ )

irq nesting은 반드시 우선적으로 완료해야할 기본과제가 아니었던가요? nesting이 가능한 구조로 만들어야 한다는 것과 nesting된뒤에 딴짓하다 unnesting하는것과는 큰 차이가 있습니다. 아니 만든사람 맘인거 맞지만 그렇게 만들면 irq뒷감당이 안되게되고 맙니다.
irq nesting은 irq끼리의 preemption을 이야기하는거지, irq아닌 다른 kernel code와 비교하면 무조건 isr이 우선순위가 높습니다.
그러므로 context switching은 nesting된 isr을 모두 수행완료하고 하는것이 옳다고 봅니다.

scheduler를 isr에서 호출할수 없는 상황이라...
irq stack을 task stack에서 처리한다고요? 글쎄요, 전 한번도 그런걸 본적도 그렇게 만들어본적도 없어서 속단은 어렵겠습니다만, 그런 경우도 있습니까?
게다가 그게 왜 isr처리에 clock이 많이 소모된다는건지 설명부탁드립니다. 논리상으로는 task stack을 쓰던(정말?ㅡ.ㅡ; ) irq_stack을 쓰던 stacking하는작업은 동일할텐데요?

isr내에서 scheduler호출이 가능하게 되려면 선점형 kernel이란 전제조건이 있어야 가능하다... 라는 님의 말씀에 헉. 이건 무슨 뜻이지? 했더랬습니다. 이전 님의 글을 읽어보니 선점형 커널이란 재진입가능한 코드로 새로 짠 코드다라고 하셨더군요. reentrancy가 preemption을 가늠하는 잣대다? 전 동의할수없습니다.
scheduler가 isr이 되었던 isr중의 하나인 tick에 의해서건 call되는 건 OS의 기본입니다. 선점성은 이미 irq nesting, context switching시의 task rescheduling으로 확보되는 특성인것입니다.

task들의 atomic한 요소가 파괴되지 않게 설계된 커널. 이것도 이상합니다. 그건 비선점형 kernel에서도 동일하게 요구되는 사항이니까요.
그래서 이부분, 비선점형 kernel이 보호해주지 않는다는건 말이 안됩니다.

그리고 요기, 그렇기 때문에 비선점형 kernel에서는 precess의 자발적 양보없이 kernel이 강제적으로 task를 바꾸는 일은 불가능하게 됩니다. (물론 kernel 모드에서 말이죠.)
이해가 잘... 이미 kernel space에서 말씀하고 계신중에 kernel이 task를 바꾸는 일이 불가능하게 된다구요? 그 kernel이란건 대체 뭔가요?
scheduler를 말씀하신거겠죠?

두서없이 또 주절거려봤습니다.
건전한 논쟁(처럼 보이게끔 하면서 수다떠는 놀이)문화의 창달을 위해 우리 모두 열심히 달려 봅시다. :D :D :D :D :D

--------------------------------------------------------------------------------
\(´∇`)ノ \(´∇`)ノ \(´∇`)ノ \(´∇`)ノ
def ed():neTdiVeR in range(thEeArTh)

kldpdais의 이미지

Quote:
게다가 그게 왜 isr처리에 clock이 많이 소모된다는건지 설명부탁드립니다. 논리상으로는 task stack을 쓰던(정말?ㅡ.ㅡ; ) irq_stack을 쓰던 stacking하는작업은 동일할텐데요?

isr을 처리를 하게 되면 현재의 register 정보를 저장해야 합니다.
isr을 처리하고 원래의 작업으로 복구를 하여야 하기 때문이 겠지요.
당연히 정보를 저장하게 되는데 clock이 많이 소모되는 것이라고 생각해서 글을 쓰신듯 한데....

anfl의 이미지

한번쯤 만들어 본듯하니깐 부연 설명없이 바로 설명하도록 하겠습니다.

Quote:

irq nesting은 반드시 우선적으로 완료해야할 기본과제가 아니었던가요? nesting이 가능한 구조로 만들어야 한다는 것과 nesting된뒤에 딴짓하다 unnesting하는것과는 큰 차이가 있습니다. 아니 만든사람 맘인거 맞지만 그렇게 만들면 irq뒷감당이 안되게되고 맙니다.
irq nesting은 irq끼리의 preemption을 이야기하는거지, irq아닌 다른 kernel code와 비교하면 무조건 isr이 우선순위가 높습니다.
그러므로 context switching은 nesting된 isr을 모두 수행완료하고 하는것이 옳다고 봅니다.

네. 만드는 사람 마음이지만 ISR 내에서 scheduler를 호출하게 되면 뒷 감당이 안되는건 분명하죠.
그래서 저 역시 좋지 않은 방법이라고 말했습니다. clock cycle은 뒷부분에서 다시 언급하였으니 나중에 이야기 하기로하고...

정석대로라면 ISR > call back > kernel code 순서로 우선순위를 가지고 있지요. 교과서에도 그렇게 나와있고요.
그렇지만 이건 정책상의 문제이지 "무조건 ISR이 우선순위가 높다." 라고 말할 개재는 안됩니다. 정책이 바뀌면 바뀔수도 있는 부분이니까요.

Quote:

scheduler를 isr에서 호출할수 없는 상황이라...
irq stack을 task stack에서 처리한다고요? 글쎄요, 전 한번도 그런걸 본적도 그렇게 만들어본적도 없어서 속단은 어렵겠습니다만, 그런 경우도 있습니까?
게다가 그게 왜 isr처리에 clock이 많이 소모된다는건지 설명부탁드립니다. 논리상으로는 task stack을 쓰던(정말?ㅡ.ㅡ; ) irq_stack을 쓰던 stacking하는작업은 동일할텐데요?

그런 경우가 있습니다. 아직 한번도 안보셨나 보신데...
IRQ 처리 모델은 여러가지가 있습니다. 그중에 stack과 관련된 모델도 여러가지가 존재하는데 그중에 하나가 task의 stack에서 ISR을 처리하는 방식도 있습니다.

한번 IRQ 처리 관련 문서와 논문을 잘~ 찾아 보시기 바랍니다.

이럴경우 아키텍쳐마다 틀리지만 ARM 아키텍쳐에서의 장점은 구현이 쉽다는것과 IRQ 처리 모델이 단순해 진다는것, common ISR에서 stack change를 위한 instruction이 몇개 빠질수 있다는것이 있죠.
단점으로는 각 task에 stack을 할당할때 ISR 처리를 위한 추가 용량을 고려해서 설계해야된다는 문제가 발생하지요.

Quote:

irq stack을 task stack에서 처리한다고요? 글쎄요, 전 한번도 그런걸 본적도 그렇게 만들어본적도 없어서 속단은 어렵겠습니다만, 그런 경우도 있습니까?

만들어 보시지 않았다면 한번 만들어보시기 바랍니다. common ISR 부분만 처리하면 되는데 그렇게 어렵지 않다고 말씀드리고 싶네요.

Quote:

게다가 그게 왜 isr처리에 clock이 많이 소모된다는건지 설명부탁드립니다. 논리상으로는 task stack을 쓰던(정말?ㅡ.ㅡ; ) irq_stack을 쓰던 stacking하는작업은 동일할텐데요?

제가 말한것은 ISR 내에서 scheduler를 호출할 경우를 말한겁니다. 최대한 빨리 수행을 끝마쳐야되는 ISR에서 scheduler를 호출하면 당연히 clock cycle을 많이 소비를하지요.
특히나 common ISR의 경우 interrupt latency를 어떻게든 한 cycle라도 줄일려고 pipe line의 스톨까지 고려하는데 ISR 내부에서 scheduler를 호출하면 당연히 무리가 따르지요.
물론 이미 해당 IRQ의 ISR이 호출된 상황이기 때문에 interrupt latency와는 직접적인 관련이 없더라도 ISR은 최대한 빨리 수행되어야 한다는 대전재를 위배하는 것이니깐요.
그래서 좋지 않은 방법이라고 이야기 한겁니다.

Quote:

isr내에서 scheduler호출이 가능하게 되려면 선점형 kernel이란 전제조건이 있어야 가능하다... 라는 님의 말씀에 헉. 이건 무슨 뜻이지? 했더랬습니다. 이전 님의 글을 읽어보니 선점형 커널이란 재진입가능한 코드로 새로 짠 코드다라고 하셨더군요. reentrancy가 preemption을 가늠하는 잣대다? 전 동의할수없습니다.
scheduler가 isr이 되었던 isr중의 하나인 tick에 의해서건 call되는 건 OS의 기본입니다. 선점성은 이미 irq nesting, context switching시의 task rescheduling으로 확보되는 특성인것입니다.

제대로 안 읽어 보셨나보네요.
일단 먼저 ISR 내에서 scheduler 호출은 당연히 선점형 kernel에서만 가능하다는것에는 동의 하실겁니다.
그전에 그러한 모델을 경험해보시지 않으셨기 때문에 아마 이해하기가 힘드셨나 봅니다.
그리고 저는 분명히 선점 가능한 kernel의 요건을 "선점 가능한 코드"로 구현 되어 있을때임을 대전재로 명시했습니다. "선점 가능한 코드"의 요소중에 하나가 reentrancy이구요.
이렇게 "선점 가능한 코드"로 구현이 되어 있어야 irq nesting, context switching시의 task rescheduling이 확보되지 않겠습니까? :D

Quote:

task들의 atomic한 요소가 파괴되지 않게 설계된 커널. 이것도 이상합니다. 그건 비선점형 kernel에서도 동일하게 요구되는 사항이니까요.
그래서 이부분, 비선점형 kernel이 보호해주지 않는다는건 말이 안됩니다.

비 선점형 kernel에서는 rescheduling을 없앰으로써 kernel code에서 task들의 atomic을 보호하지요. 안그런가요? :twisted:

Quote:

그리고 요기, 그렇기 때문에 비선점형 kernel에서는 precess의 자발적 양보없이 kernel이 강제적으로 task를 바꾸는 일은 불가능하게 됩니다. (물론 kernel 모드에서 말이죠.)
이해가 잘... 이미 kernel space에서 말씀하고 계신중에 kernel이 task를 바꾸는 일이 불가능하게 된다구요? 그 kernel이란건 대체 뭔가요?
scheduler를 말씀하신거겠죠?

이렇게 받이들이는거에 대해서 충분히 이해합니다. kernel mode, user mode로 나누어진 kernel의 관점에서만 보시니깐 그렇게 생각하시는 겁니다.
많은 RTOS들은 user mode가 존재하지 않고 kernel mode에서만 동작을 하죠.

이해하기 쉽게 예를 들어보죠.
kernel mode만 존재하는 RTOS에서 task가 수행중에 kernel의 API를 호출했습니다. 그러면 kernel API 코드가 수행되겠죠.
이 수행 흐름은 task의 수행 흐름일까요? 아니면 kernel의 수행 흐름일까요?
어떻게 보느냐 관점에 따라 틀리겠지만 task의 수행 흐름이라고 보는것이 맞을껍니다.

그러면 kernel API 내부에서 scheduler를 호출했습니다. 그러면 이러한 호출은 task가 schedule yield를 자신의 코드 내에서 명시적으로 호출하지 않았더라도 자발적으로 양보한것이라고 볼수가 있죠.

그러면 이러한 관점에서 user mode와 kernel mode가 있는 kernel에서 task가 호출한 kernel API에 의해 kernel mode에서 scheduler가 호출된다면 이것 또한 당연히 task가 자발적으로 양보했다고 보아야 옳습니다.
kernel mode에서 수행중인 task의 job 처리를 위한 code에서 호출한것이니
깐요. 안그런가요? :twisted: :twisted: :twisted: :twisted:


ed.netdiver의 이미지

kldpdais wrote:
인용:
게다가 그게 왜 isr처리에 clock이 많이 소모된다는건지 설명부탁드립니다. 논리상으로는 task stack을 쓰던(정말?ㅡ.ㅡ; ) irq_stack을 쓰던 stacking하는작업은 동일할텐데요?

isr을 처리를 하게 되면 현재의 register 정보를 저장해야 합니다.
isr을 처리하고 원래의 작업으로 복구를 하여야 하기 때문이 겠지요.
당연히 정보를 저장하게 되는데 clock이 많이 소모되는 것이라고 생각해서 글을 쓰신듯 한데....


네, 맞습니다. 그런데, 제가 언급한 부분은 task stack을 쓸경우 더 많은 clock을 소모하게 된다고 한 부분입니다.^^;

anfl wrote:
한번쯤 만들어 본듯하니깐 부연 설명없이 바로 설명하도록 하겠습니다.

Quote:

irq nesting은 반드시 우선적으로 완료해야할 기본과제가 아니었던가요? nesting이 가능한 구조로 만들어야 한다는 것과 nesting된뒤에 딴짓하다 unnesting하는것과는 큰 차이가 있습니다. 아니 만든사람 맘인거 맞지만 그렇게 만들면 irq뒷감당이 안되게되고 맙니다.
irq nesting은 irq끼리의 preemption을 이야기하는거지, irq아닌 다른 kernel code와 비교하면 무조건 isr이 우선순위가 높습니다.
그러므로 context switching은 nesting된 isr을 모두 수행완료하고 하는것이 옳다고 봅니다.

네. 만드는 사람 마음이지만 ISR 내에서 scheduler를 호출하게 되면 뒷 감당이 안되는건 분명하죠.
그래서 저 역시 좋지 않은 방법이라고 말했습니다. clock cycle은 뒷부분에서 다시 언급하였으니 나중에 이야기 하기로하고...

정석대로라면 ISR > call back > kernel code 순서로 우선순위를 가지고 있지요. 교과서에도 그렇게 나와있고요.
그렇지만 이건 정책상의 문제이지 "무조건 ISR이 우선순위가 높다." 라고 말할 개재는 안됩니다. 정책이 바뀌면 바뀔수도 있는 부분이니까요.

Quote:

scheduler를 isr에서 호출할수 없는 상황이라...
irq stack을 task stack에서 처리한다고요? 글쎄요, 전 한번도 그런걸 본적도 그렇게 만들어본적도 없어서 속단은 어렵겠습니다만, 그런 경우도 있습니까?
게다가 그게 왜 isr처리에 clock이 많이 소모된다는건지 설명부탁드립니다. 논리상으로는 task stack을 쓰던(정말?ㅡ.ㅡ; ) irq_stack을 쓰던 stacking하는작업은 동일할텐데요?

그런 경우가 있습니다. 아직 한번도 안보셨나 보신데...
IRQ 처리 모델은 여러가지가 있습니다. 그중에 stack과 관련된 모델도 여러가지가 존재하는데 그중에 하나가 task의 stack에서 ISR을 처리하는 방식도 있습니다.

한번 IRQ 처리 관련 문서와 논문을 잘~ 찾아 보시기 바랍니다.

이럴경우 아키텍쳐마다 틀리지만 ARM 아키텍쳐에서의 장점은 구현이 쉽다는것과 IRQ 처리 모델이 단순해 진다는것, common ISR에서 stack change를 위한 instruction이 몇개 빠질수 있다는것이 있죠.
단점으로는 각 task에 stack을 할당할때 ISR 처리를 위한 추가 용량을 고려해서 설계해야된다는 문제가 발생하지요.

Quote:

irq stack을 task stack에서 처리한다고요? 글쎄요, 전 한번도 그런걸 본적도 그렇게 만들어본적도 없어서 속단은 어렵겠습니다만, 그런 경우도 있습니까?

만들어 보시지 않았다면 한번 만들어보시기 바랍니다. common ISR 부분만 처리하면 되는데 그렇게 어렵지 않다고 말씀드리고 싶네요.

Quote:

게다가 그게 왜 isr처리에 clock이 많이 소모된다는건지 설명부탁드립니다. 논리상으로는 task stack을 쓰던(정말?ㅡ.ㅡ; ) irq_stack을 쓰던 stacking하는작업은 동일할텐데요?

제가 말한것은 ISR 내에서 scheduler를 호출할 경우를 말한겁니다. 최대한 빨리 수행을 끝마쳐야되는 ISR에서 scheduler를 호출하면 당연히 clock cycle을 많이 소비를하지요.
특히나 common ISR의 경우 interrupt latency를 어떻게든 한 cycle라도 줄일려고 pipe line의 스톨까지 고려하는데 ISR 내부에서 scheduler를 호출하면 당연히 무리가 따르지요.
물론 이미 해당 IRQ의 ISR이 호출된 상황이기 때문에 interrupt latency와는 직접적인 관련이 없더라도 ISR은 최대한 빨리 수행되어야 한다는 대전재를 위배하는 것이니깐요.
그래서 좋지 않은 방법이라고 이야기 한겁니다.

Quote:

isr내에서 scheduler호출이 가능하게 되려면 선점형 kernel이란 전제조건이 있어야 가능하다... 라는 님의 말씀에 헉. 이건 무슨 뜻이지? 했더랬습니다. 이전 님의 글을 읽어보니 선점형 커널이란 재진입가능한 코드로 새로 짠 코드다라고 하셨더군요. reentrancy가 preemption을 가늠하는 잣대다? 전 동의할수없습니다.
scheduler가 isr이 되었던 isr중의 하나인 tick에 의해서건 call되는 건 OS의 기본입니다. 선점성은 이미 irq nesting, context switching시의 task rescheduling으로 확보되는 특성인것입니다.

제대로 안 읽어 보셨나보네요.
일단 먼저 ISR 내에서 scheduler 호출은 당연히 선점형 kernel에서만 가능하다는것에는 동의 하실겁니다.
그전에 그러한 모델을 경험해보시지 않으셨기 때문에 아마 이해하기가 힘드셨나 봅니다.
그리고 저는 분명히 선점 가능한 kernel의 요건을 "선점 가능한 코드"로 구현 되어 있을때임을 대전재로 명시했습니다. "선점 가능한 코드"의 요소중에 하나가 reentrancy이구요.
이렇게 "선점 가능한 코드"로 구현이 되어 있어야 irq nesting, context switching시의 task rescheduling이 확보되지 않겠습니까? :D

Quote:

task들의 atomic한 요소가 파괴되지 않게 설계된 커널. 이것도 이상합니다. 그건 비선점형 kernel에서도 동일하게 요구되는 사항이니까요.
그래서 이부분, 비선점형 kernel이 보호해주지 않는다는건 말이 안됩니다.

비 선점형 kernel에서는 rescheduling을 없앰으로써 kernel code에서 task들의 atomic을 보호하지요. 안그런가요? :twisted:

Quote:

그리고 요기, 그렇기 때문에 비선점형 kernel에서는 precess의 자발적 양보없이 kernel이 강제적으로 task를 바꾸는 일은 불가능하게 됩니다. (물론 kernel 모드에서 말이죠.)
이해가 잘... 이미 kernel space에서 말씀하고 계신중에 kernel이 task를 바꾸는 일이 불가능하게 된다구요? 그 kernel이란건 대체 뭔가요?
scheduler를 말씀하신거겠죠?

이렇게 받이들이는거에 대해서 충분히 이해합니다. kernel mode, user mode로 나누어진 kernel의 관점에서만 보시니깐 그렇게 생각하시는 겁니다.
많은 RTOS들은 user mode가 존재하지 않고 kernel mode에서만 동작을 하죠.

이해하기 쉽게 예를 들어보죠.
kernel mode만 존재하는 RTOS에서 task가 수행중에 kernel의 API를 호출했습니다. 그러면 kernel API 코드가 수행되겠죠.
이 수행 흐름은 task의 수행 흐름일까요? 아니면 kernel의 수행 흐름일까요?
어떻게 보느냐 관점에 따라 틀리겠지만 task의 수행 흐름이라고 보는것이 맞을껍니다.

그러면 kernel API 내부에서 scheduler를 호출했습니다. 그러면 이러한 호출은 task가 schedule yield를 자신의 코드 내에서 명시적으로 호출하지 않았더라도 자발적으로 양보한것이라고 볼수가 있죠.

그러면 이러한 관점에서 user mode와 kernel mode가 있는 kernel에서 task가 호출한 kernel API에 의해 kernel mode에서 scheduler가 호출된다면 이것 또한 당연히 task가 자발적으로 양보했다고 보아야 옳습니다.
kernel mode에서 수행중인 task의 job 처리를 위한 code에서 호출한것이니
깐요. 안그런가요? :twisted: :twisted: :twisted: :twisted:

흐, 제가 앞선 posting에서 뭔가 anfl님에게 심사뒤틀릴만한 표현을 했었는지 다시한번 확인해봤습니다. 글쎄요, 전 우선 그럴 의도는 전혀 없었습니다만 혹시 anfl님께서 그렇게 느끼셨다면 사과드리죠. 여기까지 자기방어하고. "한번쯤 만들어 본듯하니깐..." 이야, 이거 참 간만에 보는 엄청난 표현이군요. :D :D
거의 무림지존에 서계신 분처럼 말씀을 하시니 몸둘바를 모르겠습니다...라고 하면 제 삐딱이근성이 꾸물거리고(야유정도는 해볼수 있겠네요..히~), 그렇다고 논쟁에 임하시는 anfl님의 자세에 대해 논하는건 님의 인생관에까지 간섭하는 간섭쟁이가 될테니 싫고, 또 글타래가 삼천포로 샐것같아 세마디로 갈음하겠습니다.
전 앞서 님께서 말씀하신 이력에는 전혀 관심이 없습니다. 님이 부품선정에서 시스템 설계, drawing, artwork, smt, startup, bsp, driver, kernel, app까지 혼자 다 하시건 이제 갓 졸업한 원생이건 그건 중요하지도, 확인할수도 없다는 것이 제 기본 입장이고, 서로를 이해시키고 설득하고 당하는 논쟁의 장에서는 서로 기분만 상하게 되기만 할 뿐인 해악이란 겁니다. 몇자 주절거림으로 제가 잘났다고 떠드려는것이 아니니, 님도 부디 같은 견지에서 이해하시어, 즐겁게 수다떨고는, 뭔가 서로 못보던 부분도 본것같고 얻은것같은 착각을 하며 shutdown할수 있도록 노력해보자는 제안을 님께 하겠습니다.

isr>callback>misc kernel code에 있어 정책이란 부분에 동의합니다. 맘대로도 맞습니다만, isr보다 우선시켜서 좋을게 뭐가 있을진 저도 잘 모르긴 하겠네요. 하긴 이건 isr에 어디까지 편입시킬것인가 하는 보다 근본적인 문제로도 귀결될테니 더 나아가는게 애매할것 같습니다.

음, irq 처리방식에 대한 것을 제기한 것이 아니라 irq stack이 아닌 task stack을 쓰는 방식의 위험성과 난이도 복잡성때문에 그렇게 말한것입니다.
이부분을 학문적으로 파본적은 없기 때문에 논문이 뭐가 있을진 저로선 잘 모르겠고, irq 처리에 관해 실제적인 수준에서 기술된 문건도 뭐가 있는지 모르겠군요. 두번째로 말씀드립니다. 적어도 이런 글타래는 적당히 아는 사람들끼리 이야기하고 있는것이니, RTFM류의 뉘앙스가 풍기는 표현은 감정싸움으로 흐르게 만드는 단초만 만드는 해악일뿐입니다. 자신을 좀 낮춰 대화하여 주시면 낮은 자리에 있는 저같은 사람들도 즐겁게 지껄일수 있다는 점. 기억해주세요.

바로 그 common isr 혹은 isr handler부분때문에 위험해서 안쓰는겁니다. 아, 쉬우니깐 해보라시니 역시 몸둘바를... :oops:

님께서 언급하신 부분을 보면 task stack을 쓸경우 clock 소모가 늘어나는것처럼 언급하신것처럼 이해되게끔 적혀 있습니다.
preemption을 부여하기 위한 scheduler call은 어쩔수없는거고 그로인한 clock처리는 당연한거죠. 그걸 task stack과 연관지으신것을 이의제기한것이랍니다.

비선점형 커널에서의 task atomic보장이란 부분은 제가 오해한것이군요.

kernel mode, user mode에 대한 기술에도 동의합니다. 제가 의문을 제기한 부분은 용어에 대한 것이었습니다. scheduler로 구체적으로 명시하시길 바란 것이었죠. task의 자발적 양보부분도 동의합니다.
하지만 task가 kernel api를 호출한다는 부분은 오해의 소지가 있습니다. kernel이 그대로 드러나있는 RTOS와 linux처럼 껍질에 단단히 싸여 있는 os의 경우가 분명히 다르니까요. 그런점에선 task와 process를 구분하여 기술해 주신점은 고맙게 생각하고 있습니다.

근데 이렇게 끝나버리면 밋밋하니, preemption에 곁들여 내주신 reentrancy에 대해 anfl님의 설명을 부탁드립니다.
선점형 커널의 전제조건이라는 부분만 정리하면 이 글타래도 어느정도 정리되는게 아닐까 하는 혼자만의 착각이 들어서입니다. :D :D

그럼 진지하게 시간내서 설명해주셔서 감사합니다.
좋은 주말 되세요.

--------------------------------------------------------------------------------
\(´∇`)ノ \(´∇`)ノ \(´∇`)ノ \(´∇`)ノ
def ed():neTdiVeR in range(thEeArTh)

anfl의 이미지

후후. 누가 먼저 고압적인 자세를 취했는지 모르겠네요.

님의 글 다음으로 부연 설명한 제 글에 제대로 이해 못하시고

Quote:

정말?ㅡ.ㅡ;

Quote:

전제조건이 있어야 가능하다... 라는 님의 말씀에 헉. 이건 무슨 뜻이지? 했더랬습니다.

라는 표현을 쓰신건 님이 아니신가요?
저라면 서로 조심스러운 입장에서 저러한 표현은 자제를 했을 겁니다.
아무리 상대방이 내가 아는 지식과 틀린것 같더라도 조금은 조심해서 물어 보았을 거라는 생각이드네요.

각설하고... 이 글타래가 소모적인 논쟁으로 끝나지 않기 위해서 님께서 지적하신것에 대해서 답변드리겠습니다.

Quote:

음, irq 처리방식에 대한 것을 제기한 것이 아니라 irq stack이 아닌 task stack을 쓰는 방식의 위험성과 난이도 복잡성때문에 그렇게 말한것입니다.

아키텍쳐 마다 틀리지만 task stack에서 IRQ를 처리하는 방식은 위험하지도 난이도의 복잡성도 높지 않습니다. 오히려 구조가 심플해지죠.
또한 ISR 내부에서 context switch 자유로움이 주어져서 ISR에서 scheduler를 호출하는 엄청난 일을 저지르는 겁없는 device driver 개발자의 실수도 용납이 가능하죠.

이러한것은 ISR top에서 중요한 일을 먼저 끝내고 또한 scheduler를 호출하기전에 interrupt를 enable하여 nesting 가능하게 했다는 전제하에서는 아무른 문제가 없습니다.

새로운 interrupt도 뜰수 있는 상태고 scheduler에 의해 수행될 task는 interrupt를 받은 task이거나 아니면 ISR에서 create한 interrupt를 받은 task보다 높은 priority의 task일거니깐요.

다만 문제는 모든 task에 stack을 할당할때 IRQ 처리를 위한 stack까지 할당함으로써 메모리 낭비를 가져올수 있다는것이 문제이지요.

Quote:

바로 그 common isr 혹은 isr handler부분때문에 위험해서 안쓰는겁니다.

무엇이 위험한지 구체적으로 이야기 해주시겠습니까? :twisted:
전혀 위험하지 않습니다. 어떤식으로 작성하느냐에 따라 장점이 될수도 있고 단점이 될수도 있는 상황이지만 위험한 상황은 될수가 없습니다.
아... 전혀 모르는 사람이 짜는건 위험한 상황이 될수도 있겠네요. 그러나 그건 kernel 관련 code 작성에서 어떠한 경우든 마찬가지이지 않습니까? :twisted:

Quote:

근데 이렇게 끝나버리면 밋밋하니, preemption에 곁들여 내주신 reentrancy에 대해 anfl님의 설명을 부탁드립니다.

reentrancy에 대해서 모를 분도 아니고...
때로는 밋밋하게 끝나는것도 여운을 남기는 운치가 있지 않겠습니까?

님과 이렇게 on line상에서 만난걸 행운으로 생각하고 또 이런 식으로 만난걸 유감으로 생각합니다.
다음에 기회가 있으면 같이 많은 이야기를 나누었으면 합니다.

그럼 좋은 주말되시기 바랍니다.


sangwoo의 이미지

오랜만에 고향인 부산에 왔더니, 여름밤이 의외로 시원하네요. 여름도 이젠 정말 막바지인 것 같습니다. :)

anfl님께서는, "'선점형 커널(preemptive kernel)' 이라고 이야기하면, 프로세스가 kernel mode에 있을 때, 그 프로세스가 명시적으로 sleep/block/call for reschedule 등을 하지 않아도 새로이 스케줄링이 이루어 질 수 있다는 것을 이야기하는 것이지, 인터럽트의 nesting이 가능하다고 해서 선점형 커널이라고 부를 수는 없다" 라고 말씀하시는 것 같습니다. 앞에 ed군 님께서는 "인터럽트의 nesting이 가능하면 preemptive라고 한다." 라고 말씀하셨는데, 제가 알기로도 "preemptive kernel"이라는 단어는 커널 모드에서 실행되는 프로세스(리눅스라면 task)들이 preemptive한가의 여부와 관련이 있을 때만 사용합니다. 인터럽트의 nesting도 물론 preemptiveness이겠지만, 그것이 가능하다고 해서 "preemptive kernel"이라는 단어는 쓰지 않는 걸로 알고 있습니다.

그리고 (제가 이해한 것이 맞다면) anfl님께서 말한 "task stack에서의 인터럽트의 처리"라는 것은, 실제적인 인터럽트 처리 루틴이 task의 context에서 일어난다는 것 같습니다. 실제로 이것과 비슷한 식으로 인터럽트를 처리하는 운영체제가 있습니다. 실험실에서만 쓰거나 embedded에서만 쓰는 녀석도 아니구요, 바로 버전 5이상의 FreeBSD입니다. :-) 다만, FreeBSD에서는 인터럽트*만을* 담당하는 interrupt handler thread라는 커널 쓰레드가 각 irq만큼 존재하게 됩니다.

제 생각에 interrupt 처리를 프로세스(or task) context에서 하게 될 때의 가장 큰 장점은, anfl님께서 말씀해 주셨듯이 '심플한 구조' 인 것 같습니다. 가령, 현재의 linux 커널은 SMP를 위한 synchronization 수단 (semaphore/spinlock)과, top half/bottom half 사이 (즉, 인터럽트 발생시)의 synchronization 수단 (인터럽트 on/off)이 혼재하고 있습니다. 하지만 interrupt가 프로세스 context에서 이루어진다면 첫번째 synchironization primitive들만 사용해도 좋죠. 현재의 FreeBSD에서는 실제로 커널 코드에 인터럽트를 명시적으로 on/off하는 call (spl 함수들이라고 부릅니다.)을 사용하지 않습니다. mutex만으로만 synchronization이 이루어집니다.

----
Let's shut up and code.

ed.netdiver의 이미지

anfl wrote:
후후. 누가 먼저 고압적인 자세를 취했는지 모르겠네요.

님의 글 다음으로 부연 설명한 제 글에 제대로 이해 못하시고

Quote:

정말?ㅡ.ㅡ;

Quote:

전제조건이 있어야 가능하다... 라는 님의 말씀에 헉. 이건 무슨 뜻이지? 했더랬습니다.

라는 표현을 쓰신건 님이 아니신가요?
저라면 서로 조심스러운 입장에서 저러한 표현은 자제를 했을 겁니다.
아무리 상대방이 내가 아는 지식과 틀린것 같더라도 조금은 조심해서 물어 보았을 거라는 생각이드네요.

각설하고... 이 글타래가 소모적인 논쟁으로 끝나지 않기 위해서 님께서 지적하신것에 대해서 답변드리겠습니다.

Quote:

음, irq 처리방식에 대한 것을 제기한 것이 아니라 irq stack이 아닌 task stack을 쓰는 방식의 위험성과 난이도 복잡성때문에 그렇게 말한것입니다.

아키텍쳐 마다 틀리지만 task stack에서 IRQ를 처리하는 방식은 위험하지도 난이도의 복잡성도 높지 않습니다. 오히려 구조가 심플해지죠.
또한 ISR 내부에서 context switch 자유로움이 주어져서 ISR에서 scheduler를 호출하는 엄청난 일을 저지르는 겁없는 device driver 개발자의 실수도 용납이 가능하죠.

이러한것은 ISR top에서 중요한 일을 먼저 끝내고 또한 scheduler를 호출하기전에 interrupt를 enable하여 nesting 가능하게 했다는 전제하에서는 아무른 문제가 없습니다.

새로운 interrupt도 뜰수 있는 상태고 scheduler에 의해 수행될 task는 interrupt를 받은 task이거나 아니면 ISR에서 create한 interrupt를 받은 task보다 높은 priority의 task일거니깐요.

다만 문제는 모든 task에 stack을 할당할때 IRQ 처리를 위한 stack까지 할당함으로써 메모리 낭비를 가져올수 있다는것이 문제이지요.

Quote:

바로 그 common isr 혹은 isr handler부분때문에 위험해서 안쓰는겁니다.

무엇이 위험한지 구체적으로 이야기 해주시겠습니까? :twisted:
전혀 위험하지 않습니다. 어떤식으로 작성하느냐에 따라 장점이 될수도 있고 단점이 될수도 있는 상황이지만 위험한 상황은 될수가 없습니다.
아... 전혀 모르는 사람이 짜는건 위험한 상황이 될수도 있겠네요. 그러나 그건 kernel 관련 code 작성에서 어떠한 경우든 마찬가지이지 않습니까? :twisted:

Quote:

근데 이렇게 끝나버리면 밋밋하니, preemption에 곁들여 내주신 reentrancy에 대해 anfl님의 설명을 부탁드립니다.

reentrancy에 대해서 모를 분도 아니고...
때로는 밋밋하게 끝나는것도 여운을 남기는 운치가 있지 않겠습니까?

님과 이렇게 on line상에서 만난걸 행운으로 생각하고 또 이런 식으로 만난걸 유감으로 생각합니다.
다음에 기회가 있으면 같이 많은 이야기를 나누었으면 합니다.

그럼 좋은 주말되시기 바랍니다.

네, 우선 앞서 지적해주신 제 표현상의 부분을 사과드리겠습니다. 다만 그건, anfl님의 말씀을 폄하하는 의미를 담아 빗겨가는듯하게 드러낸게 아니라 제 속생각. 이를테면 스스로 반문한달지 하는 식의 것을 적어놓는 그런 버릇일 뿐이었습니다.
하지만 그것자체가 님께 고압적(헉... : 이럴때 씁니다. :D )으로 비쳐질수도 있다는 점을 간과했습니다. 좀 재밌게 써보자는 생각으로 덜 딱딱하게 쓰고싶다는 의도였습니다만, 앞으로는 조심하도록 하겠습니다.(_._);;

anfl님과 sangwoo님 덕분에 많은 것을 배울수 있었습니다. 처음 이 글타래는 명예의 전당으로 옮겨지기 전쯤에 이미 일단락되어보여 끼어들기가 꺼려졌었더랬는데, 선점에 대한 개념이 제가 알고 있는 바와 좀 다르게 가고 있는것 같아 주제넘게 끼어들었던 것입니다. 그러니까, 제가 이해하고 있는 선점성이란 글자그대로 새치기라는 개념인거고, 그게 가능하도록 만들어진 OS면 선점형이란 칭호를 붙여도 된다는 말이었습니다. 뭐랄까 개념이 엄청 쉽다고나 할까요? :D

그 뒤에 나온 task stack부분은 정말이지 제가 전혀 몰랐던 부분이었습니다. irq stack이 아닌 task stack을 쓴다니... 그런데 sangwoo님의 bsd kernel에 대한 설명부분을 보고는 아~ 그렇게 쓰기도 하는구나라는 사실을 알았습니다. bsd kernel을 언제고 공부해보고싶다는 생각도 들었구요. :D

아뭏든 참여한 보람이 있는 좋은 글타래였습니다. 두분 모두 감사합니다. :D :D :D

--------------------------------------------------------------------------------
\(´∇`)ノ \(´∇`)ノ \(´∇`)ノ \(´∇`)ノ
def ed():neTdiVeR in range(thEeArTh)

kenos의 이미지

rtos나 운영체제에 대한 지식이 많이 필요하고 또 알고 싶어서
공부를 좀 했었는데 제가 아는 선에선 간단하게 말하자면

선점형: 만약에 스타크래프트가 선점 했다고 한다면,인터럽트르 제외한 어떤 프로세스도 실행을 못합니다.
스타를 종료 할 때까지요.(우선순위는 동일하다는 가정하에.)
즉슨 스타만 돌아간만 말입니다. 동시에 음악도 못듣고, 듀얼 모니터로
옆에서 애니 틀어놨다면 애니는 정지되겠죠.

비선점형: 운영체제가 프로제스에게서 자원을 뺏을 수 있습니다. 스케줄링 방법에는 여러가지가
있겠죠.(보통 큐 방식을 쓰죠. 스케쥴링도 파고들면 무지 많고, 어렵습니다.)
즉 지금 윈도우는 비선점으로 돌아갑니다. 프로세스가 시피유를 내놓지 않아도
운영체제가 인터럽트 후에 스케쥴링해서 다른 프로세스에게 시피유를 할당하지요.

뭐 제가 아는 선에서 간단하게 적었습니다. 일하는 와중에 이런거 적어서 대략 난감;;;;;
소히말해 땡땡이 !!

페이지

댓글 달기

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
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.