일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- Route53 Resolver
- 마운트
- bWAPP install
- node pod 분리
- SessionManager 터널링
- VGW
- Route53 Endpoint
- DNS Resolver
- S3 Gateway Endpoint
- x lock s lock
- AWS Resolver
- bWAPP M1
- 리눅스
- Terraform
- S3 PrivateLink
- ec2
- S3 Interface Endpoint
- ix is lock
- BastianHost
- bWAPP arm
- DXGW
- CrossSiteScript
- s3
- 도커
- s3 sync
- 다이렉트 커넥트
- 푸시게이트웨이
- sessionManager
- S3 private통신
- push-gateway
- Today
- Total
이것이 점프 투 공작소
커널에서의 문맥교환 본문
문맥교환(context-switching)이란?
문맥교환은 커널이 프로세스간 스위칭 할 때, 현재 실행 중인 프로세스의 상태를 저장하고, 다음 실행할 프로세스의 상태를 불러오는 과정입니다, 이를 통해 커널에서 여러 프로세스가 동시에 실행(멀티테스킹)하는 것 처럼 보여집니다.
문맥 교환은 멀티테스킹, 인터럽트 , 커널<->사용자모드 전환 시 발생됩니다.
프로세스의 문맥이란?
1. 하드웨어 문맥 (Hardware Context)
- CPU가 프로세스를 실행하기 위해 필요한 하드웨어 레지스터의 상태입니다.
- 하드웨어 문맥에는 아래와 같은 데이터가 존재합니다.
- 프로그램 카운터(Program Counter, PC): 다음에 실행할 명령어의 메모리 주소를 저장하는 레지스터입니다.
- 프로세서 레지스터: CPU에서 연산에 사용되는 레지스터로, 데이터 레지스터, 주소 레지스터 등이 있습니다.
- 상태 레지스터: CPU가 연산을 수행하는 동안에 발생하는 상태 정보를 저장하는 레지스터로, 연산 결과에 대한 정보, 예외 상황에 대한 정보 등이 저장됩니다.
- 스택 포인터(Stack Pointer, SP): 스택 메모리의 시작 주소를 저장하는 레지스터입니다.
- 프로세서 모드(Mode): CPU가 실행하는 모드를 나타내는 레지스터로, 사용자 모드와 커널 모드가 있습니다.
2. 프로세스 주소공간(Process Adress Space) - 코드,데이터,스택영역으로 구분됩니다
- 프로세스가 메모리를 사용하는 논리적인 공간, 프로세스마다 자신만의 독립된 주소 공간을 가지고 있습니다.
- 이를 통해 프로세스는 다른 메모리와 자원 등을 공유하지 않고 독립적으로 실행됩니다.
- 코드(Code) 영역: 프로세스가 실행될 때, 실행 파일에 포함된 프로그램 코드가 메모리에 로드됩니다. 이 코드는 읽기 전용(Read-only)으로 메모리에 저장되며, 여러 프로세스에서 동시에 사용할 수 있습니다.
- 데이터(Data) 영역: 프로그램에서 사용하는 전역 변수, 정적 변수 등이 저장되는 영역입니다. 데이터 영역은 읽기 쓰기(Read-write)가 가능합니다.
- 스택(Stack) 영역: 프로그램에서 사용하는 지역 변수와 함수 호출 시 생성되는 지역 변수, 매개변수 등이 저장되는 영역입니다. 스택은 아래에서 위로 자라는 구조로 되어 있으며, 메모리의 높은 주소부터 할당됩니다.
3. 커널상의 문맥(Kernel Context) - 커널이 실행되는 동안 필요한 상태정보를 나타냅니다
- 즉 프로세스를 관리를 위한 자료구조인 PCB(Process Control Block)와 Kernel stack(커널내의 주소)가 필요합니다.
커널에서 문맥교환은 언제 일어날까?
커널 코드 상에서는 schedule() 함수가 실행되면 문맥교환이 일어나게됩니다.
shcedule() 함수에서는 context_switch()를 호출하여 문맥교환을 시작합니다.
schedule() 함수는 need_resched 플래그가 변경되면 실행됩니다.
문맥교환이 실행되기 전까지 과정
need_resched 플래그 변경 -> (인터럽트, 시스템콜, 프로세스 생성, 프로세스 종료 등 재스캐줄 이벤트) -> schedule() 함수 실행 -> context_switch() 순서로 문맥교환이 실행되게됩니다.
need_resched 플래그란?
말 그대로 언제 schedule()함수를 실행해야하는지 알려주는 플래그입니다.
task_struct 구조체 안에 존재하는 변수입니다.
커널은 스케줄링 이벤트가 발생하면 need_resched 값을 체크하고 재스케줄링이 필요한 상태라면 스케줄링을 실행합니다.
커널이 need_resched 플래그를 변경하는 시점은 다음과 같습니다.
- 현재 실행 중인 프로세스의 time slice가 끝나서 다음 프로세스로 전환해야 할 때
- 현재 실행 중인 프로세스가 wait queue에 대기 중인 이벤트가 발생하기 전에 sleep 상태가 되었을 때
- 현재 실행 중인 프로세스가 semaphore나 mutex와 같은 동기화 객체에 대해 대기 중이었는데, 이를 확보할 수 있는 다른 프로세스가 생겼을 때
- 깨어난 프로세스가 현재 실행 중인 프로세스 보다 우선순위가 높을 때
- 프로세스를 선점할 필요가 있을 때
context_switch 작업 (kernel 2.6)
아래 context_switch() 함수는 현재 실행 중인 스레드의 레지스터 상태와 메모리 매핑 정보를 새로운 스레드의 정보로 교체하는 작업을 수행합니다.
/*
* 함수는 두 개의 task_struct 포인터를 인자로 받아서, 이전 스레드와 새로운 스레드를 전환합니다.
*/
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 # 스레드 전환 준비
trace_sched_switch(rq, prev, next); # 함수를 호출하여 스케줄링 변경에 대한 추적 정보를 기록합니다
mm = next->mm;
oldmm = prev->active_mm;
arch_start_context_switch(prev); # 스레드 전환에 필요한 아키텍처별 동작을 수행합니다.
if (likely(!mm)) {
next->active_mm = oldmm;
atomic_inc(&oldmm->mm_count);
enter_lazy_tlb(oldmm, next);
} else
switch_mm(oldmm, mm, next);
if (likely(!prev->mm)) {
prev->active_mm = NULL;
rq->prev_mm = oldmm;
}
#ifndef __ARCH_WANT_UNLOCKED_CTXSW
spin_release(&rq->lock.dep_map, 1, _THIS_IP_);
#endif
switch_to(prev, next, prev); # 함수를 호출하여 이전 스레드와 새로운 스레드의 레지스터 값을 교체
barrier();
finish_task_switch(this_rq(), prev);
}
references
https://byjus.com/gate/context-switching-in-os-notes/
https://lxr.linux.no/linux+v2.6.34/kernel/sched.c
'리눅스' 카테고리의 다른 글
시스템 콜 (Sys Call)에 대해 알아보자 (0) | 2023.05.06 |
---|---|
선점과 프로세스잠금에 대해서 알아보자 (0) | 2023.03.21 |
UFS와 Union Mount Filesystem에 대해 알아보자 (0) | 2023.02.04 |
리눅스 NameSpace에 대해 알아보자 (0) | 2023.02.04 |
cgroup에 대해 알아보자 (2) | 2023.01.16 |