[질문] preemtive와 nonpreemtive?

firster의 이미지

유닉스에 맛들인지 얼마되지 않은 초보입니다. 음, 프로그래밍도 초보라고 할 수 있습니다.
unix internals라는 책을 구입해서 보고있는 중에 꽤 자주 나오는 단어인데, 제가 어렴풋이 알고있는 지식으론 오히려 이해에 방해가 되는 것 같아서 여기 질문을 올립니다.

한글로는 선점형(preemtive)과 비선점형(nonpreemtive)이라고 말하며, 선점형은 OS가 주도권을 독점하여 스케쥴링에 의해서 우선권이 높은 프로세스에게 CPU 사용권을 넘긴다 정도만 알고 있습니다. 뭐.. 그 와중에도 OS는 항상 감시의 눈을 떼지 않는다는 추상적이고 대략적인 감만 잡고있는 수준입니다. 반대로, 비선점형은 실행중인 프로세스에게 모든 제어권이 있어서 해당 프로세스의 잘못으로 인하여 다른 프로세스나 OS 자체에까지 큰 영향을 미칠 수 있다는 것으로 알고있는데요.

이책을 읽다보니 제가 너무 무식하다는 생각이 또 다시 들더군요. 제가 이해하고 있는 것대로는 제대로 의미 연결이 되지 않습니다. 아마도 잘못 혹은 어설프게 알고 있는 것 같습니다.

너무 개념적이고 추상적인 질문인 것도 같지만 선점형과 비선점형이 무엇인지 나름대로 이해하고 있는 바를 듣고 싶습니다. 상세히 예문을 적어야겠지만 지금 그럴 수 없는 입장이고 당장은 조금이라도 정확한 의미를 알고 싶어서 질문을 올립니다.
답변에 미리 감사드립니다.

체스맨의 이미지

정의, 차이점은 책에서 보신 그대로 이구요. 한가지 예를 들겠습니다.

대표적 선점형 OS linux 와 대표적 비선점형 OS(?) Windows 3.1 이 있습니다.

협동형 멀티태스킹이라고도 불리는 비선점형 OS 윈3.1 은 임의 응용프로그램이
임의의 작업을 수행하고 제어권을 다른 프로그램에 넘겨주지 않으면
(협조적으로 나오지 않으면), 다른 프로그램이 실행될 수 없습니다.
예를 들어 한 프로그램이 while(1) {} 을 하면 다른 프로그램은
실행 불가능한 상태가 되지요. 그래서 GetMessage 나 PeekMessage
등으로 제어권을 응용프로그램이 넘깁니다. OS 가 주도권을 가지고
있지 못하죠.

결국 비선점형에서는 임의 시점에서 오직 하나의 프로세스만 실행권을
가지고 있습니다. 그래서 스레드,뮤텍, 세마포어 등의 개념들이 있을
필요가 없구요. 따라서 메모리 관리나 기타 자원 관리 전략도 아주 심플해
집니다. 이런 특성에 의해 운영체제의 안정성이 각 응용 프로그램의 안정성에
의해 좌우될 가능성도 매우 높아지게 됩니다.

반면 선점형 OS 인 리눅스는 위의 예에서 임의 프로그램이 독점적으로 무한
루프를 설정하더라도, 자체 스케쥴링에 의해 다른 프로그램에게 실행권을
넘길 수 있고, 필요에 따라 프로세스를 죽일 수도 있습니다.
비선점형과 달리, 임의 시점에서 둘 이상의 프로세스가 실행될 수 있으므로,
임의의 자원이 동시에 사용되는 경우가 발생하는 경우를 위해
뮤텍, 세마포어, 공유 메모리 개념 등이 나오게 됩니다.
필연적으로 자원 관리 방법도 비선점형의 경우와 차이가 있게 되지요.
OS 가 프로그램의 실행과 종료권을 독점하므로, 프로그램의 불안정성은
오직 그 프로그램에만 국한되어 운영체제의 안정성을 보장할 수 있습니다.

제가 말씀드린 것을 비롯해서 더 깊은 내용들은 책에서 얻으실 수 있을 겁니다.

Orion Project : http://orionids.org

tifler의 이미지

덧달아서 한가지 말씀만 드리겠습니다.

선점형과 비선점형을 논할때는 그 기준을 명확히 해야할 듯 합니다.

즉 커널과 프로세스로 구분해서 논해야 할것 같군요.

리눅스 커널 자체는 비선점형입니다. 하지만 리눅스 커널 위에서 동작하는
프로세스는 선점형이죠.

즉 다음과 같은 코딩으로 간단히 테스트 해 볼 수 있습니다.

