1급 시험은 명령어 암기가 아니라 "왜 이 명령어가 이렇게 동작하는가"를 커널 수준에서 묻는다. 그 출발점이 운영체제의 정의다.
정의: 하드웨어 자원을 관리하고, 응용 프로그램에게 그 자원을 추상화하여 제공하는 소프트웨어.
자원 관리(resource management): 자원은 한정돼 있다. CPU는 코어 단위로 한 번에 하나의 명령만, 메모리 용량도 정해져 있고, 디스크 I/O 속도에도 한계가 있다. 수백 개 프로그램이 마구잡이로 요구하면 시스템이 마비되므로, 운영체제가 시간적·공간적으로 나누어 공평하고 효율적으로 배분한다.
추상화(abstraction): 응용 프로그래머는 SSD가 SATA인지 NVMe인지, RAM이 DDR4인지 DDR5인지 알 필요가 없다. open()·read()·write() 표준 인터페이스만 호출하면 운영체제가 실제 하드웨어를 다룬다.
자원
관리 주체(커널 서브시스템)
핵심 기능
CPU
프로세스 스케줄러
어느 프로세스를 언제 얼마나 실행할지 결정
메모리
메모리 관리자(MMU 활용)
가상 메모리, 페이징, 스왑
저장장치
파일시스템 / 블록 I/O 계층
파일·디렉터리 추상화, 디스크 스케줄링
입출력 장치
디바이스 드라이버
키보드·네트워크·디스크 등 하드웨어 제어
네트워크
네트워크 스택(TCP/IP)
패킷 송수신, 소켓 인터페이스
💡 개념: 운영체제의 4대 핵심 기능은 프로세스 관리, 메모리 관리, 파일 관리, 장치(I/O) 관리다. 여기에 사용자 인터페이스(셸/GUI)와 보안·권한 관리를 더해 6대 기능으로 보기도 한다. 1급 시험에서는 각 기능을 담당하는 커널 서브시스템과 묶어서 묻는 경우가 많다.
커널(kernel)은 하드웨어에 가장 가까이 있으면서 모든 자원에 대한 최종 권한을 갖는 핵심 코드다.
모든 프로그램이 하드웨어를 직접 건드리면 악성·버그 프로그램 하나가 디스크를 지우거나 남의 메모리를 망가뜨릴 수 있다 → 현대 CPU는 특권 수준(privilege level)을 하드웨어 차원에서 제공한다.
x86에는 Ring 0~Ring 3의 보호 링이 있고, 리눅스는 그중 두 개만 사용한다.
모드
링
권한
실행 주체
커널 모드(특권 모드)
Ring 0
모든 CPU 명령·메모리 영역 접근 가능
커널 코드
사용자 모드(비특권 모드)
Ring 3
제한된 명령만 실행 가능
일반 응용 프로그램
사용자 모드 프로그램이 디스크에 쓰거나 네트워크로 보내려면 커널에게 "대신 해달라"고 요청해야 한다 → 이것이 시스템 콜(system call)이다.
# strace로 프로그램이 호출하는 시스템 콜을 직접 관찰해보자strace -c ls /tmp# write, read, openat, close, mmap 등 시스템 콜 통계가 출력된다
ls 같은 단순한 명령조차 수십 개의 시스템 콜(openat, read, write, close, stat 등)을 호출한다.
사용자 모드 → 커널 모드로 전환되는 이 순간을 모드 전환(mode switch)(컨텍스트 전환의 일종)이라 하며, 약간의 오버헤드가 발생한다.
시스템 콜은 단순한 함수 호출이 아니다. CPU가 특권 수준을 Ring 3에서 Ring 0으로 올리는 하드웨어 이벤트다. 과거에는 int 0x80 소프트웨어 인터럽트를 사용했지만, 현대 x86-64 리눅스는 더 빠른 syscall 명령어를 사용한다. 이 전환 비용 때문에 고성능 프로그램은 시스템 콜 횟수를 줄이려고 버퍼링을 활용한다.
커널은 최소한(IPC, 기본 스케줄링, 메모리 관리)만. 파일시스템·드라이버는 사용자 공간의 별도 서비스
통신 방식
함수 호출
서비스 간 메시지 전달(IPC)
장점
빠르다
안정성·모듈성이 높다
단점
한 부분의 버그가 전체 커널을 죽임, 코드가 거대해짐
IPC 오버헤드로 느릴 수 있음
대표 예
리눅스
미닉스(MINIX), GNU Hurd
리눅스는 모놀리식이지만 적재 가능한 커널 모듈(LKM, Loadable Kernel Module)을 지원해 마이크로커널의 장점인 모듈성을 일부 흡수했다.
덕분에 드라이버를 커널 재컴파일 없이 동적으로 넣고 뺄 수 있다.
lsmod # 현재 적재된 커널 모듈 목록modinfo e1000 # 특정 모듈의 정보 확인sudo modprobe vfat # 모듈 적재(의존성 자동 해결)sudo rmmod vfat # 모듈 제거uname -r # 실행 중인 커널 버전 확인
1992년, 미닉스의 저자 앤드루 타넨바움 교수와 리누스 토르발스 사이에 "모놀리식 커널은 구식이다 vs 마이크로커널은 너무 느리다"를 둘러싼 유명한 논쟁(Tanenbaum–Torvalds debate)이 Usenet에서 벌어졌다. 타넨바움은 "리눅스는 구식 설계"라고 비판했지만, 결과적으로 모놀리식 리눅스가 세상을 지배했다. 실용성이 학문적 우아함을 이긴 사례로 자주 인용된다.
셸(shell)은 사용자가 커널과 대화하는 통역사이자 명령어 해석기(command interpreter)다.
ls -l을 입력하면 셸이 해석 → 적절한 프로그램을 찾아 실행 → 결과를 사용자에게 보여준다.
이름의 유래: 커널을 "껍질(shell)"처럼 감싸고 있다는 데서 왔다.
셸
개발자/유래
특징
sh (Bourne Shell)
Stephen Bourne (1977)
최초의 유닉스 표준 셸, 스크립트의 원형
csh (C Shell)
Bill Joy
C 언어 문법 차용, 히스토리·별칭 도입
ksh (Korn Shell)
David Korn
sh 호환 + csh 기능 통합
bash (Bourne Again Shell)
Brian Fox (GNU)
sh의 확장판, 리눅스 기본 셸
zsh
Paul Falstad
bash 호환 + 강력한 자동완성
tcsh
csh 확장
csh + 명령행 편집
리눅스의 기본 셸은 거의 항상 bash. "Bourne Again Shell"은 원조 Bourne Shell을 "다시 태어나게" 했다는 GNU 특유의 말장난이다.
echo $SHELL # 현재 로그인 셸 확인cat /etc/shells # 시스템에 등록된 사용 가능한 셸 목록chsh -s /bin/zsh # 로그인 셸을 zsh로 변경 (/etc/passwd 갱신)echo $0 # 현재 실행 중인 셸 이름
사용자별 기본 셸은 /etc/passwd의 마지막 필드에 기록된다.
예: user:x:1000:1000:User:/home/user:/bin/bash → 맨 끝 /bin/bash가 그 사용자의 로그인 셸.
⚠️ 함정: 시험에서 "기본 셸을 변경하는 명령"으로 chsh를 묻는데, 이때 변경된 셸은 /etc/shells에 등록된 셸이어야 한다. 또한 chsh는 즉시 적용되지 않고 다음 로그인부터 반영된다. 현재 세션에서 즉시 다른 셸을 쓰려면 그냥 셸 이름(zsh)을 입력해 하위 셸을 실행하면 된다.
사용자가 ls를 입력하면 셸은 다음 단계를 거친다. 이 과정이 운영체제의 프로세스 생성 메커니즘을 그대로 보여준다.
파싱: 입력 문자열을 명령어와 인자로 분해하고, 와일드카드(*)·변수($HOME)·따옴표를 확장한다.
fork(): 자기 자신을 복제해 자식 프로세스를 만든다. 이 시점에 부모(셸)와 자식은 동일한 코드·데이터를 가진다.
exec(): 자식 프로세스가 execve() 시스템 콜로 자신의 메모리 이미지를 ls 프로그램으로 교체한다.
wait(): 부모(셸)는 자식이 끝날 때까지 기다렸다가, 자식의 종료 상태를 회수한다.
fork-exec-wait 모델은 유닉스의 가장 우아한 설계 중 하나다 — "복제 후 교체"라는 두 단계로 모든 프로그램 실행이 이루어진다.
명령어 뒤에 &를 붙이면(sleep 100 &) 셸이 wait()를 하지 않고 즉시 프롬프트를 돌려준다. 이것이 백그라운드 실행이다. 반대로 wait를 하는 동안 부모가 죽으면 자식은 고아 프로세스(orphan)가 되어 init(PID 1)에게 입양된다. 자식이 죽었는데 부모가 종료 상태를 회수하지 않으면 좀비 프로세스(zombie)가 된다.
1969년 미국 벨 연구소(Bell Labs)에서 켄 톰슨(Ken Thompson)과 데니스 리치(Dennis Ritchie)가 PDP-7 미니컴퓨터에서 유닉스를 만들었다. 처음에는 어셈블리로 작성.
1973년 데니스 리치가 만든 C 언어로 유닉스를 다시 작성 → 고급 언어로 작성하니 다른 하드웨어로 이식(porting)이 쉬워졌고, 유닉스가 빠르게 여러 기종으로 퍼졌다.
유닉스가 후대에 남긴 가장 큰 유산은 코드가 아니라 철학이다.
"하나의 프로그램은 하나의 일만 잘하라" — 작은 도구들을 조합해 큰 일을 한다.
"모든 것은 파일이다(Everything is a file)" — 장치, 프로세스 정보, 네트워크 소켓까지 파일처럼 다룬다.
"파이프로 프로그램을 연결하라" — 한 프로그램의 출력을 다른 프로그램의 입력으로 연결한다.
# 작은 도구들을 파이프(|)로 연결해 복잡한 작업을 수행cat /etc/passwd | grep "/bin/bash" | wc -l# passwd 출력 → bash 셸 사용자만 필터 → 줄 수 세기
각 도구(cat, grep, wc)는 한 가지 일만 하지만, 파이프로 엮으면 "bash 셸을 쓰는 사용자 수 세기"라는 새 작업이 만들어진다. 이것이 유닉스 철학의 정수다.
유닉스(UNIX)라는 이름은 그 전신인 MULTICS(Multiplexed Information and Computing Service)를 비꼰 말장난이다. MULTICS가 너무 복잡하고 거대했던 데 대한 반작용으로, 단순함을 추구한다는 의미에서 "UNICS(Uniplexed)"라 불렀고 이것이 UNIX가 되었다. 단순함을 향한 의지가 이름에 새겨진 것이다.
1983년: 리처드 스톨먼(Richard Stallman)이 GNU 프로젝트를 시작 — 자유로운 유닉스 호환 운영체제를 목표로.
GNU는 컴파일러(gcc), 셸(bash), 핵심 유틸리티(coreutils) 등 거의 모든 부품을 완성했지만, 심장인 커널(GNU Hurd)은 마이크로커널 설계의 복잡함 때문에 완성되지 못했다.
1991년: 핀란드 헬싱키 대학의 21세 학생 리누스 토르발스(Linus Torvalds)가 학습용 운영체제 미닉스에 만족하지 못하고 자신만의 커널을 취미로 만들기 시작. 8월 25일 comp.os.minix 뉴스그룹에 올린 글은 전설이 되었다.
"Hello everybody out there ... I'm doing a (free) operating system (just a hobby, won't be big and professional like gnu) ..."
"거대하거나 전문적이지 않을 것"이라던 취미 프로젝트가 세상에서 가장 널리 쓰이는 운영체제 커널이 되었다.
리누스의 커널 + GNU의 도구들 = GNU/Linux. 스톨먼이 "리눅스"가 아니라 "GNU/Linux"라 불러야 한다고 주장하는 이유다 — 커널만 리누스의 것이고 나머지 시스템 도구 대부분은 GNU의 산물이기 때문.
엄밀히 말하면 "리눅스"는 커널만을 가리킨다. 우리가 설치해서 쓰는 우분투·CentOS 같은 것은 리눅스 커널 + GNU 도구 + 패키지 관리자 + 응용 프로그램을 묶은 배포판(distribution)이다. 시험에서 "리눅스는 ( )이다"라는 빈칸에는 "커널"이 정답인 경우가 많다.
라이선스 전환도 중요한 시험 사실이다: 1991년 처음에는 GPL이 아닌 자체 라이선스로 배포 → 1992년 버전 0.99부터 GPL(GNU General Public License)로 전환.
이 GPL 채택이 전 세계 개발자의 참여를 폭발적으로 끌어냈고 오늘날의 리눅스를 만들었다. 라이선스 상세는 Day 2에서 다룬다.
다음 시간에는 리눅스를 자유롭게 만든 라이선스와, 그 결과 갈라진 배포판 계열들을 살펴본다.