# 하드웨어에서 이런 명령어를 제공
bool Test_and_Set(bool *flag) {
bool old = *flag;
*flag = True;
return old;
}
lock = false;
repeat
while Test_and_Set(lock) do no-op;
Critical Section
lock = false;
Remainder Section
until false
문제
Spin Lock 이기 때문에 CPU를 계속 써야 함 (Lock 값 계속 체크해야 함)
14. Sleep and Wakeup
busy-waiting 해결 → 임계 구역 진입이 허용되지 않을 때, CPU 시간을 낭비하는 대신 블록 하는 프로세스 간 통신 고려
sleep : 호출자를 block → 다른 프로세스가 깨울 때 (wakeup)까지 보류
wakeup
발생 문제 : 생산자 - 소비자 문제 (한정된 버퍼 문제)
생산자 (producer) : 버퍼에 정보를 삽입
소비자 (consumer) : 버퍼에서 정보를 제거
버퍼가 가득 차 있다면? 생산자를 sleep --> 소비자 수행 후, wakeup
15. Semaphore
화장실이 여러 개 있는 레스토랑, 열쇠 = 칸 개수만
현재 공유자원에 접근할 수 있는 프로세스/스레드 수를 나타내는 값을 두어 상호 배제
Lock시 특정 수만큼의 카운트를 더하고
Unlock시 빼주는 형식으로 처리
이런 락을 슬립( Sleep ) 가능한 락이라고 함
Up, Down은 atomic 하게 동작
생산자 소비자 문제의 근본적 해결
동기화해야 하는 대상이 여러 개일 때 사용
1) 카운팅 세마포어
가용한 개수를 가진 자원에 대한 접근 제어용으로 사용되며, 세마포는 그 가용한 자원의 개수로 초기화된다. 자원을 사용하면 세마포가 감소, 방출하면 세마포가 증가한다.
생산자 소비자 문제와 비교하기
count 하나로 표현되던 부분들이 up, down을 이용하여 mutex, empty, full로 표현
#define N 100 // 버퍼 용량
int mutex = 1; // 공유 데이터를 위한 mutex
int empty = n // 빈 용량
int full = 0 // 찬 용량
void producer(void) {
int item;
while(TRUE) {
item = produce_item(); // item 생성
down(&empty); // if 꽉차지 않았으면 empty--;
down(&mutex); // mutex = 0 으로 해서, lock 처리
insert_item(item); // 버퍼에 추가
up(&mutex); // mutex = 1 으로 해서, unlock 처리
up(&full);
}
}
void consumer(void) {
int item;
while(TRUE) {
down(&full);
down(&mutex);
item = remove_item(); //
up(&mutex);
up(&empty);
consume_item(item);
}
}
2) 이진 세마포어 (MUTEX)
MUTEX라고도 부르며, 상호 배제의 (Mutual Exclusion)의 머릿글자를 따서 만들어졌다. 이름 그대로 0과 1 사이의 값만 가능하며, 다중 프로세스들 사이의 Critical Section 문제를 해결하기 위해 사용한다.
16. Monitor
동기화를 구현하기 위한 특수 프로그램 기법
특정 공유 자원을 프로세스에게 할당하는 데 필요한 데이터와 이 데이터를 처리하는 프로시저로 구성
자료 추상화, 정보 은폐 개념을 기초, 병행성 구조
상호 배제가 low-level 단에서 지원됨
→ "단 하나의 프로세스만 한 순간에 모니터에서 활동할 수 있다."
생산자-소비자 문제 해결
조건 변수 wait, signal 도입
sleep, wakeup과 달리 모니터에서는 자동적으로 상호 배제가 됨→ 문맥교환 될 걱정하지않고 연산 완료 가능
→ wait, signal은 상호배제가 아님
17. Message Passing
send / receive ; 시스템 호출 일종
acknowledgement 분실 문제 -> 메시지 구별 필요
인증 --> 프로세스의 유일성 보장
생산자 - 소비자 문제
공유 메모리가 아닌, 메시지 전달로 해결
가정
모든 메시지는 동일한 크기
메시지는 운영체제에 의해 자동 버퍼링
방법
소비자는 시작할 때, N개의 빈 메시지를 생산자에게 보냄
생산자는 소비자에게 전달할 아이템을 생산하면, 빈 메시지 수신 → 아이템이 들어 있는 메시지 전송
system call이나 I/O 가 발생해서 Block 되면, 프로세스 자체가 block 되었다고 판단하여, 다른 스레드도 돌릴 수 없다. → CPU 안 쓰게 된다.
무한 루프 돌고 있어서 자원을 계속 차지하고 있어도, 뺏어올 수 없음 → 자발적으로 넘겨줘야 함
Kernel-level thread
단점 : 느리다.
OS 가 알아서 thread 가 block 되면 다른 thread로 CPU를 할당함
2. 멀티 스레드
멀티 스레드를 제공한다면, CPU를 점유하는 가장 작은 단위 = 스레드가 됨
즉, Parallel 한 작업
한 개의 단일 애플리케이션은 여러 스레드로 구성 후 작업 처리해야 한다.
한글에서 싱글 스레드를 사용하면, 프린트를 하는 경우 문서 수정은 불가능하다.
디버깅이 어렵다. 자원 공유 문제(교착상태)가 생긴다.
우리가 컴퓨터 살 때 보는 '6 코어 12 스레드'에서 스레드는 물리적인 코어 6개로 12개의 스레드를 동시 멀티스레딩(SMT, Simultaneous Multi-Threading)으로 구현이 된 것이라고 한다 (하이퍼스레딩이 있는 CPU라고 한다). 즉 S/W의 관점으로는 하나의 코어에 하나의 가상의 코어를 만들어서 CPU 2개로 인식된다.
즉, 물리적인 Core 위에 하이퍼스레딩으로 구현된 (물리적이라고 볼 수 있는) Core 스레드가 여러 개 존재하고, 그 위로 Kernel-level 스레드가 더 여러개 있을 수 있고, 그 위로는 User-level 스레드가 더더 여러개 있을 수 있는 구조가 되겠다. (물론 어떤 멀티 스레드 모델이냐에 따라 다를 수 있다.)
멀티 스레드 모델
3. Context-Switching : 프로세스 vs 스레드
프로세스는 운영체제로부터 자원을 할당받아 실행하고, 스레드는 프로세스로부터 자원을 할당받아 실행합니다.
프로세스 : fork()를 통해 생성되는데, 매번 동일한 코드가 복사되어 작동하고, PCB, 주소 복사 등 Context Switching에 Cost가 크다.
스레드 : 레지스터와 스택을 제외하고 자원을 공유하여 사용 → 한 가지 스레드는 I/O를 담당하는 등, 스레드로 각 CPU에 일을 할당해서 수행 가능
4. 멀티 프로세스 vs 멀티 스레드
1. 멀티 프로세스
Concurrency 한 작업
2. 멀티 스레드
멀티 프로세스보다 자원을 효율적으로 사용 가능
멀티 프로세스로 실행하던 작업을 멀티 스레드로 실행하면, 프로세스를 생성하여, 자원을 할당하는 시스템 콜이 줄어든다
메모리를 공유하기 때문에, 프로세스 간 통신 방법에 비해 스레드 간의 통신 방법이 간단하다.
처리 비용 및 응답 시간 단축
context-switching 시 발생하는 오버헤드를 감소시킬 수 있다.
심지어 스레드의 context switch는 프로세스 context switch 와는 달리 캐시 메모리를 비울 필요가 없다.
문제점
멀티 프로세스 기반으로 프로그래밍할 때는 프로세스 간 공유하는 자원이 없기 때문에 동일한 자원에 동시에 접근하는 일이 없었지만 멀티 스레딩을 기반으로 프로그래밍할 때는 이 부분을 신경 써줘야 한다. 서로 다른 스레드가 데이터와 힙 영역을 공유하기 때문에 어떤 스레드가 다른 스레드에서 사용 중인 변수나 자료구조에 접근하여 엉뚱한 값을 읽어오거나 수정할 수 있다.
해결
멀티스레딩 환경에서는 동기화 작업이 필요하다. 동기화를 통해 작업 처리 순서를 컨트롤하고 공유 자원에 대한 접근을 컨트롤하는 것이다. 하지만 이로 인해 병목현상이 발생하여 성능이 저하될 가능성이 높다. 그러므로 과도한 락으로 인한 병목현상을 줄여야 한다.
5. Thread 관련 예시
(질문1) 워드에서 글자를 입력했을 때 어떤 일이 발생하는가?
사용자 입력 → 외부 Interrupt 중 I/O Interrupt 발생 → CPU 인지 → CPU 작업 중이던 상태 저장 → 해당 인터럽트 처리 → 상태 복구 및 중단되었던 작업 재개
개인적으론 이 질문이 크롬에 사이트 url을 입력했을 때 일어나는 일을 설명해보라는 질문과 동급이라고 생각한다. 이 질문에 대해 대부분의 글들에선 위처럼 단순히 Interrupt에 대해서만 설명하고, 그대로 복사해오는 것 같아서 나름대로 깊게 생각을 해보았다.
우선 내 생각은 워드라는 프로세스는 멀티 스레드로 구현이 되어있다고 생각이든다.
그렇게 생각한 이유는 커서가 깜박이고, 입출력을 행할 때 다른 행동을 동시에 할 수 있기 때문이다.
따라서 I/O를 처리할 스레드를 만들었을 것이고, 해당 스레드에서 I/O 인터럽트가 걸릴 것이라 생각이 된다.
헌데 I/O 인터럽트가 걸렸다고 해서 해당 프로세스가 통째로 blocked 되지는 않으므로 하나의 커널 스레드만 사용 중인 것은 아닐 것 같다.
즉, 1:1 혹은 m:n으로 스레드 매핑이 이루어져 있을 것 같다.
인터럽트가 발생한 스레드는 이후 인터럽트 처리 과정이 이루어질 것이다.
실행 중이던 스레드가 실행이 중단되고, TCB에 context를 저장한 후, 인터럽트 원인을 판별 -> 인터럽트 벡터 테이블을 참조 -> ISR(인터럽트 서비스 루틴) 처리 -> Interrupt 처리 종료 후 ready 큐에 있는 작업을 실행하면서 상태를 복구할 것 같다.
이후에 화면에 출력해주는 Interrupt가 걸려서, 또다시 같은 과정을 통해 화면에 그려줄 것으로 예상된다.
이후에 더 공부하면서 추가/수정 한 부분
워드 프로세서는 3가지의 스레드를 가진다
interactive 스레드
Reformatting 스레드
Disk-backup 스레드
DMA를 이용하여 I/O를 모아서 처리한다.
출력하려면 마지막에 CPU가 인터럽트를 받아서 출력장치에 값을 넘겨줘야 한다.
이때 문제는 한 글자가 4개 블락으로 돼있으면 한 블락당 검사를 해서 4번의 인터럽트가 걸린다고 볼 수 있는데
DMA가 이 검사를 대신해줘서 CPU는 한 번의 인터럽트만 받게 된다!
모니터에 화면을 보여주는 것을 계속 I/O Interrupt 가 발생할까?
화면 출력도 프린터 출력하는 거랑 비슷하게 cpu 거쳐가서 커널 스레드가 하드웨어한테 작업을 부여해줄 뿐 실질적인 출력 실행에는 cpu가 쓰이지 않는다.
fork() 시스템 호출은 새로운 프로세스를 만들어내는 기능을 한다. 새로운 프로세스는 원래의 프로세스 주소 공간의 복사본을 가지고 있다. fork() : 현재 돌아가고 있던 프로세스를 복사해서 다른 프로세스를 만든다. exec() : 프로세스로 하여금 다른 바이너리를 가지고 새로 시작하도록 한다. 자식 프로세스는 exec을 통해 내용을 모두 바꾼다.
2. 프로세스 삭제
프로세스는 마지막 statement를 실행하고 exit() 시스템 호출을 이용하여 운영체제로 하여금 삭제하도록 한다. 부모는 자식에게서 wait을 통해 상태 값을 받을 수 있다.
3. 좀비 프로세스
1. 좀비 프로세스란?
자식 process가 종료되어 자원 해제를 요청했는데 부모 프로세스가 자식 프로세스의 종료 상태를 받아들이지 못해서 프로세스 테이블에 남아 있는 상황이다. 그래서 죽었지만 살아있는 '좀비'와 같은 상태가 된다.
좀비상태의 목적은 나중에 parent process가 가져갈 child에 대한 정보를 유지하는 것이다. 이 정보는 자식의 프로세스 ID와 종료 상태 및 자식의 자원 사용률(CPU 시간, 메모리 등) 등을 포함하고 있다.
3. 좀비 프로세스가 생겼을 때 제거되는 과정
만약 프로세스가 종료하고 좀비 상태에 있는 자식을 가지고 있으면, 모든 좀비 자식의 어버이 프로세스 ID는 1(init 프로세스)로 바뀌며, 그 프로세스는 자식을 넘겨받아 청소한다. 즉, 좀비를 제거한다 (init은 그들을 wait 한다).
4. 좀비 프로세스가 생기지 않도록 처리
그렇다면 좀비프로세스는 어떻게 처리할까? 좀비 프로세스를 내버려 두어서는 안 된다. 좀비는 커널의 공간을 차지하므로, 궁극에는 프로세스를 더 만들 수 없게 된다. 자식을 fork()할 때마다 자식이 좀비가 되는 것을 방지하기 위해 반드시 자식을 wait 해야 한다. 이렇게 하기 위하여 SIGCHLD 신호를 포착하는 신호 처리기를 설정하여 그 신호 처리기 안에서 wait를 호출한다.
Signal(SIGCHLD, sig_chld);
4. 고아 프로세스 (Orphan process)
부모 process가 먼저 종료 → 고아 프로세스의 부모 프로세스 PID=1로 변경 (init 프로세스)
PID, 상태, PC (Program Counter), CPU register, 우선순위 등
Linked List 방식으로 관리함 → 삽입, 삭제 용이
4. 프로세스의 상태
new : 프로세스 생성중
프로세스를 생성하고 있는 단계로 커널 공간에 PCB가 만들어진 상태
ready : 프로세스가 CPU를 기다리는 상태
프로세스가 메모리에 적재된 상태로 실행하는데 필요한 자원을 모두 얻은 상태
아직 CPU를 받지는 않았지만 CPU를 할당받으면 바로 실행 가능한 상태
ready상태를 가지는 여러 개의 프로세스들이 존재할 수 있음
running : 프로세스가 CPU를 할당받아 명령어를 수행 중인 상태
일반적으로 CPU가 하나이기 때문에, 여러 프로세스가 동시에 실행돼도 실제로 실행 중인 프로세스는 매 시점 하나뿐임
blocked : 프로세스가 CPU를 할당받아도 당장 실행할 수 없는 상태
현재 프로세스가 I/O 작업 등을 을 처리 중 상태를 의미
terminated : 프로세스의 실행 종료
프로세스의 실행이 완료되고 할당된 CPU를 반납, 커널 공간 내의 PCB는 남아 있음
suspended : 프로세스의 중지 상태
suspended 상태의 프로세스는 메모리를 강제로 뺏긴 상태로 특정한 이유로 프로세스의 수행이 정지된 상태를 의미하며, 외 부에서 다시 재개시키지 않는 이상 다시 활성화될 수 없음 중기 스케줄러에 의해 디스크로 스왑 아웃된 프로세스의 상태가 대표적인 suspenden상태라 할 수 있음. suspended ready와 suspended blocked가 있음
1. suspended ready : 준비 상태에 있던 프로세스가 디스크로 스왑 아웃
2. suspended blocked : 봉쇄 상태에 있던 프로세스가 디스크로 스왑 아웃
※ blocked?
프로세스 A가 CPU를 할당받고(running상태) 명령어를 실행하다 I/O 작업을 해야 하는 경우, 디스크 I/O 작업은 CPU 처리 속도에 비해 오래 걸리는 작업이기 때문에 디스크 I/O 작업 동안은 CPU를 점유하고 있어도 다음 명령어를 수행하지 못합니다. ㅡ> CPU 낭비
때문에 디스크 I/O 작업을 하는 프로세스는 CPU를 반납하고 장치 큐에 가서 줄을 서게 된다(blocked 상태). 이후 디스크 컨트롤러에 의해 서비스를 받아 일을 수행하면(마그네틱 원판에서 원하는 데이터를 로컬 버퍼로 읽어오고 나면) 디스크 컨트롤러가 CPU에게 일을 끝났음을 알린다(인터럽트). 이후 프로세스 A는 장비 큐에서 빼내어 준비 큐로 넣어주고 프로세스 A가 한 일(로컬 버퍼에 저장)은 메모리에 올라가게 된다.
※ blocked와 suspended의 차이
blocked : 잠시 중지되어있다(blocked) 끝나면 다시 ready상태로 돌아옴
suspended : 잠시 중지되어 있다(suspendedn) 누군가가 재개시켜줘야 다시 ready상태로 돌아옴.
5. 프로세스의 상태 변화
new ㅡ> ready
new 상태에서 OS에 의해 승인을 받아 프로세스가 생성되면 해당 프로세스의 PCB(Process Control Block, 커널 내 자료구조)이 OS 커널의 Ready Queue에 올라옴
ready ㅡ> running
Ready Queue에 있는 프로세스들 중에서 스케줄링 알고리즘에 의해 선택받은 프로세스가 CPU를 할당 받음
running ㅡ> ready
CPU를 할당받아 일을 하다 특정 이유로 다른 프로세스에게 CPU를 주고(dispatch) 다시 CPU를 기다림
1.time out: 프로세스 A가 정해진 시간만큼 CPU를 사용하고 CPU를 반납
2.interrupt: 프로세스 A보다 우선순위가 높은 프로세스 B가 Ready Queue에 존재하는 경우, 프로세스 B에게 CPU를 줌
running ㅡ> blocked
현재 CPU를 받아 명령어를 수행 중인 프로세스가 I/O 작업을 해야 하는 경우로 CPU를 반납하고 해당 장치 큐에 들어가게 되며 이 상태를 blocked 상태라 함
blocked ㅡ> ready
I/O 작업을 위해 장치 큐에 있던 프로세스가 디스크 컨트롤러에 의해 서비스를 받아 일을 하고 디스크 컨트롤러가 인터럽트를 발생하여 프로세스가 한 일을(로컬 버퍼에 저장된 데이터) 메모리에 올려놓고 프로세스는 다시 Ready Queue에 들어가게 됨
그동안 학교에서 배웠던 내용 + 전공책을 뒤져가며 공부했던 내용 + 취준 하면서 복습했던 내용들을 정리하는 목적으로 작성하였습니다.
1. 인터럽트(Interrupt) 란?
Interrupt는 프로그램 실행 중에 CPU의 현재 처리 순서를 중단하고, 다른 동작을 수행하도록 요구하는 것이라고 볼 수 있다. 즉, Interrupt가 발생하면 운영체제는 CPU에게 그동안 하고 있는 일들을 멈추고, Interrupt를 해결하도록 한다.
Interrupt가 발생하게 되면, ISR (Interrupt Service Routines)이라는 것이 실행되는데, 이를 인터럽트 핸들러(Interrupt Handler)라고도 한다
그렇다면 Interrupt는 어떤 때에 발생하는 것일까? Interrupt는 예외상황에 대한 처리가 필요한 상황에 발생한다. 예외상황에 따라 Interrup는 크게 (1) 외부 Interrupt, (2) 내부 Interrupt, (3) SW Interrupt로 나눌 수 있다.
1. 외부 Interrupt
외부 Interrupt는 CPU 코어 외부 요인으로 발생하는 것을 말하는데, 전기적인 신호로 CPU에게 Interrupt를 거는 경우로 (1) 전원 이상 Interrupt, (2) I/O Interrupt, (3) 타이머 Interrupt 같은 것들이 있다.
전원 이상 Interrupt의 경우,
갑자기 전원 공급이 중단되는 경우 CPU에 Interrupt를 걸어 작업 중이던 프로세스를 대피시킬 수 있도록 한다.
I/O Interrupt의 경우,
CPU가 I/O 장치 (키보드, 마우스, 프린터 등) 에게 일을 맡기거나, I/O 장치가 CPU에게 정보를 전달해 줄 때 호출된다.
타이머 Interrupt의 경우,
컴퓨터 내부의 타이머가 CPU에 주기적으로 expired 되었다고 알림을 주는데, 이것이 Interrupt이다. 따라서 하나의 프로그램이 CPU 자원을 너무 오랫동안 점유하지 못하도록 한다. 또한 무한루프가 도는 프로그램도 이 덕분에 종료되고 Context Switch가 발생할 수 있다.
(참고) 타이머 Interrupt는 100hz로 인터럽트를 건다. 즉, 10ms 마다 interrupt가 걸린다.
2. 내부 Interrupt
내부 Interrupt는 CPU 코어 내부에서 프로그램이 실행되면서 Interrupt에 걸리는 경우로 프로그램 검사 인터럽트(Program check interrupt)이다. Exception Interrupt, 혹은 Trap이라고 부른다.
Exception Interrupt (Trap)
Division by zero
Overflow/Underflow
기타 프로그램 Exception
Exception이라는 것은, 결국 예외상황에 대한 의미로, 소프트웨어 내부에서 예외상황을 처리하는 것을 두고 소프트웨어 Interrupt를 Exception으로 보는 경우도 있다.
Trap의 의미는, 특별한 조건을 걸어두고 조건에 부합하는 경우 상황에 맞는 Service Routine이나 Handler 가 실행되도록 하는 것을 의미한다. 따라서 이 경우에는 ISR (Interrupt Service Routines) 혹은인터럽트 핸들러(Interrupt Handler)가 되겠다.
Exception과 Trap 은 프로그래밍 전반적으로도 사용되는 용어이니, 결국은 단어를 어떻게 해석하느냐의 차이인 것 같다. 결국 너무 단어에 매몰되지 말고, 개념을 잘 익히는 것이 중요하다.
3. 소프트웨어 Interrupt
소프트웨어 Interrupt는프로그램 처리 중 명령의 요청에 의해서 발생하는 경우로 SVC (SuperVisor Call) 이 있다.
SVC (SuperVisor Call)
일반적인 응용 프로그램은 User Mode에서 실행이 되는데, 이 경우 직접 접근할 수 있는 자원에 제한이 있다. 예를 들어 어떤 프로그램이 컴퓨터에 대한 통제권을 갖는 코드를 갖고 있다고 할 때, 이런 것이 허락도 없이 수행될 수는 없는 것이다. 즉, 이러한 자원에 접근하는 명령어는 Supervisor 만 실행할 수 있어야 하고, 이것이 즉, Kernel Mode가 되는 것이다. 즉, 응용프로그램은 SuperVisor Call을 통해 허락을 맡은 후 Supervisor Mode (=Kernel Mode)로 변경하고, 해당 명령을 실행 후, 다시 User Mode로 변경하는 과정을 거치게 된다.
운영체제가 제공하는 서비스에 대한 프로그래밍 인터페이스가 System Call이고, System Call을 실행시키기 위한 CPU 명령어가 SVC이다.
2. 인터럽트 처리 과정
요청 → 중단 → 보관 → 인터럽트 처리 → 재개
인터럽트 요청
프로그램 실행 중단
현재 실행 중이던 Micro Operation까지 수행
현재 실행 중인 프로그램 상태 보관
PCB(Process Control Block), PC(Program Counter) 저장
인터럽트 원인 판별
인터럽트를 요청한 장치를 식별 → 인터럽트의 원인을 파악
Interrupt Vector 테이블을 참조하여 호출할 ISR (인터럽트 서비스 루틴) 주소 값을 얻음
ISR (인터럽트 서비스 루틴) 처리
실질적인 인터럽트 처리 작업을 한다.
서비스 루틴 수행 중, 우선순위가 더 높은 인터럽트가 발생하면 재귀적으로 1~5 과정 수행한다
인터럽트 서비스 루틴을 실행할 때 인터럽트 플래그(IF)를 0으로 하면 인터럽트 발생을 방지할 수 있다.
상태 복구
상태 복구 명령어가 실행되면, 저장해둔 PC(Program counter)를 다시 복원하여 이전 실행 위치로 복원한다.
중단된 프로그램 실행 재개
PCB의 값을 이용하여 이전에 수행 중이던 프로그램을 재개한다.
3. Interrupt 관련 예시
(질문) 구글 검색창을 클릭 후 빈칸에 커서가 깜빡이고 있다. 이때 hello world를 작성하면 컴퓨터 내부에서 어떤 일이 발생하는가?
사용자 입력 → 외부 Interrupt 중 I/O Interrupt 발생 → CPU 인지 → CPU 작업 중이던 상태 저장 → 해당 인터럽트 처리 → 상태 복구 및 중단되었던 작업 재개
커널은 운영체제(OS)의 주요 구성 요소이며 컴퓨터 하드웨어와 프로세스를 잇는 핵심 인터페이스이다.
커널이라는 이름은 단단한 껍질 안의 씨앗처럼 OS 내에 위치하고 전화기, 노트북, 서버 또는 컴퓨터 유형에 관계없이 하드웨어의 모든 주요 기능을 제어하기 때문에 붙은 이름이다.
2. 커널의 기능
1) 메모리 관리: 메모리가 어디에서 무엇을 저장하는 데 얼마나 사용되는지를 추적합니다.
2) 프로세스 관리: 어느 프로세스가 중앙 처리 장치(CPU)를 언제 얼마나 오랫동안 사용할지를 결정합니다.
3) 장치 드라이버: 하드웨어와 프로세스 사이에서 중재자/인터프리터의 역할을 수행합니다.
4) 시스템 호출 및 보안: 프로세스의 서비스 요청을 수신합니다.
3. 이중 실행 모드 (Kernel mode vs User mode)
Kernel mode와 User mode에 대해 살펴보기 전에, 이를 나눈 근본적인 이유가 상당히 중요하다.
응용 프로그램이 시스템 자원에 직접 접근하게 되면 심각한 오류들을 유발할 수 있기 때문에, 각 응용 프로그램이 시스템 자원에 직접 접근하지 못하도록 하기 위해서 나누어 놓았다. 따라서, 자원에 대한 접근 권한은 커널에게만 부여하여, 자원에 대한 접근이 필요한 시점에는 System call을 통해서 간접적으로 실행하도록 하였다. 결국 자원에 대한 접근은 커널을 통해서만 접근할 수 있는 것이다.
1. 커널 모드 (Kernel mode / SuperVisor mode)
커널 모드에서 운영체제는 모든 하드웨어에 대한 완전한 접근이 가능하며, 기계가 실행할 수 있는 어떤 명령도 실행할 수 있다. 즉, Kernel mode는 운영체제가 CPU의 제어권을 가지고 명령을 수행하는 모드로 일반 명령과 특권 명령 모두 수행할 수 있다. 또한 모든 주소 공간에 접근이 가능하다.
2. 유저 모드 (User mode)
유저 모드는기계 명령 중 일부만을 실행할 수 있는 모드로, 특별히 기계의 제어에 영향을 미치거나 I/O를 하는 명령들은 사용자 모드에서 실행할 수 없다. 즉, User mode는 일반 사용자 프로그램이 CPU 제어권을 가지고 명령을 수행하는 모드이기 때문에 일반 명령만을 수행할 수 있다. 또한 사용자 주소 공간만 접근이 가능하다.
운영체제 구조
4. 일반/특권 명령
CPU가 수행하는 명령에는 2가지 명령이 있는데, 명령을 다음과 같이 구분하여 부적절한 사용을 막는다.
일반 명령은 메모리에서 자료를 읽어와 CPU에서 계산하고 결과를 메모리에 쓰는 등의 명령이고, 모든 프로그램이 수행할 수 있는 명령이다. 따라서 사용자 응용 프로그램은 특권 명령을 사용하지 못합니다.
특권 명령은 프로세스 제어, 파일 조작, 장치(I/O, 타이머 등) 조작, 정보 유지 보수, 통신, 보호 등의 명령으로, 항상 운영체제에서만 수행할 수 있으며, 특권 명령을 사용하고 싶을 때 사용하는 것이 바로 '시스템 콜'이며 OS에게 특권 명령을 대신 실행해달라고 요청하는 것입니다.
5. 논리 주소 공간
1. 사용자 주소 공간 (User space)
각 응용 프로그램이 나누어 적재되고 사용되는 공간
2. 커널 주소 공간 (Kernel space)
커널에 의해 배타적으로 사용 - 커널 코드, 커널 데이터, 디바이스 드라이버 등
커널
6. 커널과 관련된 Issue
1. 커널은 스스로 실행되는 프로세스인가?
X, 시스템 호출을 통해 호출되는 단순 함수/데이터의 집합
2. 커널은 실행 중이다?
X, 시스템 호출/인터럽트를 통해 커널 코드/ISR이 실행되고 있을 뿐이다. (능동적인 주체 x, 수동적인 대상 o)
3. 커널은 스택이나 힙을 갖는가?
X, 각 프로세스/스레드가 스택/힙 소유
app이 커널 코드 실행 시, 커널 공간에 커널 코드 실행을 위한 스택 생성, 복귀 시 해제
커널은 하나의 프로세스가 아니므로 그 자신만의 스택/힙을 갖지 않는다. 사용자 프로그램이 시스템 호출을 통해 간접적으로 커널 함수를 호출하게 되면, 현재 커널 코드의 실행을 위해 커널 영역에 stack이 임시로 생성이 될 수는 있다. 하지만 이는 커널이 관리하는 것이 아니라, 사용자 프로그램의 요청을 처리하기 위해 임시로 만들어진 stack/heap 에 불과하다. 따라서 시스템 호출을 마무리하고 복귀하면 없어진다.