/* 커널의 비선점성(커널모듈) 
   커널자체가 아무 응답이 없어집니다. */
int init_module()
{
	while(1)	;
	return 0;
}

/* 프로세스의 선점성 
   프로세스의 CPU점유율만 높아질뿐 동작에는 문제가 없죠. */
int main()
{
	while(1)	;
	return 0;
}

즉 커널모듈로 로드를 했을경우는 커널레벨에서 동작하고 커널이 비선점형이므로
절대로 CPU의 사용권을 반납하지않죠.
하니만 유저레벨 프로세스는 커널의 간섭을받아 일정 quantum이 지나게되면
커널이 CPU를 회수하여 다른 프로세스에게 돌려주게 됩니다.

/***********************
* while(1) sleep(INFINITE);
***********************/

체스맨의 이미지

우선, 커널은 비선점형이고, 커널 위에서 동작하는 프로세스는 선점형이라는
것은 제가 모르는 부분인 것 같네요. 저는 선점형이라 할 때는 커널이
프로세스를 어떻게 다루는 지에 관한 정의를 말하는 것으로 할고 있었거든요.

그런데 어쨌든, 커널의 비선점성 이라는 개념이 있다 하더라도,
지금 제시하신 커널 모듈 예는 그 개념에 부합하는 예가 될 수 없다고
생각합니다. 커널 모듈은 마치 프로세스의 주소 공간으로 동적으로
로드되는 공유 라이브러리와 같아서, 공유라이브러리의 임의 함수가
무한 루프를 잡으면 해당 프로세스가 먹통이 되는 건 당연한 일입니다.
이건 선점형, 비선점형을 따질 문제가 아니죠.

커널 모듈 역시 커널의 주소 공간으로 로드되어 실행되는 일종의
동적 라이브러리와 같다는 것이죠.

여기 한 줄 수정 합니다. 좀 잘 못 적은 것 같아서...
혹시 모노리딕과 마이크로 커널을 언급하신 것이라면 마이크로 커널에
말씀하신 개념이 있는지요?

Orion Project : http://orionids.org

익명 사용자의 이미지

tifler wrote:
덧달아서 한가지 말씀만 드리겠습니다.

선점형과 비선점형을 논할때는 그 기준을 명확히 해야할 듯 합니다.

즉 커널과 프로세스로 구분해서 논해야 할것 같군요.

리눅스 커널 자체는 비선점형입니다. 하지만 리눅스 커널 위에서 동작하는
프로세스는 선점형이죠.

즉 다음과 같은 코딩으로 간단히 테스트 해 볼 수 있습니다.

/* 커널의 비선점성(커널모듈) 
   커널자체가 아무 응답이 없어집니다. */
int init_module()
{
	while(1)	;
	return 0;
}

/* 프로세스의 선점성 
   프로세스의 CPU점유율만 높아질뿐 동작에는 문제가 없죠. */
int main()
{
	while(1)	;
	return 0;
}

즉 커널모듈로 로드를 했을경우는 커널레벨에서 동작하고 커널이 비선점형이므로
절대로 CPU의 사용권을 반납하지않죠.
하니만 유저레벨 프로세스는 커널의 간섭을받아 일정 quantum이 지나게되면
커널이 CPU를 회수하여 다른 프로세스에게 돌려주게 됩니다.


무한 루프를 돌려서 안죽는 커널은 존재하지 않습니다. 따라서 커널 자체의 선점/비선점 구분은 무의미합니다.
익명 사용자의 이미지

체스맨 wrote:
혹시 모노리딕과 마이크로 커널을 언급하신 것이라면 마이크로 커널에
말씀하신 개념이 있는지요?

없습니다. 마이크로커널에도 여전히 스케줄러는 커널 안에 있으니까요.
tifler의 이미지

음 글쎄요...

제말보다는 객관적인 자료가 필요한 시점인가 봅니다.

다음 링크를 보시고나서 다시 생각해 보시면 감사하겠습니다.

[url]
http://lachesis.pe.kr/documents/schedule/sort-of-kernel.html
[/url]

체스맨 wrote:
우선, 커널은 비선점형이고, 커널 위에서 동작하는 프로세스는 선점형이라는
것은 제가 모르는 부분인 것 같네요. 저는 선점형이라 할 때는 커널이
프로세스를 어떻게 다루는 지에 관한 정의를 말하는 것으로 할고 있었거든요.

