JSCODE 모의면접 스터디
운영체제 6기 2주차
목차
1. 프로세스
프로그램과 프로세스
프로그램
프로그램(program)은 컴퓨터에서 실행할 수 있는 파일을 통칭한다.
단, 아직 파일을 실행하지 않은 상태이기 때문에 정적 프로그램을 프로그램으로 줄여 부른 것이다.
프로세스
프로세스(process)는 "실행 중인 프로그램"이다.
프로그램은 실행되기 전까지는 보조기억장치에 저장되어 있는 데이터일 뿐이지만,
메모리에 적재하고 실행하는 순간 그 프로그램은 "프로세스"가 된다.
프로세스 제어 블록(PCB)
프로세스 제어 블록(PCB)은 프로세스와 관련된 정보를 저장하는 자료 구조이다.
운영체제는 수많은 프로세스 사이에서 PCB로 특정 프로세스를 식별하고 해당 프로세스를 처리하는 데 필요한 정보를 판단한다.
하나의 프로세스를 식별하기 위한 정보들이 저장되는데,
대표적인 정보로는 프로세스 ID(PID), 레지스터 값, 프로세스 상태, CPU 스케줄링 정보, 메모리 관리 정보 등이 있다.
PCB 생명주기
- 프로세스가 생성되면 커널 영역에 PCB가 생성됨
- 실행 중에는 프로세스 상태에 따라 정보 갱신됨
- 실행이 끝나면 PCB가 폐기됨
프로세스 문맥(Context)
프로세스 문맥은 프로세스의 특정 시점의 상태를 표현하는 정보이다.
하나의 프로세스에서 다른 프로세스로 실행 순서가 넘어갈 때 사용하던 중간 정보를 백업해야 한다.
이 중간 정보, 즉 하나의 프로세스 수행을 재개하기 위해 기억해야할 정보가 문맥이다.
문맥은 PCB에 저장되어 관리된다.
PCB에 저장된 문맥을 통해 언제든 해당 프로세스의 실행을 재개할 수 있다.
문맥에는 프로그램 카운터, 각종 레지스터 값, 메모리 정보, 실행을 위해 열었던 파일, 사용한 입출력 장치 등이 있다.
문맥 교환(Context Switch)
문맥 교환은 기존 프로세스의 문맥을 PCB에 백업하고, 새로운 프로세스를 실행하기 위해 문맥을 PCB로부터 복구하여 새로운 프로세스를 실행하는 것이다.
여러 프로세스가 끊임없이 빠르게 번갈아가며 실행되는 원리이다.
문맥 교환 발생 상황
- CPU 사용 시간이 만료되었을 때
- 인터럽트가 발생했을 때
- 자식 프로세스를 생성했을 때
문맥 교환을 너무 자주 하면 오버헤드가 발생할 수 있다.
프로세스의 메모리 구조
하나의 프로세스는 사용자 영역에 크게 코드 영역, 데이터 영역, 힙 영역, 스택 영역으로 나뉘어 저장된다.
프로세스의 메모리 구조 정보는 문맥의 일부로서 PCB에 저장된다.
정적 할당 영역 (크기가 고정된 영역)
- 코드 영역 (= 텍스트 영역)
- 실행할 수 있는 코드, 즉 기계어로 이루어진 명령어가 저장된다.
- CPU가 실행할 명령어가 담겨 있기 때문에 쓰기가 금지된 읽기 전용(read-only) 공간이다.
- 데이터 영역
- 프로그램이 실행되는 동안 유지할 데이터가 저장되는 공간이다.
- 프로그램 시작과 동시에 할당되고 프로그램이 종료되어야 메모리가 해제된다.
- 전역 변수와 정적 변수(static)이 할당된다.
동적 할당 영역 (크기가 가변적인 영역)
- 힙 영역
- 프로그래머가 직접 할당할 수 있는 저장 공간이다.
- 할당된 메모리는 필요하지 않을 때 반드시 해제해야 한다.
- 메모리 누수 : 할당된 메모리를 반환하지 않아 메모리가 낭비되는 현상
=> Java에서는 가비지 컬렉터가 자동으로 메모리를 해제함 - 참조형(Reference Type) 데이터 타입을 갖는 객체(인스턴스), 배열 등이 저장된다.
- 메모리의 낮은 주소에서 높은 주소로 할당된다. => 선입선출(FIFO) 구조
- 스택 영역
- 데이터를 일시적으로 저장하는 공간이다.
- 지역 변수와 매개 변수가 저장되는 영역이다.
- -> 선언된 블록이 종료되면 자동으로 메모리가 해제된다.
- 메모리의 높은 주소에서 낮은 주소로 할당된다. => 후입선출(LIFO) 구조
2. 프로세스의 실행과 상태
프로세스 상태와 전이
생성 상태
프로그램이 메모리에 적재되어 PCB를 할당받은 상태이다. (즉, 프로세스를 생성 중인 상태)
프로세스 생성 후 메모리 공간이 충분하면 프로세스 주소 공간을 할당한 후 프로세스를 준비 상태로 바꾼다.
준비 상태
프로세스가 CPU를 할당받기 위해 기다리고 있는 상태이다.
CPU 스케줄링을 통해 실행 상태로 전환된다. (디스패치)
* CPU 스케줄링: 운영체제가 준비 상태의 여러 프로세스 중 CPU에 할당하는 순서를 정하는 것
실행 상태
준비 상태의 프로세스가 CPU를 할당받아 실행 중인 상태이다.
프로세스는 할당된 일정 시간 동안만 CPU를 사용할 수 있고,
할당된 시간을 모두 사용한다면(타이머 인터럽트가 발생하면) 다시 준비 상태가 된다.
프로세스가 입출력 작업이 필요해 시스템 콜을 하게 되면 입출력이 종료될 때까지 대기 상태가 된다.
대기 상태
실행 상태인 프로세스가 입출력 등의 작업을 요청하면 CPU를 반납하고 요청된 작업이 완료될 때까지 기다리는 상태이다.
요청된 작업이 완료되면 대기 상태의 프로세스는 다시 준비 상태로 CPU 할당을 기다린다.
종료 상태
프로세스가 정상적으로 실행이 완료된 상태이다.
프로세스가 종료되면 운영체제는 할당된 모든 자원을 회수하고, 마지막으로 PCB를 삭제하여 프로세스를 정리한다.
프로세스 생성
프로세스는 실행 도중 시스템 콜을 통해 다른 프로세스를 생성할 수 있다.
새로운 프로세스(자식 프로세스)는 기존 프로세스(부모 프로세스)에 의해 생성된다.
- 부모 프로세스: 새 프로세스를 생성한 프로세스
- 자식 프로세스: 부모 프로세스에 의해 생성된 프로세스
프로세스 생성 방식
1. fork만 호출하는 방식
- 부모 프로세스와 동일한 코드를 실행하는 자식 프로세스 생성
- 부모의 메모리 공간을 그대로 복사하여 사용
2. fork-exec 방식
- fork로 자식 프로세스를 생성한 후 exec로 새로운 프로그램을 실행
- 일반적으로 많이 사용되는 프로세스 생성 방식
fork() 시스템 콜
fork는 실행 중인 프로세스의 복사본을 생성하는 시스템 콜이다. (부모 프로세스의 복사본 -> 자식 프로세스)
부모 프로세스의 자원들(메모리 내용, 열린 파일의 목록 등)이 자식 프로세스에 복사되지만, PID 값과 저장된 메모리 위치는 새로 할당된다.
fork 호출 결과는 프로세스에 따라 다르다.
- 부모 프로세스: 자식 프로세스의 PID 반환
- 자식 프로세스: 0 반환
- 실패: 음수 반환
exec() 시스템 콜
exec는 자신의 메모리 공간을 새로운 프로그램으로 덮어쓰는 시스템 콜이다.
실행 시 코드 영역과 데이터 영역은 새로운 프로그램의 내용으로 교체되고, 나머지 영역은 초기화된다.
fork-exec 수행 과정
- 부모 프로세스가 fork를 통해 자신의 복사본인 자식 프로세스 생성
- 자식 프로세스는 exec를 통해 새로운 프로그램으로 자신의 메모리 공간 교체
- 두 가지 방식 중 하나로 실행
- 부모와 자식이 병행하게 실행
- 부모가 wait를 호출하여 자식의 종료를 대기
3. 스레드
스레드는 프로세스를 구성하는 실행의 흐름 단위이다.
프로세스는 하나 이상의 스레드를 갖기 때문에, 하나의 프로세스 안에서 여러 작업을 동시에 실행할 수 있다.
프로세스를 생성하면 기본적으로 하나의 main 스레드가 생성되고, 추가 스레드는 개발자가 프로그래밍을 통해 생성할 수 있다.
스레드의 메모리 구조
스레드는 프로세스의 실행의 흐름 단위로서, 스레드가 여러 개 있으면 여러 작업을 동시에 실행할 수 있다.
이것은 프로세스의 스레드들이 실행에 필요한 최소한의 정보(프로그램 카운터, 레지스터, 스택 등)만을 유지한 채 프로세스 자원을 공유하며 실행되기 때문에 가능하다.
스레드의 자원 공유
프로세스끼리는 기본적으로 자원을 공유하지 않지만, 스레드끼리는 같은 프로세스 내의 자원을 공유한다.
스레드는 프로세스의 메모리 영역(코드, 데이터, 힙, 스택) 중 스택만 독립적으로 할당받고, 나머지 영역은 다른 스레드들과 공유한다.
- 스레드 별로 독립적으로 가지는 자원
- 스레드 ID
- 프로그램 카운터를 포함한 레지스터 값
- 스택 영역
- 함수 호출 시 전달되는 인자, 되돌아갈 주소값, 함수 내 지역변수 등을 저장
- 독립적인 스택을 가짐으로써 스레드는 독립적인 실행 흐름을 가질 수 있음
- 프로세스 내의 다른 스레드들과 공유하는 자원
- 코드 영역
- 데이터 영역
- 힙 영역
- 열린 파일과 같은 운영체제 자원
스레드 제어 블록(TCB)
스레드 제어 블록(TCB)는 각 스레드마다 운영체제에서 유지하는 스레드에 대한 정보를 담고 있는 자료 구조이다.
스레드가 프로세스 내에 위치한 것처럼 TCB는 PCB 안에 들어있다.
TCB는 스레드의 상태 정보, 스레드 ID, 스레드 우선순위, 스케줄링 정보 등을 저장한다.
TCB 생명주기
- 스레드가 생성되면 PCB 내부에 TCB가 생성됨
- 스레드가 종료되면 TCB가 폐기됨
스레드 종류
스레드는 구현되는 수준에 따라 사용자 수준 스레드와 커널 수준 스레드로 나뉜다.
최근 운영체제는 사용자 스레드와 커널 스레드를 1:1로 매핑(one-to-one model)하여 멀티프로세서 환경에서 병렬 처리가 가능하도록 한다.
사용자 수준 스레드 (User-Level Thread)
사용자 영역에서 라이브러리를 통해 구현되는 스레드로, 라이브러리는 스레드의 생성 및 스케줄링 등을 관리한다.
커널은 프로세스만 인식하고 스레드는 인식하지 못하기 때문에 프로세스 전체를 하나의 실행 단위로 본다.
장점
- 커널의 개입이 없어 생성 및 관리가 빠름
- 유저 모드와 커널 모드 간 전환이 없어 오버헤드가 적음
- 운영체제와 독립적이라 이식성이 높음
단점
- 커널이 스레드를 인식하지 않으므로 하나의 스레드가 중단되면 전체 프로세스가 중단됨
- 멀티프로세서 활용 불가능 (커널이 프로세스만 인식하기 때문에 여러 프로세서에서 병렬로 실행 못함)
커널 수준 스레드 (Kernel-Level Thread)
운영체제가 직접 지원하는 스레드로, 커널이 스레드의 생성 및 스케줄링을 관리한다.
커널이 스레드를 인식하기 때문에 각 스레드를 실행 단위로 인식하여 관리할 수 있다.
장점
- 커널이 각 스레드를 개별적으로 관리할 수 있어 한 스레드가 중단 되어도 다른 스레드는 계속 실행 가능
- 멀티프로세서 시스템에서 스레드를 병렬로 실행 가능
단점
- 스레드 관련 작업마다 커널 호출이 필요해 오버헤드가 큼
- 상대적으로 많은 자원을 필요로 함
사용자 수준 스레드 VS 커널 수준 스레드
사용자 수준 스레드 | 커널 수준 스레드 | |
구현 위치 | 사용자 영역 | 커널 영역 |
관리 주체 | 스레드 라이브러리 | 운영체제 커널 |
성능 | 생성 및 관리 빠름, 오버헤드 적음 | 생성 및 관리 느림, 오버헤드 큼 |
안전성 | 하나가 종료되면 모두 종료됨 | 스레드 개별로 종료 가능 |
병렬 처리 | 불가능 | 가능 |
사용자 수준 스레드는 커널의 개입 없이 사용자 영역에서 관리되어 빠르지만, 커널이 스레드를 인식하지 못해 하나의 스레드 종료 시 모든 스레드가 중단되고 병렬 처리가 불가능하다.
커널 수준 스레드는 커널이 직접 관리하여 상대적으로 느리지만, 스레드를 개별적으로 인식하고 관리할 수 있어 독립적인 실행과 병렬 처리가 가능하다.
4. 멀티 프로세스와 멀티 스레드
멀티 프로세스
멀티 프로세스는 하나의 응용 프로그램이 여러 개의 프로세스를 동시에 실행하는 것이다.
하나의 부모 프로세스가 여러 개의 자식 프로세스를 생성하여 구성한다.
장점
- 프로그램 안전성
- 각 프로세스가 독립적인 메모리 공간을 가짐
- 한 프로세스의 오류가 다른 프로세스에 영향을 주지 않음
- 시스템 확장성
- 각 프로세스가 독립적이므로 새로운 기능이나 모듈 추가가 용이함
- 다른 프로세스에 영향 없이 개별 프로세스 수정 가능
단점
- 문맥 교환(Context Switching) 오버헤드
- 프로세스 전환 시 많은 비용 발생
- CPU 캐시 메모리를 초기화, 프로세스 상태를 저장, 불러올 데이터를 준비 등
- 자원 공유의 비효율성
- 독립적인 메모리 공간을 가지므로, 메모리 사용량 증가
- 프로세스 간 통신(IPC)이 필요하며, 이것 자체로 오버헤드가 발생
프로세스 간 통신 (IPC)
프로세스는 기본적으로 독립적이지만 필요한 경우 IPC(Inter-Process Communication)을 이용한다.
- Message Passing (메시지 전달)
- 프로세스 간 커널을 통해 메시지를 전달하는 방식
- Direct Communication: 통신할 프로세스 이름 명시
- Indirect Communication: mailbox(port)를 통해 전달
- Shared Memory (공유 메모리)
- 프로세스 간에 공유 메모리 영역을 생성하고, 이 영역을 통해 서로 데이터를 주고받는 방식
- 커널에 시스템 콜을 통해 공유 메모리 사용을 요청
- 공유 메모리 설정 후 프로세스들이 별도의 커널 도움없이 직접 접근 가능
멀티 스레드
멀티 스레드는 하나의 프로세스 안에 여러 개의 스레드가 동시에 작업을 수행하는 것이다.
하나의 프로그램에서 여러 개의 동작을 동시에 처리할 수 있다.
많은 운영체제들이 기본적으로 멀티 스레드를 지원하고 있다.
장점
- 시스템 자원 효율성
- 스레드는 프로세스 내 자원을 공유하여 메모리를 효율적으로 사용
- 프로세스 간 통신(IPC) 없이 스레드 간 데이터 공유 가능
- 처리 비용 감소
- 스레드 생성 및 종료가 프로세스보다 빠름
- 문맥 교환 비용이 프로세스보다 적음 (스택, 레지스터만 교체)
- 응답 시간 단축
- 스레드 간 작업 분담으로 빠른 처리 가능
- 한 스레드가 대기 중일 때도 다른 스레드가 실행 가능
단점
- 자원 공유로 인한 문제
- 하나의 스레드의 오류가 전체 프로세스에 영향을 미침동기화 문제
- 공유 자원 접근 시 동기화 작업 필요
- 동기화 작업으로 성능 저하와 데드락(교착 상태) 발생 가능
- 디버깅 어려움
- 동시 실행되는 스레드 추척이 어려움
- 자원 접근 시점이나 실행 순서 파익이 어려움
멀티스레드 프로그래밍 주의점
- 동기화 처리
- 공유 자원 접근 시 임계 영역에 대해 뮤텍스나 세마포어 방식 활용
- 데드락 방지를 위한 동기화 설계
- 스레드 개수 관리
- 과도한 스레드 생성 시 문맥 교환 오버해드 발생
- 스레드 풀 활용
- 예외 처리
- 스레드 오류가 전체 프로세스에 영향을 미치므로 적절한 예외 처리
멀티프로세스 VS 멀티스레드
멀티 프로세스 | 멀티 스레드 | |
메모리 공간 | 많은 메모리 공간 차지 | 적은 메모리 공간 차지 |
문맥 교환(Context Switching) | 느림 (CPU 캐시 메모리 초기화 필요) | 빠름 |
안정성 | 높음 | 낮음 (하나의 스레드가 전체 영향) |
자원 공유 | 별도의 IPC 필요 | 스레드 간 자원 공유 가능 |
멀티프로세스와 멀티스레드는 모두 동시에 여러 작업을 수행한다는 공통점이 있다.
적용할 시스템에 따라 적합한 방식을 선택해야 한다.
- 멀티 프로세스 => 메모리 구분이 필요한 경우
- 멀티 스레드 => 잦은 문맥 교환 또는 데이터 공유가 필요한 경우, 자원을 효율적으로 사용해야 하는 경우
5. 스레드 안전 (Thread Safe)
Thread Safe란 여러 스레드가 동시에 접근하더라도 프로그램이 예상한 대로 동작하고 데이터 무결성을 유지하는 것을 의미한다.
하나의 함수가 한 스레드로부터 호출되어 실행 중일 때, 다른 스레드가 그 함수를 호출하여 동시에 함께 실행되더라도 각 스레드에서의 함수의 수행 결과가 올바르게 나오는 것이다.
Thread Safe 설계 방법
- 불변 객체 (Immutable Objects)
- 객체 생성 후 상태가 변하지 않는 객체
- 여러 스레드에서 안전하게 공유할 수 있음
- 상호 배제 (Mutual exclusion)
- 여러 스레드가 동시에 공유 자원에 접근하지 못하게 하는 방법
- synchronized 블록, Lock 등을 통해 임계 영역을 설정하여 하나의 스레드만 접근하도록 함
- 한 스레드가 사용 중이면 다른 스레드는 대기
- 스레드 로컬 저장소 (Thread-local storage, TLS)
- 각 스레드가 독립적인 저장소 사용
- 스레드 간 데이터 공유가 없어 동기화 불필요
- 원자적 연산 (Atomic operations)
- 중단되지 않는 연산을 의미
- 연산을 하나의 단위로 처리하여 다른 스레드의 중간 개입을 방지
- 재진입성 (Re entrancy)
- 동일한 스레드나 다른 스레드가 실행 중인 함수를 호출해도 올바르게 실행\
- 전역/정적 변수 대신 매개변수나 지역변수로 상태 정보 저장
- 공유 자원 접근 시 원자적 연산 사용
REF
https://kdhyo98.tistory.com/103
https://velog.io/@sweet_sumin/PCBTCB
https://fourjae.tistory.com/entry/OS-Thread-Safe%EC%8A%A4%EB%A0%88%EB%93%9C-%EC%95%88%EC%A0%84
'Study > 운영체제' 카테고리의 다른 글
[운영체제] 가상 메모리 (2) - 성능 최적화와 관리 기법 (0) | 2024.12.02 |
---|---|
[운영체제] 가상 메모리 (1) - 기본 개념과 구현 방식 (0) | 2024.11.24 |
[운영체제] 프로세스 동기화 (0) | 2024.11.19 |
[운영체제] CPU 스케줄링 (0) | 2024.11.12 |
[운영체제] 운영체제 개요 & 컴퓨터 시스템 동작원리 (0) | 2024.10.28 |
댓글