OS가 관리하는 자원
• 하드웨어 자원: 프로세서(CPU), 메모리(RAM), 입출력 장치, 통신 장치
• 소프트웨어 자원: 각종 응용 프로그램, API 제공으로 하드웨어 조작을 간단히 해결
2. 운영체제의 역사
• 1940년대(OS 없음): 초기 디지털 컴퓨터, 운영체제 없이 전선을 직접 연결
• 1950년대(단일 배치 처리): 한 번에 한 가지 작업을 수행하는 단일 스트림 배치 처리 시스템
• 1960년대(멀티프로그래밍/시분할): 여러 작업 동시처리, IBM System/360, CTSS·TSS·Multics 등장
• 1970년대(TCP/IP/네트워크): 개인 컴퓨터 혁명 시작, 이더넷 등장, 보안 문제 대두
• 1980년대(PC/GUI): 마이크로프로세서 발전, 그래픽 사용자 인터페이스 등장, 클라이언트/서버 모델
• 1990년대(WWW/오픈소스): 월드 와이드 웹 탄생, Windows 성장, 리눅스 등 오픈소스 확산
• 2000년대~(미들웨어/병렬): 미들웨어, 웹 서비스, 고도 병렬성(massive parallelism), 표준화
인터넷과 WWW의 역사
• ARPAnet: 오늘날 인터넷의 조상으로 중앙 통제 없이 작동
• TCP/IP 프로토콜: 오류 없는 전송을 보장
• WWW: 1989년 CERN에서 하이퍼링크 기반 문서 공유로 개발 시작
3. 운영체제 환경
• 범용 컴퓨터: 대용량 메모리, 고속 프로세서, 주변 장치. 예: PC, 워크스테이션, 서버
• 임베디드 시스템: 소형 기기에 특화, 효율적 자원 관리와 전력 관리가 중요. 예: 휴대폰, PDA
• 실시간 시스템: 정해진 시간 안에 반드시 완료(소프트/하드). 예: 비행기 제어, 심박기
• 가상 머신: 컴퓨터를 소프트웨어로 추상화해 여러 OS를 동시 실행. 예: VMware, JVM
4. 운영체제의 구성 요소와 목표
핵심 구성 요소 5가지(시험 단골)
① 프로세스 스케줄러: CPU를 어떤 프로그램에 얼마나 줄지 결정
② 메모리 관리자: 메모리(RAM)를 각 프로그램에 배분하고 회수
③ 입출력 관리자: 키보드, 마우스, 프린터 등 입출력 장치 관리
④ 프로세스 간 통신 관리자(IPC): 프로그램들끼리 데이터를 주고받을 수 있게 해줌
⑤ 파일 시스템 관리자: 파일 저장, 불러오기, 디렉터리 구조 관리
OS 목표 8가지
효율성(자원을 낭비 없이 최대한 활용), 견고함(오류가 발생해도 시스템이 버팀), 규모 확장성(사용자/데이터가 늘어나도 잘 작동), 확장성(새로운 기능 추가가 쉬움), 이식성(다른 하드웨어 환경에서도 작동), 보안(외부 침입이나 악성코드 방어), 상호 작용성(사용자와 실시간으로 소통), 사용성(쓰기 편하고 직관적인 인터페이스)
5. 운영체제 아키텍처
• 모놀리식 커널: 모든 기능이 커널에 통합. 성능이 빠르지만(직접 호출) 오류·악성코드에 취약
• 계층적 구조: 기능별로 계층을 구분해 위아래 계층만 소통. 디버깅·수정이 쉽지만 성능이 다소 저하됨
• 마이크로커널: 핵심 기능만 커널에 두고 나머지는 외부에서 처리. 확장성·이식성·보안이 높지만 모듈 간 통신 오버헤드가 있음
• 네트워크 OS: 다른 컴퓨터 자원에 네트워크로 접근 가능
• 분산 OS: 여러 컴퓨터 자원을 하나처럼 관리(구현이 복잡하고 복잡한 알고리즘이 필요)
OS는 컴퓨터 부품들이 서로 잘 협력하도록 관리하는 총감독입니다.
• 하드웨어 자원: 프로세서, 메모리, 2차 저장소, 기타 장치
• 소프트웨어 자원: 프로세스, 스레드, 파일, 데이터베이스
2. 하드웨어 구성 요소
메인보드
PCB(인쇄 회로 기판)는 장치들을 전기적으로 연결해주는 기판이며, 프로세서·메모리 등을 꽂는 슬롯과 BIOS 같은 저수준 기능 담당 칩을 포함합니다.
프로세서(CPU)
• 명령어 페치기: 명령어를 레지스터에 불러옴
• 명령어 해석기: 명령어를 해석해서 실행 처리기에 전달
• ALU: 덧셈·곱셈 등 산술 연산, 대소비교 등 논리 연산 수행
• 캐시(L1, L2): 자주 쓰는 데이터를 빠르게 접근하기 위해 복사해두는 고속 메모리
• 레지스터: CPU 내부의 초고속 메모리, 데이터 조작 시 반드시 여기에 있어야 함
메모리 계층(시험 자주 출제)
속도는 빠름→느림, 가격은 비쌈→쌈, 용량은 작음→큼 순으로 변합니다.
1위(가장 빠름) 레지스터: CPU 내부, 지연 0 사이클
2위 L1 캐시(SRAM): 지연 2~3 사이클
3위 L2 캐시(SRAM): 지연 ~10 사이클
4위 메인 메모리(DRAM): 지연 ~30 사이클
5위(가장 느림) 2차 저장소(HDD/SSD): 지연 ~10^6 사이클
비유하면 레지스터는 책상, 캐시는 책꽂이, 메인메모리는 방 안 창고, 하드디스크는 외부 창고이며 빠를수록 용량이 작고 비쌉니다.
휘발성 메모리는 전원을 끄면 데이터가 사라지는 레지스터, 캐시, 메인 메모리이고, 비휘발성 메모리는 전원이 꺼져도 유지되는 하드디스크 등 2차 저장소입니다.
메인 메모리(RAM)
휘발성 임의 접근 메모리로 어떤 순서로든 데이터에 접근할 수 있습니다.
• DRAM(동적 램): 재생 회로가 필요, 일반 PC에 사용
• SRAM(정적 램): 재생 회로가 불필요, 캐시에 사용, 더 빠르고 비쌈
DMA(직접 메모리 접근)
핵심 장점은 CPU가 입출력 중에도 다른 작업을 할 수 있어 성능이 향상된다는 점입니다.
① 요청: 프로세서가 입출력 컨트롤러에 요청을 보냄
② 전송: 디스크에서 메모리로 직접 데이터 전송(프로세서 개입 없이)
③ 완료: 완료되면 인터럽트로 프로세서에 알림
3. 하드웨어의 운영체제 지원
실행 모드(시험 자주 출제)
• 사용자 모드(User): 일반 프로그램이 실행되는 모드, 접근 제한이 있음
• 커널 모드(Super): OS가 실행되는 모드, 특권 명령어 실행과 모든 자원 접근이 가능
메모리 보호는 프로세스가 자신에게 할당되지 않은 메모리에 못 들어가게 막는 기능입니다. 인터럽트는 장치가 이벤트 발생 시 프로세서에 보내는 신호이고, 예외(Exception)는 오류에 대한 반응으로 발생하는 인터럽트입니다.
부트스트랩핑(부팅 과정)
① BIOS가 시스템 하드웨어를 초기화
② 2차 저장소의 부트 섹터에서 명령어를 읽어 메인 메모리에 로드
③ OS 실행 시작
4. 캐싱과 버퍼링
• 캐시 적중(Hit): 찾는 데이터가 캐시에 있는 경우 → 즉시 사용
• 캐시 실패(Miss): 찾는 데이터가 캐시에 없는 경우 → 메인 메모리까지 가야 함
• 버퍼: 다른 속도의 장치 간 임시 저장 공간, 비동기 전송이 가능해짐
• 스풀링: 느린 장치 사이에 중간 매개체를 두는 기술(예: 프린터 대기열)
5. API, 펌웨어, 미들웨어
API(응용 프로그래밍 인터페이스)
프로그래머가 운영체제에 서비스를 요청할 수 있는 함수들의 집합입니다. 소프트웨어와 OS 간 통신은 오직 API를 통해서만 가능하며, 예로는 POSIX 표준(리눅스/유닉스), 윈도우 API가 있습니다. 식당 메뉴판에 비유하면 손님(프로그램)이 직접 주방(OS)에 들어가지 않고 메뉴판으로 주문하는 것과 같습니다.
펌웨어(Firmware)
ROM(읽기 전용 메모리) 또는 플래시 메모리에 저장된 실행 가능한 명령어로, 마이크로프로그래밍으로 작성됩니다(기계어보다 더 낮은 수준). 예로는 BIOS, TV 리모컨, 라우터, Arduino가 있으며, 전원을 꺼도 지워지지 않는 비휘발성이라 하드웨어와 소프트웨어의 중간 단계로 볼 수 있습니다.
미들웨어(Middleware)
분산 시스템에서 서로 다른 컴퓨터의 프로그램들이 통신하게 해주는 소프트웨어로, 이기종 컴퓨터 플랫폼에서도 프로그램 실행이 가능합니다. 예: ODBC(MySQL, Oracle, MS SQL 등 어떤 DB든 같은 코드로 접근 가능)
PART 2 — 컴파일링 · 링킹 · 로딩
전체 흐름: .c 파일 → [컴파일] → .o 파일 → [링킹] → 실행파일 → [로딩] → 메모리에서 실행
6. 컴파일링(Compiling)
컴파일링은 사람이 읽을 수 있는 소스코드를 컴퓨터가 이해하는 기계어로 번역하는 과정입니다. 결과물은 오브젝트 파일(.o)이며 아직 실행할 수 없고, 대표 컴파일러는 GCC입니다.
핵심 개념 비유
• 프로세스: 요리사가 레시피(프로그램)를 들고 실제로 요리하는 행위
• PCB: 요리사의 이름표 + 현재 진행 상태 메모
• 메모리 영역: 주방의 구역 나누기(재료 창고, 조리대, 냉장고)
• fork(): 요리사를 하나 더 복제해서 같은 레시피로 동시에 요리
• pipe(): 요리사끼리 재료를 전달하는 컨베이어 벨트
• signal(): 주방장이 “멈춰!”, “빨리해!“라고 외치는 호루라기
1. 프로세스란 무엇인가?
정의: 프로세스 = ‘실행 중인 프로그램(Program in Execution)’
프로그램은 하드디스크에 저장된 코드 파일(아직 실행 안 됨)이고, 프로세스는 그 프로그램이 실제로 메모리에 올라가서 실행되는 것입니다.
프로세스 메모리 구조(5가지 영역)
• Text(코드): 실행 코드, 함수, 명령어가 저장. 읽기 전용이라 실행 중 변경 불가(건물 설계도 보관실에 비유)
• Data(전역): 초기화된 전역·정적 변수. 프로그램 시작부터 끝까지 유지(공용 창고에 비유)
• BSS: 초기화 안 된 전역 변수. 실행 시 자동으로 0으로 채워짐(예약된 빈 창고에 비유)
• Heap(동적): malloc()으로 할당된 메모리. 위(↑) 방향으로 성장(필요할 때 임대하는 방에 비유)
• Stack(스택): 지역 변수, 함수 호출 기록. 아래(↓) 방향으로 성장(현재 사용 중인 작업실에 비유)
스택과 힙이 왜 서로 반대 방향으로 자랄까? 같은 방향이면 충돌 지점을 미리 예측하기 어렵습니다. 반대 방향으로 자라면 중간 빈 공간을 두 영역이 나눠 쓰다가, 두 영역이 만나는 순간이 진짜 메모리 부족 상황이 되기 때문입니다(설계상의 지혜).
2. 프로세스 상태(생명 주기) — 시험 핵심
5가지 상태
• 생성(Created/New): 프로세스가 막 만들어진 상태
• 준비(Ready, ps 코드 R): CPU를 받으면 바로 실행 가능
• 실행(Running, ps 코드 R): CPU를 할당받아 실제로 명령 처리 중
• 대기/블록(Blocked, ps 코드 S/D): I/O 완료 등 이벤트를 기다리는 중
• 종료(Terminated, ps 코드 Z): 실행 완료, PCB만 남은 상태(좀비 가능)
4가지 핵심 상태 전이
① 준비→실행: CPU 할당받음(디스패치)
② 실행→준비: 할당 시간(퀀텀) 만료 또는 타이머 만료
③ 실행→블록: 이벤트 대기 필요(I/O 요청 등)
④ 블록→준비: 기다리던 이벤트 완료(깨어남)
퀀텀(Quantum)이란 한 프로세스가 CPU를 독점하지 못하도록 OS가 정해둔 최대 실행 시간입니다. sleep()을 호출하면 프로세스는 스스로 CPU를 포기하고 블록 상태로 전환되고, 타이머가 울리면 준비 큐에 넣었다가 CPU가 비면 실행 상태로 전환됩니다.
일시 정지 상태(추가)
OS가 강제로 프로세스를 멈출 수 있는 상태입니다(디버깅, 보안 위협 감지 등).
• 일시 정지 준비(Suspended Ready): 준비 상태에서 일시 정지됨
• 일시 정지 블록(Suspended Blocked): 블록 상태에서 일시 정지됨
3. 프로세스 관리
OS가 프로세스에게 제공하는 서비스
create(생성)/destroy(소멸)/suspend(일시 정지)/resume(재시작)/change priority(우선순위 변경)/block(대기 상태 전환)/wake up(블록 해제)/dispatch(CPU 할당)/IPC(프로세스 간 통신)
PCB(프로세스 제어 블록) — 시험 출제 빈도 높음
PCB는 OS가 프로세스를 관리하기 위한 ‘프로세스 신분증+상태 기록부’로, Linux에서는 /proc/[PID]/status 파일로 확인할 수 있습니다.
PCB 항목: PID(프로세스 고유 번호), PPID(부모 프로세스 번호), State(현재 상태), 프로그램 카운터(다음에 실행할 명령어 주소), 스케줄링 우선순위(CPU 받는 순서), VmSize(할당된 가상 메모리 크기), 부모/자식 프로세스 정보(프로세스 계층 관계), 메모리/자원 포인터(사용 중인 자원 위치)
프로세스 테이블: 모든 PCB를 모아둔 표로, PCB에 빠르게 접근하기 위해 사용합니다.
부모/자식 프로세스
부모 프로세스는 다른 프로세스를 생성하는 프로세스(fork() 호출자)이고, 자식 프로세스는 생성된 프로세스입니다(각 자식은 부모가 정확히 하나).
fork() 반환값 3가지(시험 단골)
• -1(음수): 부모가 받음, fork() 실패, 에러 처리 필요
• 0: 자식이 받음, “나는 자식이다”, 부모 PID는 getppid()로 확인
• 양수(PID 값): 부모가 받음, “나는 부모”, 이 숫자가 자식의 PID
fork() 횟수와 프로세스 수는 총 2ⁿ개입니다(1번→2개, 2번→4개, 3번→8개, n번→2ⁿ개).
좀비 프로세스란? 자식이 종료됐는데 부모가 wait()를 호출하지 않으면 자식의 PCB가 메모리에 계속 남습니다. 이를 좀비 프로세스라고 하며, 좀비가 너무 많으면 PID 테이블이 꽉 차서 새 프로세스를 만들 수 없게 됩니다.
Copy-on-Write(CoW): fork() 직후 실제로 메모리를 복사하지 않고, 자식이 데이터를 수정하려는 순간에만 해당 페이지를 복사합니다. 덕분에 fork()가 빠르고 메모리를 절약할 수 있습니다.
문맥 교환(Context Switch)
CPU가 실행 중인 프로세스를 바꾸는 과정입니다.
① 실행 중인 프로세스 P1의 상태 → P1의 PCB에 저장
② 다음 실행할 P2의 상태를 PCB에서 불러옴
③ P2 실행 시작
문맥 교환이 일어나는 동안 CPU는 아무 유용한 작업도 못 하므로, OS는 이 시간을 최소화해야 합니다.
4. 인터럽트(Interrupts)
정의: 인터럽트는 ‘잠깐! 나 좀 봐줘!’ 하는 신호로, 소프트웨어가 하드웨어 신호에 반응할 수 있게 해주는 메커니즘입니다.
인터럽트 vs 폴링
• 폴링(Polling): CPU가 계속 “뭐 왔어?“를 반복 확인. 시스템이 복잡해질수록 오버헤드가 증가하는 단점
• 인터럽트: 이벤트 발생 시에만 CPU에게 알림. 오버헤드가 적음
인터럽트 2가지 종류
• 동기적 인터럽트(트랩, Trap): 프로세스 실행 중 오류로 발생(예: 0으로 나누기, 금지된 메모리 접근)
• 비동기 인터럽트: 현재 실행과 무관한 외부 이벤트 발생(예: 키보드 입력, 마우스 클릭, 타이머)
인터럽트 처리 과정
① 인터럽트 발생
② 현재 명령어 실행 완료 후 현재 프로세스 멈춤
③ 실행 문맥을 임시 저장(PCB에 저장)
④ 적절한 인터럽트 처리기 실행
⑤ 처리 완료 후 원래 프로세스 상태 복구
⑥ 원래 프로세스 재실행
IA-32 인터럽트 유형 3가지
• 입출력: 입출력 완료 알림(장치 상태 변경)
• 타이머: 주기적 발생, 퀀텀 만료 확인에 사용
• 프로세서 간: 멀티프로세서에서 프로세서끼리 메시지 전달
예외(Exception) 3가지
• 폴트(Fault): 0으로 나누기, 잘못된 메모리 참조, 권한 초과
• 트랩(Trap): 레지스터 오버플로우, 코드 중단점 도달
• 중단(Abort): 프로세서가 극복 불가한 오류 탐지 → 프로세스 종료
5. 프로세스 간 통신(IPC)
왜 IPC가 필요한가? fork()로 생성된 자식은 부모와 독립된 메모리 공간을 갖습니다. 전역 변수를 수정해도 상대방에게 전달되지 않기 때문에 별도의 통신 메커니즘이 필요합니다.
IPC 방식 비교
• Pipe(파이프): 단방향, 부모-자식 간, 커널 버퍼 사용
• Named Pipe(FIFO): 파일 이름으로 무관한 프로세스도 통신 가능
• Shared Memory: 가장 빠름, 직접 메모리 공유
• Message Queue: 메시지 단위 송수신, 커널 관리
• Socket: 네트워크 통신과 동일한 방식
① 신호(Signal)
프로세스에게 “이벤트 발생했어!“라고 알리는 소프트웨어 인터럽트입니다. 데이터를 보내지 않고 알림만 보냅니다.
• SIGINT(2): Ctrl+C 입력, 처리 가능
• SIGTERM(15): kill 명령 기본값, 처리 가능
• SIGKILL(9): kill -9 강제 종료, 처리 불가(커널이 강제 처리)
• SIGCHLD(17): 자식 프로세스 종료 시, 처리 가능
• SIGALRM(14): alarm() 타이머 만료, 처리 가능
• SIGUSR1/2(10/12): 사용자 정의, 처리 가능
SIGKILL(9)은 절대 처리할 수 없습니다. 커널이 강제로 처리하기 때문에 핸들러 등록 자체가 불가능합니다.
신호 처리 3가지 방법: 잡음(Catch, 신호 받으면 특정 함수 실행), 무시(Ignore, OS 기본 동작에 맡김), 마스킹(Masking, 특정 신호 완전 차단)
② 메시지 전달(Message Passing)
프로세스끼리 실제 데이터를 주고받는 방식입니다.
• 블록킹 송신: 수신자가 받을 때까지 송신자가 대기
• 넌블록킹 송신: 보내고 바로 다른 작업 가능
파이프(Pipe) 구조
pipe[0]은 읽기 전용 끝(read end), pipe[1]은 쓰기 전용 끝(write end)입니다. 파이프는 단방향이라 양방향 통신을 하려면 파이프가 2개 필요합니다. pipe()는 반드시 fork() 전에 호출해야 합니다(자식이 상속받아야 하므로).
데드락 주의: 사용하지 않는 pipe 끝을 close()하지 않으면 read()가 EOF를 못 받아 무한 대기 상태가 됩니다.
6. 유닉스(UNIX) 프로세스 사례 연구
특징: 메모리는 가상 주소 공간(virtual address space)을 제공하고, PCB는 사용자가 직접 접근 불가한 보호 영역에 저장됩니다. 자식 생성은 fork() 시스템 호출을 사용하고, 우선순위는 -20~19 정수(낮을수록 높은 우선순위)이며, IPC는 신호(signal)와 파이프(pipe)를 사용합니다.
주요 유닉스 시스템 호출
• fork: 자식 프로세스 생성(부모 자원의 사본 할당)
• exec: 파일에 있는 프로세스 명령어들과 데이터를 주소 공간에 로드
• wait: 자식 프로세스들이 종료되기까지 호출하는 프로세스가 블록
• signal: 프로세스가 특정 유형의 신호를 위한 신호 처리기를 지정
• exit: 호출하는 프로세스를 종료
• nice: 프로세스의 스케줄링 우선순위를 수정
'운영체제' 카테고리의 다른 글
| [전공 중간고사 정리] 운영체제 – 리눅스 사용자와 그룹 (0) | 2026.07.28 |
|---|---|
| [전공 중간고사 정리] 운영체제 – 리눅스 명령어(파일과 디렉터리) (0) | 2026.07.28 |
| [전공 중간고사 정리] 운영체제 – 가상머신(Virtual Machine) (0) | 2026.07.28 |
| [전공 중간고사 정리] 운영체제 – 운영체제의 이해와 기초 개념 (0) | 2026.07.28 |
| [전공 기말고사 정리] 운영체제론 – 병행실행·교착상태·스케줄링·세마포어·시스템 보안 (0) | 2026.07.28 |