그런데 어쨌든, 커널의 비선점성 이라는 개념이 있다 하더라도,
지금 제시하신 커널 모듈 예는 그 개념에 부합하는 예가 될 수 없다고
생각합니다. 커널 모듈은 마치 프로세스의 주소 공간으로 동적으로
로드되는 공유 라이브러리와 같아서, 공유라이브러리의 임의 함수가
무한 루프를 잡으면 해당 프로세스가 먹통이 되는 건 당연한 일입니다.
이건 선점형, 비선점형을 따질 문제가 아니죠.

커널 모듈 역시 커널의 주소 공간으로 로드되어 실행되는 일종의
동적 라이브러리와 같다는 것이죠.

여기 한 줄 수정 합니다. 좀 잘 못 적은 것 같아서...
혹시 모노리딕과 마이크로 커널을 언급하신 것이라면 마이크로 커널에
말씀하신 개념이 있는지요?

/***********************
* while(1) sleep(INFINITE);
***********************/

체스맨의 이미지

제가 제시한 논점은 다음과 같습니다.

1. 커널 자체의 선점성과 프로세스 선점을 구분하는 것은 제가 몰랐던 내용이라는 것을 전제 했구요.

2. 커널 자체의 선점성 개념이 있다 하더라도, 제시하신 커널 모듈 예가 그 개념에 대한 적절한 예가 될 수 없다는 근거를 제시했습니다.

링크하신 자료 1장을 보면,
"이 문서는 저자가 공부하던 내용을 그냥 정리해 본 것입니다. "
라고 돼 있어서, 객관적인 자료로서 완전히 의미를 부여하기엔 조금 부족해 보이구요.
조금 더 다른 출처가 있었으면 좋겠습니다.

그리고, 2장을 보면
"프로세스들을 스케쥴링하고, 제어하는 방식에 따라서 선점형(preemptive)커널과 비선점형(non-preemptive)커널로 분류할 수 있다."
처럼, 선점, 비선점은 '프로세스 스케쥴링 방식'에 의해 분류된다고 언급하고 있습니다.

"커널레벨의 수행 패스에서까지 선점형으로 제작된 커널..."
이라는 문장이 나오는데, '수행 패스'를 프로세스 스케쥴링이 의미하는 범주에 포함시킬 수 있다면 말씀하신 개념을 고려해야 겠지요.

어쨌든 말씀하신 구분은 몰랐던 내용이고, 좀 더 자료가 있었으면 좋겠구요.

Orion Project : http://orionids.org

sliver의 이미지

커널 자체도 preemptive/non-preemptive kernel로 나누어 집니다.

리눅스 같은 경우는, 어떤 process가 kernel mode에서 실행중 일때,

꼭 자기 자신이 schedule()을 불러야만이 context switch가 발생합니다.

즉, non-preemptive kernel입니다.

하지만 왠만한 RTOS일 경우는(QNX 등등), 언제라도 interrupt나 preemption이 disable되어 있지 않은 상황에서,

더 높은 priority의 process가 runnable되면 바로 context switch가 발생하게 됩니다.

예를 들면, I/O를 기다리고 있는 높은 priority의 process가, I/O가 완료됨에 따라 다시 runnable해지는 경우가 있겠지요.

p.s. 요즘 리눅스 커널을 fully-preemptive kernel로 바꾸는 작업이 진행 중에 있다고 알고 있습니다.

arimae의 이미지

Understanding Linux Kernel 이란 책의 2장을 보면 리눅스 커널 자체는 non-preemptive 라고 설명이 나옵니다.
따라서 커널 함수 수행 도중에는 위에서 언급하신 분의 말처럼 임의로 빠져나올수 없고, 이런 특성 때문에 일정 시간의
response time(Dead line) 을 충족시켜야 하는 RTOS에는
적합하지 않다고 나오는군요.

Dream, Passion and Challenge..

체스맨의 이미지

예 개념적으로 이해가 되네요. 제가 몰랐던 부분은 해결이 된 것 같구요.

하지만, 커널 모듈은 여전히 커널이 비선점형이라는 데 대한
좋은 예는 아니라고 생각됩니다.

Orion Project : http://orionids.org

sliver의 이미지

저는 좋은 예라고 생각합니다 :)

리눅스같은 non-preemptive kernel은 커널 모드에서 while(1);을 해버리면,

절대 다른 process는 스케줄 될 수가 없죠. 한마디로 컴퓨터가 멈추어 버립니다.

하지만 preemptive kernel의 "커널모드"에서 인터럽트가 enabled된 상태에서,

while(1);을 실행했다고 합시다.

어느 순간 interrupt가 발생해서 I/O완료를 기다리고 있던, priority가 높은 process가 다시 runnable해지면,

그 process가 스케줄이 되어 실행되게 됩니다.

따라서 컴퓨터가 항상 멈추어 버리지는 않습니다.

