우리가 사용하는 시스템 콜의 예시를 들어주세요.

개발자가 일상적으로 사용하는 거의 모든 I/O, 프로세스, 네트워크 작업은 내부적으로 시스템 콜을 통해 커널에 요청됩니다.

일상적인 작업과 시스템 콜 매핑

일상 작업시스템 콜설명
파일 열기open()파일 디스크립터 반환
파일 읽기read()버퍼에 데이터 읽기
파일 쓰기write()버퍼의 데이터 쓰기
파일 닫기close()파일 디스크립터 해제
프로세스 생성fork()현재 프로세스 복제
프로그램 실행execve()새 프로그램으로 교체
프로세스 종료exit()프로세스 종료
메모리 할당mmap() / brk()힙 메모리 확장
네트워크 연결socket() / connect()소켓 생성 및 연결
시간 조회gettimeofday()현재 시간 반환
프로세스 대기wait()자식 프로세스 종료 대기
디렉토리 조회getdents()디렉토리 내 파일 목록

1. 파일 읽기/쓰기

// Java
FileInputStream fis = new FileInputStream("data.txt");  // open()
byte[] buf = new byte[1024];
int n = fis.read(buf);         // read()
fis.close();                   // close()

FileOutputStream fos = new FileOutputStream("out.txt"); // open()
fos.write("hello".getBytes()); // write()
fos.close();                   // close()
내부 시스템 콜 흐름:
open("data.txt", O_RDONLY)  → fd = 3
read(3, buf, 1024)          → n = 읽은 바이트 수
close(3)                    → 파일 디스크립터 해제

2. 콘솔 출력

System.out.println("hello world");
내부 시스템 콜:
write(1, "hello world\n", 12)
       │
       └── fd=1 은 stdout (표준 출력)

표준 파일 디스크립터:
  0 = stdin  (표준 입력)
  1 = stdout (표준 출력)
  2 = stderr (표준 에러)

3. 프로세스 생성

// Java에서 외부 프로그램 실행
Process p = Runtime.getRuntime().exec("ls -al");
내부 시스템 콜:
fork()           → 현재 프로세스 복제 (자식 프로세스 생성)
execve("/bin/ls", ["ls", "-al"], envp)  → 자식을 ls 프로그램으로 교체
wait4()          → 부모가 자식 종료 대기

┌────────────┐   fork()   ┌────────────┐
│  부모(JVM)  │ ────────→ │  자식(JVM)  │
└────────────┘            └─────┬──────┘
       │                        │ execve()
       │ wait4()                ▼
       │                  ┌────────────┐
       │                  │  ls -al    │
       │                  └─────┬──────┘
       │                        │ exit()
       ▼                        ▼
  자식 종료 감지            프로세스 종료

4. 네트워크 통신

// Java 소켓 통신
Socket socket = new Socket("example.com", 80);
OutputStream out = socket.getOutputStream();
out.write("GET / HTTP/1.1\r\n".getBytes());
InputStream in = socket.getInputStream();
int data = in.read();
socket.close();
내부 시스템 콜 순서:
socket(AF_INET, SOCK_STREAM, 0)  → 소켓 생성 (fd = 4)
connect(4, {ip, port}, ...)       → 서버에 TCP 연결
write(4, "GET / HTTP/1.1\r\n", 16) → 요청 전송
read(4, buf, size)                → 응답 수신
close(4)                          → 소켓 닫기

5. 스레드 생성

new Thread(() -> {
    System.out.println("새 스레드");
}).start();
내부 시스템 콜:
clone(CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_THREAD, ...)
      │
      ├── CLONE_VM     : 메모리 공간 공유
      ├── CLONE_FS     : 파일 시스템 정보 공유
      ├── CLONE_FILES  : 파일 디스크립터 공유
      └── CLONE_THREAD : 같은 스레드 그룹

※ Linux에서 스레드는 clone()으로 생성
   fork()와 clone()의 차이는 공유 범위

6. 메모리 할당

byte[] arr = new byte[10 * 1024 * 1024]; // 10MB 배열
JVM이 힙 메모리 부족 시:
mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0)
  → 커널이 가상 메모리 영역 할당
  → 실제 물리 메모리는 접근 시 Page Fault로 할당

또는:
brk(new_address)
  → 힙 영역의 끝 주소를 확장

7. 시간 조회

long now = System.currentTimeMillis();
long nano = System.nanoTime();
내부 시스템 콜:
clock_gettime(CLOCK_REALTIME, &ts)   → currentTimeMillis()
clock_gettime(CLOCK_MONOTONIC, &ts)  → nanoTime()

8. Sleep

Thread.sleep(1000); // 1초 대기
내부 시스템 콜:
nanosleep({tv_sec=1, tv_nsec=0}, NULL)
  → 커널이 프로세스를 Sleep 상태로 전환
  → 타이머 인터럽트로 시간 경과 감지
  → 1초 후 프로세스를 다시 Ready 상태로 전환

9. 파일 목록 조회

File dir = new File("/home/user");
String[] files = dir.list();
내부 시스템 콜:
open("/home/user", O_RDONLY|O_DIRECTORY) → fd = 3
getdents64(3, buf, size)                 → 디렉토리 엔트리 읽기
close(3)

전체 요약

Java 코드                        시스템 콜              커널 작업
─────────────────────────────────────────────────────────────────
System.out.println()         →   write()           →   콘솔 장치 출력
new FileInputStream()        →   open()            →   파일 시스템 접근
fis.read()                   →   read()            →   디스크에서 데이터 읽기
Runtime.exec()               →   fork() + execve() →   프로세스 생성
new Socket()                 →   socket()+connect()→   네트워크 연결
new Thread().start()         →   clone()           →   스레드 생성
new byte[10MB]               →   mmap() / brk()    →   메모리 할당
System.currentTimeMillis()   →   clock_gettime()   →   시간 조회
Thread.sleep()               →   nanosleep()       →   프로세스 슬립

CSLOG에서 보기