2011. 10. 25. 21:18
mm_struct 구조체와 커널 스레드 OS이야기2011. 10. 25. 21:18
커널스레드는 프로세스 주소공간을 가지지 않는다. 그러므로 커널 스레드 프로세스 서술자의 mm필드는 NULL값을 가진다.
이것이 바로 유저 컨텍스트를 갖지 않는 프로세스인, 커널스레드에 대한 정의다.
여기부터 이해해보자
커널 스레드는 사용자의 메모리를 접근할 일이 없기 때문에 이점은 크게 문제가 되지 않는다. (시스템콜은?)
커널스레드는 사용자 공간에 어떠한 페이지도 가지고 있지 않기 때문에 스레드를 위한 ㅔㅁ모리 서술자와 페이지 테이블을 가질필요가 없다. 그럼에도 불구하고 커널스레드는 페이지 테이블이나 커널의 메모리 등과 같은 곳의 접근을 위해 몇몇 정보가 필요하다. 메모리서술자(mm_struct)와 페이지 테이블을 위한 메모리의 낭비나 커널 스레드가 실행될 때마다 새로운 주소공간으로의 스위칭을 위한 프로세서 사이클의 낭비를 방지하기 위해, 커널 스레드는 그 작업이 무엇이든 간에 바로 이전에 실행되었던 작업의 메모리 서술자를 활용
프로세스가 스케줄될 떄마다 해당 프로세스의 mm필ㄹ드에 의해 참조되는 주소공간이 로드된다.
이 경우 프로세스 서술자에 있는 active_mm필드는 새로운 주소공간을 가르키기 위해 갱신된다.
커널스레드는 주소공간을 갖지 않으며, 따라서 mm필드는 NULL값을 가진다. 따라서 커널 스레드가 스케줄되면 커널은 mm의 값이 NULL임을 인지하고 이전 프로세스의 주소공간을 로드한채로 유지한다.
다음으로 커널 스레드의 프로세스 서술자에 있는 active_mm 필드를 갱신하여 커널이 이전프로세스의 메모리 서술자를 참조할 수 있도록한다. (next->active_mm = oldmm);
이렇게 되면 커널스레드는 이전 프로세스의 페이지 테이블을 사용할 수 있게된다. 커널 스레드는 유저공간 메모리 공간을 접근하지 않으므로, 모든 프로세스에게 동일한, 커널 메모리에 속한 주소공간에 있는 정보만 사용한다.
참조 ; http://icecreamie.tistory.com/entry/%EB%A9%94%EB%AA%A8%EB%A6%AC-%EA%B4%80%EB%A6%AC
이것이 바로 유저 컨텍스트를 갖지 않는 프로세스인, 커널스레드에 대한 정의다.
여기부터 이해해보자
커널 스레드는 사용자의 메모리를 접근할 일이 없기 때문에 이점은 크게 문제가 되지 않는다. (시스템콜은?)
커널스레드는 사용자 공간에 어떠한 페이지도 가지고 있지 않기 때문에 스레드를 위한 ㅔㅁ모리 서술자와 페이지 테이블을 가질필요가 없다. 그럼에도 불구하고 커널스레드는 페이지 테이블이나 커널의 메모리 등과 같은 곳의 접근을 위해 몇몇 정보가 필요하다. 메모리서술자(mm_struct)와 페이지 테이블을 위한 메모리의 낭비나 커널 스레드가 실행될 때마다 새로운 주소공간으로의 스위칭을 위한 프로세서 사이클의 낭비를 방지하기 위해, 커널 스레드는 그 작업이 무엇이든 간에 바로 이전에 실행되었던 작업의 메모리 서술자를 활용
프로세스가 스케줄될 떄마다 해당 프로세스의 mm필ㄹ드에 의해 참조되는 주소공간이 로드된다.
이 경우 프로세스 서술자에 있는 active_mm필드는 새로운 주소공간을 가르키기 위해 갱신된다.
커널스레드는 주소공간을 갖지 않으며, 따라서 mm필드는 NULL값을 가진다. 따라서 커널 스레드가 스케줄되면 커널은 mm의 값이 NULL임을 인지하고 이전 프로세스의 주소공간을 로드한채로 유지한다.
다음으로 커널 스레드의 프로세스 서술자에 있는 active_mm 필드를 갱신하여 커널이 이전프로세스의 메모리 서술자를 참조할 수 있도록한다. (next->active_mm = oldmm);
이렇게 되면 커널스레드는 이전 프로세스의 페이지 테이블을 사용할 수 있게된다. 커널 스레드는 유저공간 메모리 공간을 접근하지 않으므로, 모든 프로세스에게 동일한, 커널 메모리에 속한 주소공간에 있는 정보만 사용한다.
/* 3149 * context_switch - switch to the new MM and the new 3150 * thread's register state. 3151 */ 3152static inline void 3153context_switch(struct rq *rq, struct task_struct *prev, 3154 struct task_struct *next) 3155{ 3156 struct mm_struct *mm, *oldmm; 3157 3158 prepare_task_switch(rq, prev, next); 3159 //다음에 수행될 프로세스의 mm 3160 mm = next->mm;
//수행되었던 프로세스의 active_mm 3161 oldmm = prev->active_mm; 3162 /* 3163 * For paravirt, this is coupled with an exit in switch_to to 3164 * combine the page table reload and the switch backend into 3165 * one hypercall. 3166 */ 3167 arch_start_context_switch(prev); 3168 //커널 스레드이면 이 블록으로 빠진다. 3169 if (!mm) { 3170 next->active_mm = oldmm; //수행되었던 프로세스의 mm을 빌린다. 3171 atomic_inc(&oldmm->mm_count); //커널스레드임으로 해제시키면 안되니깐, 증가. 3172 enter_lazy_tlb(oldmm, next); 3173 } else 3174 switch_mm(oldmm, mm, next); 3175 //수행되엇던 프로세스가 커널 스레드이면, active_mm = NULL로 한다. 3176 if (!prev->mm) { 3177 prev->active_mm = NULL; 3178 rq->prev_mm = oldmm; 3179 } 3180 /* 3181 * Since the runqueue lock will be released by the next 3182 * task (which is an invalid locking op but in the case 3183 * of the scheduler it's an obvious special-case), so we 3184 * do an early lockdep release here: 3185 */ 3186#ifndef __ARCH_WANT_UNLOCKED_CTXSW 3187 spin_release(&rq->lock.dep_map, 1, _THIS_IP_); 3188#endif 3189 3190 /* Here we just switch the register state and the stack. */ 3191 switch_to(prev, next, prev); 3192 3193 barrier(); 3194 /* 3195 * this_rq must be evaluated again because prev may have moved 3196 * CPUs since it called schedule(), thus the 'rq' on its stack 3197 * frame will be invalid. 3198 */ 3199 finish_task_switch(this_rq(), prev); 3200}
참조 ; http://icecreamie.tistory.com/entry/%EB%A9%94%EB%AA%A8%EB%A6%AC-%EA%B4%80%EB%A6%AC
'OS이야기' 카테고리의 다른 글
메모리영역 다루기 (0) | 2011.10.31 |
---|---|
VMA연산 (0) | 2011.10.25 |
메모리 서술자의 할당 (0) | 2011.10.25 |
프로세스 주소영역 (0) | 2011.10.25 |
VFS객체와 그 자료구조 (2) | 2011.10.20 |