다만, while(1);을 수행하고 있는 process보다 낮은 priority를 가지고 있는 process들은

더이상 스케줄이 될 수 없겠지요.

체스맨의 이미지

우선 이 쪽으로 더 깊은 지식은 제가 없기 때문에 용어상, 개념상 이상한 점은 양해 바라구요.

그렇다면, 선점형 커널인 경우

커널이 동적으로 로드된 커널 모듈 초기화를 위해 init_module을 호출할 때
init_module 에서 while(1); 이 걸려도,
인터럽트가 발생해서 다른 프로세스가 스케쥴 되면
그 프로세스의 커널에 대한 요구가 적절히 실행 되는 것인지요?

이것은 각 커널 모듈의 함수 호출도 별도의 프로세스처럼 선점되어 실행된다는 것을 의미합니까?

Orion Project : http://orionids.org

체스맨의 이미지

공부 좀 하고 왔습니다.
제 전문 분야가 아니라, 제 지식이 짧았네요.
좋은 답글들 많이 도움이 됐습니다.

아뭏든, 잘 모르는 분야 공부하려니
골치가 다 아프네요.

Orion Project : http://orionids.org

junghwanz의 이미지

선점형 커널인 경우에는
어떤 특정한 규칙에 의해서 커널도 스케줄링이 될 것입니다.
이경우에는 스케줄러만을 독립적으로 따로 두어야 되겠군요.
마치 커널위에 또다른 커널이 있는것과 같은 개념이 되겠네요.
어차피 context switch와 같은 구현들도 해야 할테니까요
아니면 현재의 리눅스에서 스케줄러만을 priority 1순의로 하로 커널모드에서 수행되는 것들을 스케줄링해도 preemptive kernel이 되겠군요

송지석의 이미지

임베디드를 위해 Real time linux 프로젝트와 회사들이 여럿 있습니다.

커널 코드 자체를 수정하거나

커널에 모듈형태로 리얼타임 부분을 추가하는 형식입니다.

혹시 관심있으시면 자세한 것은 구글을.. (저도 써본 적은 없습니다만.. PC에서도 돌아간다는군요)

RTAI RTLINUX 등이 그 예가 되겠지요..

커널에 preemption을 지원시킨다는 게 정말인가요? 음. 그 회사들 어떻게 먹고 살지? ^^;; 아마 오픈소스로 진행되는 프로젝트와 realtime리눅스 회사들이 커널 개발에 관여하게 되는 게 아닐까 합니다.RTLinux등등 회사에서도 리눅스 커널 쪽 지원을 하는 것 같고 몬타비스타는 커널의 실시간화에 꽤 공헌한다고 들었습니다.

익명 사용자의 이미지

제가 알고 있기로는 선점가능한 커널이란 커널 컨텍스트에 존재하는 사용자 프로세스로부터 스케줄러가 제어권을 빼앗아올 수 있는 구조로 된 커널을 뜻합니다. 예를 들어 어떤 프로세스가 입출력을 하기 위해 시스템콜을 통해 커널에 진입하면, 비선점형 커널은 시스템콜이 종료되고 컨텍스트가 다시 사용자 모드로 넘어가기 전까지 제어권을 빼앗아오지 못합니다. 따라서 입출력 시간이 길어지면 전체적인 시스템의 반응성이 눈에 띄게 느려지는 것이죠(디스크 읽고 쓰기가 한참중일 때 마우스가 먹통이 되거나 점프를 하는 현상, 음악 끊기는 현상 등).

이것은 디바이스 드라이버에서 무한 루프를 돌려서 죽으면 비선점형, 안죽으면 선점형이라고 구분하는 것과는 관계가 없습니다.

무엇보다 리눅스에서 선점형 커널 패치로 이와 같은 일을 직접 해보신 분이 가장 정확한 답을 알고 계실 것 같습니다.

wish의 이미지

커널 자체가 선점형 / 비선점형이라는 말 보다는...

커널 모드에서 돌고 있는 프로세스의 선점성과 비선점성을 말하는게 명확하겠네요.

리눅스는 커널모드에서 비선점형 OS 맞습니다.

예를 들어 시스템 콜이 호출 되고 트랩이 걸려서 커널 코드가 실행 되고 있는데, 그 커널 코드에 무한 루프가 들어가 있다면, 리눅스는 죽습니다. 선점형 OS라면 클럭 인터럽트의 인터럽트 핸들러가 그 프로세스를 끌어내리고 다른 프로세스를 올릴 수 있어야 합니다.

다만 리눅스 최신 개발 버전의 경우 선점형 스케줄링 옵션이 들어 있는 것을 보았습니다.

