context switching 은 아래 3경우에 일어난다.
- Multitasking
- Interrupt handling
- Kernel mode and user mode switching
이 context switching 은 PCB ( Process Control Block) 이라는 data structure를 통해 구현된다.
위의 그림에서 A의 process PC (Program counter) 및 registers 이 저장되는 공간이 PCB 이며 보통 kernel space의 stack 공간에 저장된다 .
Interrupt handling은 process context 와 interrupt context의 switching이 일어나는 경우이다.
Interrupt handling은 CPU 내 어떤 interrupt 가 발생했을 때 해당 interrupt 를 처리하기 위한 활동이다.
인터럽트가 발생한 시점에 현재 시점에 runnign 중인 process context 와 interrupt context 간의 switching이 일어난다.
Interrupt context 는 interrupt 가 발생한 시점의 request 를 처리하기 위한 context 로서 최소한의 문맥교환만 일어난다. (Interrupt 처리 후 process context 로 switching 될 때 overhead를 최소화 하기 위
또한 이러한 Interrupt handler 를 “top half” 라고도 부른다. top half 및 bottom half 가 있는데 의미는 아래와 같다.
- Top half : hw interrupt 가 발생했을 때 interrupt 의 request 에 대한 response를 담당
- Bottom half : 해당 interrupt 에 대한 실제 처리를 담당
Bottom-half 는 workqueue 와도 관련이 있다.
sched.c - kernel/sched.c - Linux source code (v2.6.39.4) - Bootlin
/*
* context_switch - switch to the new MM and the new
* thread's register state.
*/
static inline void context_switch(struct rq *rq, struct task_struct *prev,
struct task_struct *next)
{
struct mm_struct *mm, *oldmm;
prepare_task_switch(rq, prev, next);
mm = next->mm;
oldmm = prev->active_mm;
/*
* For paravirt, this is coupled with an exit in switch_to to
* combine the page table reload and the switch backend into
* one hypercall.
*/
arch_start_context_switch(prev);
if (!mm) {
next->active_mm = oldmm;
atomic_inc(&oldmm->mm_count);
enter_lazy_tlb(oldmm, next);
} else
switch_mm(oldmm, mm, next);
if (!prev->mm) {
prev->active_mm = NULL;
rq->prev_mm = oldmm;
}
/*
* Since the runqueue lock will be released by the next
* task (which is an invalid locking op but in the case
* of the scheduler it's an obvious special-case), so we
* do an early lockdep release here:
*/
#ifndef __ARCH_WANT_UNLOCKED_CTXSW
spin_release(&rq->lock.dep_map, 1, _THIS_IP_);
#endif
/* Here we just switch the register state and the stack. */
switch_to(prev, next, prev);
barrier();
/*
* this_rq must be evaluated again because prev may have moved
* CPUs since it called schedule(), thus the 'rq' on its stack
* frame will be invalid.
*/
finish_task_switch(this_rq(), prev);
}
mm struct
유저 공간에서 생성된 프로세스에 대한 정보 (mm)을 교환하고, cPU레지스터들의 값을 바꿔준다.
해당 글은 기록용으로 문제시 삭제조치 하도록 하겠습니다.
출처
[Linux][Kernel]메모리 디스크립터 - struct mm_struct 구조체 소개
이 글은 옵시디언을 이용해서 작성되었습니다.
'Misc > CS' 카테고리의 다른 글
[MISC] busy waiting (0) | 2023.10.24 |
---|