
현대의 많은 시스템은 CLI와 GUI를 모두 포함한다.
운영체제인터페이스 특징Microsoft WindowsGUI 중심 + CLI "command" 셸 (cmd, PowerShell)SolarisCLI 중심 + 선택적 GUI (Java Desktop, KDE)
핵심 포인트: CLI는 텍스트 명령 기반으로 강력하고 자동화에 유리하며, GUI는 직관적이고 사용이 쉽다. 현대 OS는 대부분 두 가지를 모두 제공한다.

ex : 프로그래머는 printf()같은 API 함수를 호출하고, 이 API가 내부적으로 write() 같은 시스템 콜을 호출한다. 프로그래머가 직접 시스템 콜 번호를 지정할 필요가 없다.
API대상 시스템 Win32 API, WindowsPOSIX API POSIX 기반 시스템 (UNIX, Linux, Mac OS X 거의 모든 버전)Java API Java 가상 머신 (JVM)

API가 복잡한 시스템 콜의 세부 사항을 감추어 프로그래밍을 쉽게 한다.
그림은 API의 호환성(portability)을 보여준다:
핵심 포인트: API를 사용하면 OS가 달라져도 같은 API를 지원하는 한 프로그램을 재컴파일 없이 또는 최소한의 수정으로 이식할 수 있다. 이것이 API의 가장 큰 장점이다.

핵심 포인트: 사용자 프로그램은 이름(open)으로 API를 호출하지만, 커널 내부에서는 번호(숫자)로 해당 시스템 콜 루틴을 찾는다. 사용자는 커널 내부의 세부 사항을 알 필요가 없다.

C 프로그램이 printf() 라이브러리 호출을 하면, 이 함수가 내부적으로 write() 시스템 콜을 호출한다.
[C 프로그램]
#include <stdio.h>
int main() {
printf("Greetings"); ← ① printf() 호출 (라이브러리 함수)
return 0;
}
│
▼
[Standard C library] ← ② 표준 C 라이브러리 (사용자 모드)
│
▼
[System call interface] ← ③ 시스템 콜 인터페이스 (경계)
│
▼
[write() system call] ← ④ write() 시스템 콜 실행 (커널 모드)
핵심 포인트: 프로그래머가 사용하는 printf()는 사용자 공간의 라이브러리 함수이고, 실제 OS 서비스를 사용하는 것은 그 내부에서 호출되는 write() 시스템 콜이다. 이 계층 구조가 프로그래밍을 쉽게 만든다.

핵심 포인트: 시스템 콜은 번호로 관리된다. 커널은 배열(sys_call_table)에서 번호를 인덱스로 사용하여 해당 커널 루틴의 주소를 찾아 실행한다.

// user 코드
syscall(5, "file.txt", 0); // 5가 뭐지...?
syscall(2); // 2는 또 뭐고?
syscall(1, 0); // ???
// user 코드
syscall(__NR_open, "file.txt", 0); // 아, open이구나
syscall(__NR_fork); // fork
syscall(__NR_exit, 0); // exit

방법 1: 레지스터 (Registers)
방법 2: 블록/테이블 (Block or Table)
방법 3: 스택 (Stack)

블록 방식과 스택 방식은 커널에 전달할 매개변수의 수나 길이를 제한하지 않는다.
레지스터 방식은 레지스터 수에 제한이 있지만, 블록/스택 방식은 메모리를 사용하므로 제한이 없다.
핵심 포인트: Linux는 블록(테이블) 방식, Windows는 스택 방식을 주로 사용한다. 두 방식 모두 매개변수 수에 제한이 없다는 장점이 있다.


read() 시스템 콜의 전체 흐름
이 그림은 read() 시스템 콜이 사용자 공간(User space)에서 커널 공간(Kernel space)까지 어떻게 흘러가는지 보여준다. 중앙의 빨간 선이 사용자 공간과 커널 공간의 경계이다.
| 단계 | 위치 | 동작 | 한국어 설명 |
|---|---|---|---|
| 1 | main() | push arguments, _libc_read() | 인자를 스택에 넣고 C 라이브러리의 read 함수 호출 |
| 2 | __libc_read() | load args to regs, EAX = __NR_read | 인자를 레지스터에 로드, EAX에 시스템 콜 번호(3) 저장 |
| 3 | __libc_read() | int 0x80 | 소프트웨어 인터럽트(TRAP) 발생 → 커널 모드 진입 |
| 4 | system_call() | SAVE_ALL, check EAX, syscall_tabEAX | 모든 레지스터 저장, EAX 범위 확인, 시스템 콜 테이블에서 해당 함수 호출 |
| 5 | sys_read() | fget(fd), check file ops/locks | 파일 디스크립터로 파일 객체를 가져오고, 파일 연산과 락을 확인 |
| 6 | device code | retrieve data, copy data | 실제 장치에서 데이터를 가져와 사용자 버퍼에 복사 |
| 7 | system_call() | handle signals, RESTORE_ALL, iret | 시그널 처리, 레지스터 복원, 인터럽트 리턴으로 사용자 모드 복귀 |
| 8 | __libc_read() | check error, return | 에러 확인 후 결과 반환 |

핵심 포인트: Linux에서 시스템 콜 호출의 핵심 흐름은 EAX에 번호 저장 → int 0x80으로 TRAP 발생 → 커널 진입 → sys_call_table에서 루틴 찾아 실행 → iret(interrupt return)으로 사용자 모드 복귀이다.



| 영어 | 한국어 | 설명 및 예시 |
|---|---|---|
| File management | 파일 관리 | 파일과 디렉토리의 생성, 삭제, 복사, 이름 변경, 출력, 덤프, 목록 조회 등 |
| Status information | 상태 정보 | 날짜, 시간, 사용 가능한 메모리, 디스크 공간, 사용자 수 등을 시스템에 질의. 성능, 로깅, 디버깅 정보도 제공. 일부 시스템은 **레지스트리(registry)**를 구현하여 설정 정보를 저장/조회 |
| File traversal | 파일 탐색 | 파일 내용을 검색하거나 텍스트 변환을 수행하는 특수 명령어 (예: grep, sed, awk) |
| Programming-language support | 프로그래밍 언어 지원 | 컴파일러(compilers), 어셈블러(assemblers), 디버거(debuggers), 인터프리터(interpreters) |
| Program loading and execution | 프로그램 로딩 및 실행 | 절대 로더, 재배치 로더, 링키지 에디터, 오버레이 로더, 고수준/기계어 디버깅 시스템 |
| Communications | 통신 | 프로세스, 사용자, 컴퓨터 시스템 간 가상 연결 메커니즘 제공. 예: 웹 페이지 브라우징, 이메일, 원격 로그인, 파일 전송 |
핵심 포인트: 시스템 프로그램은 OS와 함께 제공되어 사용자가 파일 관리, 상태 조회, 프로그래밍, 통신 등의 작업을 쉽게 할 수 있도록 돕는다. 시스템 콜 위에 구축된 유틸리티 프로그램이다.