wish의 이미지

아 그리고 커널 모듈 예는 가만히 생각해보니까 제 생각에는 맞는 듯 보입니다.

커널 모듈을 올리는 것은 커널 코드를 고치는 것입니다.

커널 코드를 고치려면, 그 역활을 담당하는 프로그램(프로세스)은 커널 모드로 진입해야 합니다. 아마 커널을 고치는 시스템 콜이 있겠지요. 그 콜이 불리면 커널은 커널 모듈을 relocation 해서 커널 코드를 고칠 것입니다. 그리고 나서 그 모듈중 init 함수를 실행하겠지요.

그렇다면 insmod 프로세스가 커널모드로 진입한 상태에서 무한루프에 빠지는 것입니다. 이미 커널 모드인 상태에서 무한 루프이기 때문에, 리눅스 같은 비선점형 OS는 커널 모드에 진입되어 있는 insmod 프로세스를 끌어내릴 수가 없습니다.

선점형 OS에서는 프라이어티가 높은 다른 프로세스가 웨이팅 큐에 있다면, 리얼타임 클럭의 인터럽트가 걸렸을 때, 수행되는 인터럽트 핸들러가 스케쥴 함수를 부를 것이기 때문에, 현재 무한 루프를 돌고 있는 커널 모드에 있는 insmod 프로세스를 내리고, 가장 높은 프라이어티의 다른 프로세스를 Running 상태에 둘 것입니다.

앞에서도 같은 말씀을 하신분이 계신 것 같은데, 저도 개념 정리하는 차원에서.. 몇자 다시 적습니다. ^^

송지석의 이미지

RTLinux의 예제 프로그램에 보면 realtime이란 것이 어떻게 테스트 가능한지 나와있습니다.

hello 커널 모듈을 올리고 그안에서 루프를 돌게 한 뒤 다른 응답을 할 수 있는 지를 테스트 하는 것 같더군요.

음. 저도 잘 기억이 안나네요 궁금하실 것 같으니 좀 더 찾아보고 글 수정을 하도록 하죠.

----------추가--------
찾느라 힘들었네요..

#include <rtl.h>
#include <time.h>
#include <pthread.h>

pthread_t thread;

void * start_routine(void *arg)
{
	struct sched_param p;
	p . sched_priority = 1;
	pthread_setschedparam (pthread_self(), SCHED_FIFO, &p);

	pthread_make_periodic_np (pthread_self(), gethrtime(), 500000000);

	while (1) {
		pthread_wait_np ();
		rtl_printf("I'm here; my arg is %x\n", (unsigned) arg);
	}
	return 0;
}

int init_module(void) {
	return pthread_create (&thread, NULL, start_routine, 0);
}

void cleanup_module(void) {
	pthread_delete_np (thread);
}

가장 간단한 테스트 예제입니다.

커널 쓰레드를 만들어서 돌리다가(바로 무한루프는 아니었군요. ;-)) rmmod로 종료시킬 수 있는 지 테스트 하는 군요.

익명 사용자의 이미지

	while (1) {
		pthread_wait_np ();
		rtl_printf("I'm here; my arg is %x\n", (unsigned) arg);
	}

비선점형 커널인 BSD도 페이지대몬이 위와 같은 구조로 동작하는데요(무한 루프 도중에 잠들었다가 깨어나면 일하고 다시 잠드는 구조). 이 예로써 선점성이나 리얼타임을 증명하는 것은 불충분하다고 봅니다.

sliver의 이미지

방준영 wrote:
	while (1) {
		pthread_wait_np ();
		rtl_printf("I'm here; my arg is %x\n", (unsigned) arg);
	}

비선점형 커널인 BSD도 페이지대몬이 위와 같은 구조로 동작하는데요(무한 루프 도중에 잠들었다가 깨어나면 일하고 다시 잠드는 구조). 이 예로써 선점성이나 리얼타임을 증명하는 것은 불충분하다고 봅니다.

page daemon의 경우는 저런 식으로 무한루프이긴 하겠지만, 계속 깨어있는게 아니라 할 작업을 마치고

sleep함으로써 "스스로" cpu를 내놓는데요..;;

반면에 저 무한루프는 cpu를 스스로 내놓는 부분이 없습니다.

wish의 이미지

silver 님 말씀이 정확한 듯 싶습니다.

커널 모드에서 preemtive, non-preemtive의 구분은 Hardware Interrupt Service Rutine 에서, 스케쥴 함수를 부르느냐 안부르냐의 차이에 있습니다. preemtive 커널은 어떠한 형식으로든 ISR(특히 리얼 차임 클럭 인터럽트)에 리스케줄을 위한 방편이 있어야 합니다.

