1-1. 운영체제
운영체제란?
하드웨어와 응용 프로그램을 연결하는 소프트웨어 계층이다. 시스템 자원을 관리하고 자원을 사용할 수 있는 환경을 제공한다.
커널과 시스템 콜
커널은 운영체제의 핵심 요소로, 스케줄링과 메모리 관리 등을 담당한다.
운영체제는 중요 자원을 보호하기 위해서 커널 모드와 사용자 모드를 나눈다.
커널 모드는 하드웨어에 직접 접근할 수 있고 사용자 모드에서는 커널 모드의 자원에 접근할 수 없다.
사용자 모드에서 실행된 프로세스가 시스템 자원을 사용하기 위해서는 시스템 콜을 호출해야한다.
커널은 시스템 콜로 요청을 받고 다시 시스템 콜로 값을 반환한다.
시스템 콜의 예로는 자식 프로세스를 생성하는 fork(), 부모 프로세스가 자식 프로세스를 기다리는 wait()가 있다.
프로세스와 스레드
프로그램은 어떤 목적을 가진 명령어의 집합이다. 그리고 프로세스는 실행 중인 프로그램을 의미한다.
운영체제는 프로그램을 실행하기 위해 데이터를 메모리에 올리고 프로세스에 독립된 메모리 영역을 할당한다.
위 그림은 프로세스에 할당된 메모리 영역을 나타내고 있다.
사용자 영역은 바이트 코드로 이루어진 코드 영역이 가장 낮은 주소 번지에서 시작한다. 다음 데이터 영역은 전역 변수와 정적 변수가 저장되는 영역이다. 세부적으로 초기화된 영역과 초기화되지 않은 영역으로 구분한다. 다음은 동적 할당되는 힙 영역으로, 런타임 시에 영역 크기가 결정된다. 다음 영역은 스택 영역인데, 지역 변수와 함수의 매개 변수를 저장한다. 또한 힙과 스택 영역 사이에는 빈 공간이 존재한다. 스택 영역은 높은 주소 값에서 낮은 주소 값으로 할당되며 영역 크기가 컴파일 시기에 결정된다.
스택 영역이 힙 영역을 침범하는 경우를 스택 오버플로우라고 하고, 힙 영역이 침범하는 경우를 힙 오버플로우라고 한다.
스레드는 프로세스에서 실제로 실행되는 흐름의 단위를 의미한다.
프로세스 안에 존재하기 때문에 한 프로세스 안에 각 스레드들은 프로세스의 메모리 공간을 공유할 수 있다.
다만, 각 스레드는 고유한 스택 영역을 할당받는다.
PCB
운영체제가 프로세스를 제어할 수 있도록 필요한 정보가 저장된 공간이다.
PCB에는 프로세스의 상태, 프로세스 id, 다음 명령어의 주소, 부모와 자식의 id, 기타 상태 값을 저장한다.
프로세스의 생성
새로운 프로세스를 생성하기 위해서 기존 프로세스에서 fork() 함수를 호출할 수 있다.
fork 함수는 호출한 프로세스를 복사한다. 이 때, 기존 프로세스를 부모 프로세스, 생성한 프로세스를 자식 프로세스라고 한다.
fork 함수의 반환값은 부모 프로세스에서는 자식 프로세스의 pid 값이고, 자식 프로세스에서는 0이다.
#include <stdio.h>
#include <unistd.h>
int main() {
printf("start!\n");
int forkRet = fork();
if (forkRet == 0) {
printf("자식 프로세스의 pid: %d\n", getpid());
} else {
printf("부모 프로세스의 pid: %d\n", getpid());
}
return 0;
}
/*
start!
부모 프로세스의 pid: 4043
자식 프로세스의 pid: 4044
*/
위 코드는 fork 함수를 이용하여 새로운 프로세스를 만든 예제 코드이다.
fork 함수의 특징 중, 호출한 프로세스를 복사하는 것과 자식 프로세스는 0을 반환한다는 것으로 위 코드를 이해할 수 있다.
프로세스 상태도
생성(new): 프로세스가 생성되어 PCB를 가지고 있지만 운영체제로부터 승인 받기 전
준비(ready): 다른 자원이 준비가 끝나 cpu의 승인을 받고 준비 큐에서 기다리는 중
실행(running): cpu를 할당받아 실행 중
대기(waiting): 프로세스가 입출력이나 이벤트 발생을 기다려야 해서 실행을 멈춘 상태
종료(terminated): 프로세스 종료
멀티 프로세스와 멀티 스레드
동시성, concurrency
하나의 코어에서 여러 작업을 빠르게 번갈아 가면서 처리하는 방식이다.
콘텍스트 스위칭
하나의 cpu에서 여러 작업을 번갈아 가면서 처리하기 위해 처리 중인 작업을 교체하는 것을 의미한다.
병렬성, parallelism
cpu가 여러 코어로 구성되어 있어 각 cpu에서 작업을 동시에 처리하는 방식이다.
오버헤드, overhead
cpu가 처리하던 프로세스를 교체하기 위해서 현재 프로세스의 메모리 영역을 저장하고 다음 프로세스를 불러오기 위해 필요한 시간
멀티 프로세스
응용 프로그램을 여러 프로세스로 구성하는 것을 의미한다.
독립적인 메모리 영역을 사용하기 때문에 한 프로세스가 죽어도 다른 프로세스가 영향을 주지 않는다는 장점을 가지고 있으나,
시간과 메모리 공간을 많이 사용한다는 단점이 있다.
프로세스 간에 공유할 자원이 있다면 IPC를 사용한다.
위 그림은 멀티 프로세스의 구조를 나타낸다.
멀티 스레드
스레드를 여러 개 생성하여 작업을 처리한다.
스레드끼리 코드 영역과 데이터, 힙을 공유하기 때문에 오버헤드가 적게 발생하고 IPC를 사용하지 않아도 되서 자원 소모가 적다.
하지만 한 스레드에 문제가 생기면 다른 스레드에 영향을 줄 수 있고, 공유 자원에 대한 동기화가 필요하다.
컨텍스트 스위칭
인터럽트, interrupt
입출력 관련 이벤트가 발생하거나 타임 아웃이 되었을 때, 자식 프로세스를 생성할 때 발생하여 cpu에 요청하여 실행에서 벗어나게 한다.
컨텍스트, context
cpu가 처리하는 프로세스의 정보를 의미한다.
위 그림은 프로세스 P_0와 P_1이 번갈아 실행되는 과정을 나타낸 그림이다.
인터럽트나 시스템 콜에 의해 중간된 P_0는 pcb에 프로세스 정보가 저장된다.
다음으로 P_1의 정보를 가져와 처리하기 시작하는데 이 사이 간격동안 어떠한 프로세스도 실행 상태에 있지 않다.
이 시간 동안 cpu은 어떤 일도 실행하고 있지 않으므로 오버헤드가 발생한다라고 표현한다.
프로세스가 중단되었다 다시 이어서 실행할 수 있는 이유는 pcb에 프로그램 카운터와 스택 포인터가 저장되어 있기 때문이다.
프로그램 카운터(pc)는 다음에 처리해야 하는 명령어의 주소를 의미하고,
스택 포인터는 스택 영역에서 데이터가 채워진 가장 높은 주소 값을 의미한다.
프로세스 동기화
경쟁 상태, race condition
프로세스나 스레드가 공유 자원에 동시에 접근해 경쟁하는 상태
임계 영역, critical section
공유 자원에 접근할 수 있는 코드 영역. 프로세스나 스레드가 접근하는 순서에 따라 결과가 달라질 수 있다.
프로세스 동기화, process synchronization
경쟁 상태가 발생하는 것을 방지하고 공유 자원에 대한 데이터 일관성이 유지되도록 한다.
공유 자원으로 동시에 접근하는 것을 막기 위해서는 다음의 3가지 조건이 필요하다.
- 상호배제 기법: 한 작업이 임계 영역을 실행 중이라면, 다른 프로세스가 임계 영역에 접근할 수 없다.
- 진행: 임계 영역을 실행 중인 프로세스가 없다면, 다른 프로세스가 실행할 수 있어야 한다.
- 한정된 대기: 임계 영역으로의 접근이 무한정 대기하지 않아야 한다.
뮤택스, mutex
락을 가진 프로세스만이 공유 자원에 접근할 수 있는 방법이다.
예를 들면, 화장실의 열쇠를 가지고 있는 사람만이 화장실을 이용할 수 있는 것과 유사하다.
여기서 화장실은 임계 영역, 화장실을 이용하려는 사람이 프로세스에 해당하고, 열쇠가 락에 해당한다.
참고로 화장실 열쇠가 없는 것을 발견한 사람은 화장실 열쇠가 제자리로 돌아올 때까지 계속해서 확인하는 수밖에 없는데
이를 바쁜 대기(busy waiting)이라고 한다.
세마 포어, semaphore
공유 자원에 접근할 수 있는 프로세스의 수를 정해 접근을 제어하는 방법이다.
예를 들면, 화장실이 3개가 있고 모든 화장실을 열 수 있는 열쇠 3개가 있다고 하자.
역시, 화장실이 임계 영역이고 화장실을 이용하려는 사람이 프로세스에 해당한다.
화장실과 열쇠의 개수는 공유 자원에 접근할 수 있는 프로세스의 수를 제어한다.
만약, 4명의 사용자가 화장실을 이용하려고 하면 마지막 한 명은 이용할 수 없는데,
가장 먼저 화장실을 나온 사용자가 그 한 명에게 신호를 보내 사용하도록 한다.
이 부분이 뮤택스의 바쁜 대기와 다르다.
교착 상태
2개 이상의 프로세스가 각자 자원을 소유한 채로 서로의 자원을 요구하며 기다리는 상태를 의미한다.
다음은 교착 상태의 필요 충분 4가지 조건이다.
교착 상태를 해결하기 위해서는 아래 조건 중에 하나를 제거하면 된다.
- 상호배제: 하나의 공유 자원에 하나의 프로세스만 접근할 수 있다.
- 점유와 대기: 프로세스가 자원을 소유한 채로, 다른 프로세스의 자원을 사용하기 위해 대기한다.
- 비선점: 다른 프로세스에 할당된 자원을 뺏을 수 없다.
- 환형 대기: 프로세스가 자신의 자원을 점유하면서 앞이나 뒤에 있는 프로세스의 자원을 요구한다.
스레드 안전, thread safe
멀티 스레드 환경에서 하나의 변수, 함수, 객체에 여러 스레드가 접근해도 문제가 없는 것을 의미한다.
여러 시도에서 다른 결과가 나온다면 스레드가 안전하지 않다고 한다.
IPC의 종류
- 공유 메모리에 의한 통신
- 소켓
- 세마포어
- 파이프
- FIFO 형태의 메세지 큐
좀비 프로세스와 고아 프로세스
좀비 프로세스는 자식 프로세스가 종료되었지만, 부모 프로세스가 회수하지 못한 상태를 의미한다.
좀비 프로세스가 쌓이면 자원이 낭비될 수 있다.
고아 프로세스는 부모 프로세스가 먼저 죽게되는 경우를 말한다.
자식 프로세스의 부모 프로세스 pid를 init 프로세스(pid가 1)로 바꿔주어
자식 프로세스가 종료되었을 때, init 프로세스가 자원을 회수할 수 있도록 한다.
출처
기술 면접 대비 cs전공 핵심 요약집 - 길벗
'컴퓨터과학' 카테고리의 다른 글
[전공 복습] 2. 네트워크 (1) | 2024.03.13 |
---|---|
[전공 복습] 1-2. 운영체제 (1) | 2024.03.13 |
[컴퓨터 네트워크] ICMP (0) | 2024.03.12 |
[운영체제] 프로세스 동기화 (1) | 2024.03.12 |
파이썬 정리 (2) (1) | 2024.01.07 |