운영 체제 시리즈
1. 운영 체제 구조 (Operating System Structures)
전체 흐름: User → OS → Hardware
사용자(User): 프로그램 실행, 파일 저장, 프린트 요청 같은 명령을 내림.
운영체제(OS): 명령을 해석해 HW가 이해할 수 있는 방식으로 전달.
하드웨어(HW): 실제 동작(예: 디스크에 파일 저장, 모니터에 그림 출력, 키보드 입력 전달)을 수행.
Interrupts (인터럽트) – OS ↔ HW의 직접 신호
하드웨어가 CPU/OS에 보내는 전기적 신호.
CPU가 계속 물어보지 않아도, “나 준비 됐어!” 하고 HW가 먼저 알려줌.
키보드를 누르면 → 키보드 컨트롤러가 “사용자가 키를 눌렀다”는
신호(인터럽트)를 CPU/OS로 보냄.
프린터 출력 완료 시 → 프린터 컨트롤러가 “출력 끝났어”라는 인터럽트를 발생시켜 OS가 다음 작업을 진행.
👉 인터럽트 덕분에 CPU는 불필요하게 계속 “입력 왔어? 끝났어?” 하고 확인(polling)하지 않아도 됩니다. → 효율성과 실시간 반응성 확보.
Device Controller (HW)
운영체제가 장치를 사용하려면 Device Controller를 거쳐야 한다.
장치 종류마다 전용 Controller가 있음 (예: 디스크 컨트롤러, 프린터 컨트롤러). Controller는 interrupt를 만들어 CPU에 알려주는 주체.
👉 USB 메모리에 있는 파일을 열 때, 디스크 컨트롤러가 데이터를 읽어와 CPU에 전달한다.
Device Driver (SW)
운영체제(OS) 안에서 Device Controller와 소통하기 위한 소프트웨어 모듈.
OS는 각 Controller마다 해당하는 Driver를 가지고 있어야 한다. 즉, Controller와 OS 사이의 통역사 역할.
👉 새로운 프린터를 연결하면, 프린터 드라이버를 설치해야만 OS가 프린터 컨트롤러와 대화할 수 있다.
I/O 요청과 Interrupt 흐름
👉 키보드를 누르면, 키보드 컨트롤러가 Interrupt를 발생 → CPU가 이를 받아 화면에 글자를 표시한다.
System Bus & Shared Memory
System Bus: CPU, 메모리, Controller 사이를 연결하는 공통 통로.
Shared Memory: CPU와 Controller가 데이터를 주고받는 공유 공간.
👉 동영상을 재생할 때, 디스크 컨트롤러가 영상 데이터를 Shared Memory에 올려두고, CPU는 이 데이터를 읽어 화면에 출력한다.
Device Controller (HW) ↔ Device Driver (SW) ↔ CPU
Controller는 장치 제어 + Interrupt 생성
Driver는 OS와 Controller의 소통 담당
CPU는 Interrupt Handling 후 원래 작업으로 복귀
OS ↔ Hardware: Interrupts
운영체제(OS)와 하드웨어(HW)는 Interrupts를 통해 상호작용한다. Device Controller는 자신이 맡은 작업이 끝났음을 CPU에게 알리기 위해 Interrupt를 발생시킨다.
Interrupt의 종류에 따라 Interrupt Vector를 참고해 알맞은 Handler가 실행된다.
I/O Request → Interrupt 흐름
CPU → I/O Device 요청
CPU가 Device에 “이 작업 해줘”라고 요청한다.
예: 프린터에게 인쇄 명령, 디스크에서 데이터 읽기 명령.
Device 작업 수행
Device Controller가 실제 장치를 제어하여 요청된 작업을 처리한다.
예: 디스크에서 데이터를 메모리로 전달, 프린터가 인쇄 실행.
작업 완료 후 Interrupt 발생
작업이 끝나면 Device Controller가 CPU에게 Interrupt Signal을 보낸다.
예: “프린트 다 끝났어!”
CPU의 Interrupt Handling
CPU는 실행 중이던 프로그램을 잠시 멈추고, Interrupt Handling 절차를 실행한다. 끝나면 다시 원래 하던 작업으로 복귀한다.
Interrupt Vector: OS가 Interrupt를 받았을 때, 어떤 Handler를 불러야 할지 알려주는 테이블. 벡터 안에는 Interrupt 번호(int)와, 그에 대응하는 Handler 함수 주소(포인터)가 저장된다.
Intel Processor Event-Vector Table: OS가 부팅될 때 메모리에 올라가며 초기화된다. 따라서 CPU는 Interrupt 번호만 보고도 즉시 올바른 Handler를 찾을 수 있다.
Interrupt 번호 0 → Divide by Zero Handler
Interrupt 번호 1 → Keyboard Input Handler
Interrupt 번호 2 → Disk I/O Handler
Implementation: Hardware
Programmable Interrupt Controller (PIC)
문제: 동시에 여러 장치에서 Interrupt가 발생할 수 있음.
해결: Intel의 PIC가 여러 Interrupt를 받아 우선순위 정리 후 CPU로 전달.
Interrupt Request Line (IRQ): PIC가 CPU에 최종적으로 신호를 보내는 선.
👉 키보드, 마우스, 디스크에서 동시에 Interrupt 발생 → PIC가 정리 → CPU에 전달. 보통 “디스크 작업 완료”가 “마우스 움직임”보다 중요하므로, 우선순위를 조정해 처리.
운영체제(OS)와 사용자 프로그램은 System Call을 통해 상호작용한다.
System Call: User program이 OS의 다양한 서비스(파일 관리, 프로세스 제어, 통신 등)를 이용할 수 있도록 하는 인터페이스.
System Call은 User Mode에서 API를 통해 호출된다.
실제 동작(파일 열기, 프로세스 생성 등)을 수행할 때는 Kernel Mode로 전환된다.
👉 예시:
printf() → 라이브러리 함수 (User Mode)
내부적으로 write() System Call을 호출 → Kernel Mode에서 실제 출력 수행
대표적인 API 예시:
Win32 API (Windows)
POSIX API (Unix/Linux)
JVM API (Java 환경)
모든 System Call에는 고유 번호(Number)가 할당되어 있음.
호출 시 → OS의 System Call Table에서 번호를 보고 해당 함수로 연결.
호출자는 내부 구현 방식을 몰라도 됨 (추상화).
System Call은 작업에 따라 다양한 데이터를 필요로 한다.
하지만 User Mode에서 Kernel Mode로 전달할 때 제약이 있어, Stack을 직접 공유할 수 없음.
전달 방식:
Register 방식
CPU Register에 parameter 저장
단점: 전달할 수 있는 인자의 수가 한정적
👉 예: read(fd, buffer, count) → fd, buffer 주소, count를 register에 전달
Block 방식
메모리에 parameter를 저장한 뒤, 해당 메모리 주소값을 Kernel에 전달
많은 데이터 전달 가능
👉 예: 파일 입출력 시 버퍼 주소 전달
Stack 방식
호출 시 User Stack에 parameter를 Push
Kernel이 이를 Pop하여 사용
구현 방식: register에 Stack 시작 주소를 전달
Process Control: fork(), exit(), wait()
File Management: open(), read(), write(), close()
Device Management: ioctl(), read(), write()
Information Maintenance: getpid(), alarm(), sleep()
Communication: pipe(), shm_open(), mmap()
Protection: chmod(), umask()
👉 예시 흐름:
printf("Hello") → 라이브러리 함수 호출 (User Mode) → 내부적으로 write() System Call 실행 → Kernel이 모니터에 실제 출력
디바이스 컨트롤러 - 하드웨어에 속함