준영님 예는 강제로 스케줄링이 되는 것이 아니라, 스스로 정기적으로 잠들기 때문에 그 사이에 스케줄링이 일어날 수 있게 만드는 것입니다. pthread_wait_np (); 요 함수를 빼버리고 커널을 돌리면 바로 죽겠지요.

익명 사용자의 이미지

sliver wrote:
방준영 wrote:
	while (1) {
		pthread_wait_np ();
		rtl_printf("I'm here; my arg is %x\n", (unsigned) arg);
	}

비선점형 커널인 BSD도 페이지대몬이 위와 같은 구조로 동작하는데요(무한 루프 도중에 잠들었다가 깨어나면 일하고 다시 잠드는 구조). 이 예로써 선점성이나 리얼타임을 증명하는 것은 불충분하다고 봅니다.

page daemon의 경우는 저런 식으로 무한루프이긴 하겠지만, 계속 깨어있는게 아니라 할 작업을 마치고

sleep함으로써 "스스로" cpu를 내놓는데요..;;

반면에 저 무한루프는 cpu를 스스로 내놓는 부분이 없습니다.


pthread_wait_np()는 현재 쓰레드를 일시중단시키고 제어권을 내놓는 함수인데요.

http://www.fsmlabs.com/developers/docs/html/MAN/pthread_wait_np.3.html

wish의 이미지

Quote:

반면에 저 무한루프는 cpu를 스스로 내놓는 부분이 없습니다.

pthread_wait_np()는 현재 쓰레드를 일시중단시키고 제어권을 내놓는 함수인데요.

제 생각이 맞다면,

여기서 "저 무한루프"가 가르키는 바는...
아마도 준영님 코드가 아니라 실버님께서 올린 RTOS 예제인듯합니다.

BSD 페이지데몬이 CPU에 제어권을 스스로 넘겨주는 부분이 있구요.

페이지데몬 소스의 경우는 대표적인 non-preemtive 커널의 소스인듯 보입니다. preemtive 의 경우는 저렇게 스스로 CPU를 내놓지 않아도... 필요하다면 스케쥴링을 강제로 시켜야 합니다.

익명 사용자의 이미지

wish wrote:
silver 님 말씀이 정확한 듯 싶습니다.

커널 모드에서 preemtive, non-preemtive의 구분은 Hardware Interrupt Service Rutine 에서, 스케쥴 함수를 부르느냐 안부르냐의 차이에 있습니다. preemtive 커널은 어떠한 형식으로든 ISR(특히 리얼 차임 클럭 인터럽트)에 리스케줄을 위한 방편이 있어야 합니다.

준영님 예는 강제로 스케줄링이 되는 것이 아니라, 스스로 정기적으로 잠들기 때문에 그 사이에 스케줄링이 일어날 수 있게 만드는 것입니다. pthread_wait_np (); 요 함수를 빼버리고 커널을 돌리면 바로 죽겠지요.


그럼 제 말이 맞지 않나요? 8)

선점성을 증명하기 위한 예제에 pthread_wait_np()처럼 중간에 자는 부분이 있는 무한루프를 사용한 것은 적절한 예가 아니란 생각입니다. 만일 pthread_wait_np()를 빼서 커널이 죽어버리면 이것은 선점/비선점을 구분하는 기준이 무한루프와는 관련이 없다는 뜻이죠. 반대로 안죽으면 관련이 있다는 것이구요(비선점형 커널에선 반드시 죽으니까).

제가 궁금한 것은 실제로 선점형 커널에서 진짜 무한루프(중간에 자는 것 말고)를 돌려서 죽나 안죽나를 시험해 본 분이 있는가하는 것입니다.

wish의 이미지

실수 맞습니다...

죄송합니다 .. ㅜㅜ

제가 잠시 잘못 읽었네요...
준영님 말이 맞습니다. 사실 무한루프만 보고 코드를 안 읽었더니 저런 함수가.

그래도 확실한 건 선점형 커널은 커널 모드에 진입한 프로세스 조차도 도중에(커널 코드를 실행하는 중이더라도) 스케줄링이 가능해야 합니다. :)

sliver의 이미지

제가 pthread_wait_np()에 관해 잘못 알았군요..ㅡ.ㅜ

방준영 wrote:

제가 궁금한 것은 실제로 선점형 커널에서 진짜 무한루프(중간에 자는 것 말고)를 돌려서 죽나 안죽나를 시험해 본 분이 있는가하는 것입니다.

OS라고 하기는 좀 그렇지만,

unix위에서 시뮬레이션되는 NachOS가 preemptive kernel인데,

무한루프를 돌려도 그 쓰레드만 삽질-_-;;을 하고

나머지는 정상적으로 돕니다.

송지석의 이미지

옷 제가 올린 글 때문에 이렇게 많은 글을 올리셨군요.

함수 이름 뒤에 붙은 np가 non-preemptable 의 약자일 줄 알았는데 보니 non-portable이로군요.. ( http://www.fsmlabs.com/developers/docs/html/MAN/pthread_wait_np.3.html )

음 어쨌거나 왜 그 예제에서 무한루프로 돌리지 않고 저렇게 했는 지 궁금하군요..

다른 예도 찾아봐야 하나.. 음..

withlhw의 이미지

여기서 선점과 비선점이라고 하는것은 리눅스에서 어떤 스케줄러를 사용하는

가에 따라서 결정이 됩니다. 일반적인 리눅스의 경우 스케줄러로 라운드로빈을

사용합니다. 그러니 당근 리눅스 커널의 경우 선점방식입니다.

charsyam의 이미지

지금 논의가 되고 있는것이 리눅스를 preemptable 라고 부르긴 하지만,

사실은 스스로 schedule 함수를 부르면서 스케줄링이 일어나기 때문에

정확한 preemptable OS라고 하기 힘들다 아닌가요? 예를 들어서,

정말 RTOS라면 중요한 프로세서가 생성되면, 그 순간 제어권이 넘어가야

되는데, 리눅스에서는 실제로 프로세스가 schedule 을 수행했을 때, 제어권이

넘어가는 것 아닙니까? rtlinux 같은 것도 좀더, 리눅스에서 RT를 강조할려고

나온것이 아닐런지... 쩝... 그럼 고운 하루되시길...

=========================
CharSyam ^^ --- 고운 하루
=========================

익명 사용자의 이미지

charsyam wrote:
지금 논의가 되고 있는것이 리눅스를 preemptable 라고 부르긴 하지만,

사실은 스스로 schedule 함수를 부르면서 스케줄링이 일어나기 때문에

정확한 preemptable OS라고 하기 힘들다 아닌가요? 예를 들어서,

정말 RTOS라면 중요한 프로세서가 생성되면, 그 순간 제어권이 넘어가야

되는데, 리눅스에서는 실제로 프로세스가 schedule 을 수행했을 때, 제어권이

넘어가는 것 아닙니까? rtlinux 같은 것도 좀더, 리눅스에서 RT를 강조할려고

나온것이 아닐런지... 쩝... 그럼 고운 하루되시길...


용어와 개념상의 혼동이 있는 것 같습니다. 맨처음 질문하신 분의 요지는 선점형과 비선점형이 무엇이냐였고, 지금 얘기가 오가고 있는 것은 스케줄러뿐만 아니라 커널 자체도 선점 가능하냐 안하냐에 관한 것입니다.
next의 이미지

charsyam wrote:
지금 논의가 되고 있는것이 리눅스를 preemptable 라고 부르긴 하지만,

사실은 스스로 schedule 함수를 부르면서 스케줄링이 일어나기 때문에

정확한 preemptable OS라고 하기 힘들다 아닌가요? 예를 들어서,

정말 RTOS라면 중요한 프로세서가 생성되면, 그 순간 제어권이 넘어가야

되는데, 리눅스에서는 실제로 프로세스가 schedule 을 수행했을 때, 제어권이

넘어가는 것 아닙니까? rtlinux 같은 것도 좀더, 리눅스에서 RT를 강조할려고

나온것이 아닐런지... 쩝... 그럼 고운 하루되시길...

리눅스 커널 자체는 비선점형입니다.(동작하는 프로세스들의 스케쥴링 방식이 선점형입니다.)

RTOS의 조건이라면 프로세스가 생성되면 제어권이 넘어 가는것이 아니라 마감시간(deadline) 을 맞출 수 있도록 스케쥴링 하는 것입니다. 그런점에서 리눅스 커널모드의 비선점은 Hard RealTime의 조건을 만족하기가 어렵겠지요.

참고로 rtlinux는 리눅스 커널 자체를 우선순위가 낮은 하나의 커널 쓰레드로 취급한다고 합니다.

totohero의 이미지

방준영 wrote:

제가 궁금한 것은 실제로 선점형 커널에서 진짜 무한루프(중간에 자는 것 말고)를 돌려서 죽나 안죽나를 시험해 본 분이 있는가하는 것입니다.

제가 솔라리스용 드라이버를 짤 기회가 있어 드라이버 모듈 초기화 함수에 while (1) ; 을 넣어보았더니 모듈 로딩 작업은 멎어버렸지만 다른 작업은 모두 잘 되는군요. 방준영님께서는 preemptive kernel이란 커널 컨텍스트에 존재하는 사용자 프로세스로부터 스케줄러가 제어권을 빼앗아올 수 있는 구조로 된 커널이라고 한정하셨던 듯 한데 (저도 preemptive kernel에 대한 정확한 정의를 본적이 없어서 묻습니다만) 어디에 나와 있는 정의인지요?
choissi의 이미지

totohero wrote:
방준영 wrote:

제가 궁금한 것은 실제로 선점형 커널에서 진짜 무한루프(중간에 자는 것 말고)를 돌려서 죽나 안죽나를 시험해 본 분이 있는가하는 것입니다.

제가 솔라리스용 드라이버를 짤 기회가 있어 드라이버 모듈 초기화 함수에 while (1) ; 을 넣어보았더니 모듈 로딩 작업은 멎어버렸지만 다른 작업은 모두 잘 되는군요. 방준영님께서는 preemptive kernel이란 커널 컨텍스트에 존재하는 사용자 프로세스로부터 스케줄러가 제어권을 빼앗아올 수 있는 구조로 된 커널이라고 한정하셨던 듯 한데 (저도 preemptive kernel에 대한 정확한 정의를 본적이 없어서 묻습니다만) 어디에 나와 있는 정의인지요?

테스트 하신 환경의 cpu가 몇개짜리 인가요?

울랄라~ 호기심 천국~!!
http://www.ezdoum.com

kyong의 이미지

tifler wrote:
덧달아서 한가지 말씀만 드리겠습니다.

선점형과 비선점형을 논할때는 그 기준을 명확히 해야할 듯 합니다.

즉 커널과 프로세스로 구분해서 논해야 할것 같군요.

리눅스 커널 자체는 비선점형입니다. 하지만 리눅스 커널 위에서 동작하는
프로세스는 선점형이죠.

즉 다음과 같은 코딩으로 간단히 테스트 해 볼 수 있습니다.

/* 커널의 비선점성(커널모듈) 
   커널자체가 아무 응답이 없어집니다. */
int init_module()
{
	while(1)	;
	return 0;
}

/* 프로세스의 선점성 
   프로세스의 CPU점유율만 높아질뿐 동작에는 문제가 없죠. */
int main()
{
	while(1)	;
	return 0;
}

즉 커널모듈로 로드를 했을경우는 커널레벨에서 동작하고 커널이 비선점형이므로
절대로 CPU의 사용권을 반납하지않죠.
하니만 유저레벨 프로세스는 커널의 간섭을받아 일정 quantum이 지나게되면
커널이 CPU를 회수하여 다른 프로세스에게 돌려주게 됩니다.


리눅스 kernel이 preemption을 지원한지가 상당히 되지 않았나요?
kernel preemption은 바로 위와 같은 경우를 피하기 위해 만들어진 것입니다.
단 예외는 lock을 갖고 있는 경우입니다.
kyong의 이미지

next wrote:

RTOS의 조건이라면 프로세스가 생성되면 제어권이 넘어 가는것이 아니라 마감시간(deadline) 을 맞출 수 있도록 스케쥴링 하는 것입니다.

이것이 바로 SCHED_FF, SCHED_RR가 있는 이유가 아닙니까?
Quote:

그런점에서 리눅스 커널모드의 비선점은 Hard RealTime의 조건을 만족하기가 어렵겠지요.

커널이 보장하지 않는다는 점에 soft realtime이라고 하는 것은 맞습니다.
totohero의 이미지

choissi wrote:
totohero wrote:
방준영 wrote:

제가 궁금한 것은 실제로 선점형 커널에서 진짜 무한루프(중간에 자는 것 말고)를 돌려서 죽나 안죽나를 시험해 본 분이 있는가하는 것입니다.

제가 솔라리스용 드라이버를 짤 기회가 있어 드라이버 모듈 초기화 함수에 while (1) ; 을 넣어보았더니 모듈 로딩 작업은 멎어버렸지만 다른 작업은 모두 잘 되는군요. 방준영님께서는 preemptive kernel이란 커널 컨텍스트에 존재하는 사용자 프로세스로부터 스케줄러가 제어권을 빼앗아올 수 있는 구조로 된 커널이라고 한정하셨던 듯 한데 (저도 preemptive kernel에 대한 정확한 정의를 본적이 없어서 묻습니다만) 어디에 나와 있는 정의인지요?

테스트 하신 환경의 cpu가 몇개짜리 인가요?

CPU 1개입니다.

댓글 달기

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
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.