CertNote/ 출퇴근 학습 노트
로드맵
KOEN
리눅스마스터 2급 · 2급리눅스마스터 2급
리눅스마스터 1급 · 1급리눅스마스터 1급
  • Week 1
    • 1.운영체제와 리눅스: 커널이 하는 일
    • 2.자유 소프트웨어와 배포판: 라이선스가 만든 생태계
    • 3.설치와 부팅: 전원을 켜는 순간부터
    • 4.파일시스템 구조와 파일의 종류: 모든 것은 파일이다
    • 5.Week 1 종합 복습: 개념을 꿰뚫는 시간
  • Week 2
  • Week 3
  • Week 4
  • Week 5
  • Week 6
    • 1.프로세스 관리: PID부터 시그널·우선순위까지
    • 2.데몬과 프로세스 생애: fork·exec부터 좀비·고아까지
    • 3.시스템 초기화: init·런레벨에서 systemd·target까지
    • 4.작업 예약: cron의 5필드부터 at·batch까지
    • 5.Week 6 종합 복습: 프로세스·초기화·예약을 한 장으로 꿰기
  • Week 7
  • Week 8
  • Week 9
  • Week 10
  • Week 11
  • Week 12
  • Week 13
  • Week 14
합격 후기

© CertNote · 주간랩스

  • 소개
  • 수정 기록
  • 문의
  • 이용약관
  • 개인정보처리방침
← 리눅스마스터 1급/Week 6/Day 2

기준: 리눅스마스터 1급 출제 기준·오류 제보

리눅스마스터 1급· AssociateWeek 6 · Day 2읽기 약 12분
핵심 정리
  • 데몬은 터미널에 묶이지 않고 백그라운드에서 서비스를 제공하는 프로세스. 이름이 보통 'd'로 끝나고, 항상 떠 있는 standalone과 요청 시 띄우는 super-daemon(xinetd) 두 방식이 있다.
  • 작업 제어는 &(백그라운드) · Ctrl+Z(정지) · jobs · bg · fg · nohup(로그아웃 후 생존).
  • 프로세스 탄생은 fork(복제, 새 PID) → exec(교체, PID 유지) 두 단계. 그 사이에 리다이렉션·파이프를 끼워 넣을 수 있는 것이 유닉스 설계의 핵심이다.
  • 좀비 = 죽은 자식 + wait 안 하는 부모. Z/defunct 상태로 PID 슬롯을 점유하며, kill -9가 안 통하고 부모를 종료·재시작해야 사라진다.
  • 고아 = 산 자식 + 죽은 부모. 즉시 PID 1번에 입양되어 PPID가 1로 바뀌고 정상 회수되므로 무해하다.

Day 2 - 데몬과 프로세스 생애: fork·exec부터 좀비·고아까지

데몬이란 무엇인가

  • 데몬(daemon) : 사용자와 직접 대화하지 않고 백그라운드에서 특정 서비스를 제공하는 프로세스.
  • 대표 예: 웹 서버(httpd), SSH 접속(sshd), 예약 작업(crond), 메일(postfix).
  • 이름 끝에 'd'가 붙는 관례가 있어 sshd·httpd·crond처럼 d로 끝나면 십중팔구 데몬이다.
  • 데몬의 특징은 다음과 같다.
특징설명
제어 터미널 없음특정 터미널에 묶이지 않아 로그아웃해도 계속 동작
백그라운드 상주부팅 시 시작되어 시스템 종료까지 메모리에 상주
부모는 보통 1번systemd/init이 직접 관리하거나 입양
이름에 'd'sshd, httpd, crond, rsyslogd 등
  • 데몬이 서비스를 제공하는 방식은 크게 두 가지다.
방식동작예
Standalone(독립)데몬이 항상 떠 있다가 요청을 직접 처리httpd, sshd
Super-daemon(슈퍼)xinetd/inetd가 대기하다 요청 시 자식 데몬 실행옛 telnet, ftp

standalone 방식은 응답이 빠르지만 항상 메모리를 차지한다. super-daemon(xinetd) 방식은 평소 메모리를 아끼지만 요청마다 새로 띄우느라 응답이 느리다. 자주 쓰는 서비스는 standalone, 가끔 쓰는 서비스는 super-daemon이 유리하다는 트레이드오프가 시험에 나온다.

'daemon'은 그리스 신화의 "보이지 않게 일을 돕는 정령"에서 따왔다. MIT의 Project MAC에서 백그라운드 보조 프로세스를 이렇게 부른 것이 시초다. 악마(demon)와 철자가 다르며, 사용자 눈에 안 보이게 묵묵히 일한다는 뜻을 담았다.

포그라운드와 백그라운드

  • 포그라운드(foreground) : 명령을 그냥 실행한 상태. 셸이 명령이 끝날 때까지 기다리므로 다른 명령을 칠 수 없다.
  • 백그라운드(background) : 명령 끝에 &를 붙인 상태. 셸이 바로 프롬프트를 돌려주므로 계속 작업할 수 있다.
sleep 100          # 포그라운드: 100초 동안 프롬프트가 멈춤
sleep 100 &        # 백그라운드: 즉시 프롬프트 복귀, [1] 12345 출력
  • 실행 중인 작업(job)을 포그라운드와 백그라운드 사이에서 옮기는 명령들이 핵심이다.
명령/키동작
& (명령 뒤)처음부터 백그라운드 실행
Ctrl+Z포그라운드 작업을 일시 정지(Stopped)
jobs현재 셸의 작업 목록과 작업 번호 확인
bg %1정지된 1번 작업을 백그라운드에서 재개
fg %11번 작업을 포그라운드로 가져옴
nohup ... &로그아웃 후에도 살아남게 실행
sleep 200            # 실행 중...
# (Ctrl+Z 입력) → [1]+ Stopped  sleep 200
jobs                 # [1]+ Stopped sleep 200
bg %1                # 백그라운드로 재개 → [1]+ sleep 200 &
fg %1                # 다시 포그라운드로
nohup ./long.sh &    # 로그아웃해도 계속, 출력은 nohup.out에 저장

⚠️ 함정: Ctrl+Z는 종료가 아니라 일시 정지(SIGSTOP, 상태 T)다. 종료는 Ctrl+C(SIGINT)다. 정지된 작업은 bg/fg로 되살려야 하며, 그냥 두고 셸을 닫으면 사라질 수 있다. 또한 &만으로는 셸 종료 시 SIGHUP을 받아 죽을 수 있으므로, 로그아웃 후에도 살리려면 nohup을 함께 써야 한다.

직접 쳐보기: sleep 300을 실행하고 Ctrl+Z로 멈춘 뒤 jobs로 상태가 Stopped인지 본다. bg %1로 재개하면 Running으로 바뀐다. fg %1로 다시 가져와 Ctrl+C로 종료하면 완전히 사라진다. 작업 제어의 한 사이클이다.

fork와 exec — 프로세스 탄생의 원리

  • 리눅스에서 새 프로그램을 실행하는 과정은 fork → exec 두 단계다. 유닉스 설계의 핵심 모델.
  1. fork(): 부모가 자기 자신을 거의 똑같이 복제한다. 새 PID의 자식이 생기고, 자식의 PPID는 부모의 PID가 된다. 복제 직후에는 부모와 자식이 같은 코드를 실행한다.
  2. exec(): 복제된 자식이 자신의 메모리 내용을 다른 프로그램으로 통째로 교체한다. PID는 유지되지만 실행되는 프로그램은 완전히 바뀐다.
[셸 프로세스] --fork()--> [자식(셸 복제본)] --exec("/bin/ls")--> [ls 프로세스]
   PID 1000                  PID 1500              PID 1500(유지)
                             PPID 1000             PPID 1000
  • 예: 셸에서 ls를 치면 셸이 자신을 fork해 자식을 만들고, 그 자식이 exec로 ls가 된 뒤 실행을 마치면 종료된다.
  • 부모 셸은 wait()로 자식이 끝나길 기다렸다가 프롬프트를 돌려준다.
시스템 호출역할PID 변화
fork()프로세스 복제(자식 생성)새 PID 생성
exec()현재 프로세스를 다른 프로그램으로 교체PID 유지
wait()부모가 자식 종료를 기다리고 회수—
exit()프로세스 종료(종료 코드 반환)—

exec는 새 프로세스를 만들지 않는다. 현재 프로세스의 껍데기(PID)는 그대로 두고 알맹이(실행 코드)만 갈아끼운다. 그래서 exec ls를 셸에서 직접 치면 셸 자신이 ls로 변신해 버려, ls가 끝나면 셸도 함께 종료된다. fork(복제)와 exec(교체)를 분리한 것이 유닉스의 우아함이다.

fork-exec 분리 덕분에 셸은 자식을 fork한 직후, exec 전에 입출력 리다이렉션(>, <)이나 파이프(|)를 설정할 수 있다. 만약 "복제와 교체"가 한 번에 묶여 있었다면 이런 유연한 입출력 재배치가 불가능했을 것이다. 이 설계가 유닉스 파이프라인 철학의 토대다.

좀비 프로세스 — 회수되지 않은 시체

  • 자식이 exit()로 종료하면 커널은 그 종료 코드를 부모가 가져갈 수 있도록 잠시 보관한다.
  • 부모가 wait()를 호출해 종료 코드를 거두면 자식의 흔적이 완전히 사라진다.
  • 부모가 wait()를 하지 않으면 자식은 이미 죽었는데 종료 코드만 남아 프로세스 테이블에 흔적이 남는다 → 이것이 좀비(zombie, defunct) 프로세스.
항목좀비 프로세스
상태(STAT)Z (또는 <defunct> 표시)
메모리거의 사용 안 함(껍데기만)
원인부모가 wait()로 종료 코드를 회수하지 않음
위험PID 자리를 차지 — 다량 누적 시 PID 고갈
해결부모 프로세스를 종료/재시작 → 좀비가 1번에 입양되어 정리
ps aux | grep -w Z         # 좀비 상태 프로세스 찾기
ps -ef | grep defunct      # defunct로 표시된 좀비 확인
  • 좀비는 이미 죽은 상태라 kill -9로 죽일 수 없다(이미 죽어 있으니까).
  • 없애려면 그 부모 프로세스를 종료하거나 재시작한다.
  • 부모가 사라지면 좀비는 PID 1번(systemd/init)에 입양되고, 1번이 즉시 wait()로 회수해 정리한다.

⚠️ 함정: 좀비 프로세스는 메모리를 거의 안 쓰지만 PID 슬롯을 점유한다. 잘못 만든 프로그램이 좀비를 계속 양산하면 PID가 고갈되어 새 프로세스를 못 만드는 사태가 온다. 좀비를 kill -9 좀비PID로 죽이려는 시도는 무의미하다 — 표적은 부모다.

고아 프로세스 — 부모를 잃은 자식

  • 고아(orphan) 프로세스는 좀비와 정반대 상황이다. 자식이 아직 살아 일하는데 부모가 먼저 종료해 버린 경우.
  • 뒤집어 외우면 안 헷갈린다: 좀비는 "자식은 죽었는데 부모가 안 거둠", 고아는 "부모가 죽었는데 자식은 살아 있음".
  • 부모를 잃은 고아는 즉시 PID 1번(systemd/init)에 입양되고 PPID가 1번으로 바뀐다.
  • 1번이 부모 역할을 대신하므로, 고아가 나중에 종료하면 wait()로 깔끔히 회수된다 → 시스템에 해롭지 않다.
구분좀비(Zombie)고아(Orphan)
자식 상태죽음(종료됨)살아 있음(실행 중)
부모 상태살아 있으나 wait 안 함먼저 종료됨
PPID원래 부모1번으로 변경(입양)
위험성PID 점유, 누적 시 문제무해(1번이 정상 회수)
해결부모 종료/재시작자동 입양으로 해결

핵심 대비표 한 줄 — 좀비는 죽은 자식 + 안 거두는 부모(위험), 고아는 산 자식 + 죽은 부모(무해, 1번이 입양). 이 둘을 뒤바꾼 보기가 함정으로 쓰인다. "Z 상태 = 좀비, defunct 표시"도 함께 외운다.

직접 쳐보기: ps -ef를 실행해 PPID(세 번째 컬럼)가 1인 프로세스들을 살펴본다. 부팅 시 시작된 데몬들과 입양된 고아들이 모두 1번을 부모로 가진다. 1번이 어떻게 모든 미아의 보호자 역할을 하는지 실제 목록으로 확인할 수 있다.

고아 입양 메커니즘이 없다면, 백그라운드로 실행한 nohup ./job & 같은 프로세스는 셸(부모)이 종료되는 순간 회수자 없는 상태가 되어 결국 좀비가 될 것이다. 1번 프로세스의 입양 덕분에 우리는 로그아웃 후에도 백그라운드 작업을 안심하고 돌릴 수 있다.

📖 용어

  • 데몬(daemon) : 터미널에 묶이지 않고 백그라운드에 상주하며 서비스를 제공하는 프로세스. 이름이 보통 'd'로 끝난다.
  • standalone 방식 : 데몬이 항상 떠 있다가 요청을 직접 처리. 빠르지만 늘 메모리를 먹는다(httpd, sshd).
  • super-daemon(xinetd) : 평소엔 대기하다 요청이 오면 자식 데몬을 띄우는 방식. 메모리는 아끼지만 응답이 느리다.
  • 포그라운드 / 백그라운드 : 셸이 끝날 때까지 기다리는 실행 / &를 붙여 뒤로 보내고 프롬프트를 돌려받는 실행.
  • job(작업) : 셸이 관리하는 실행 단위. jobs로 목록을, %1 같은 작업 번호로 지정한다.
  • nohup : "no hang up". SIGHUP을 무시하게 만들어 로그아웃 후에도 프로세스를 살려두는 명령. 출력은 nohup.out으로 간다.
  • fork() : 자기 자신을 복제해 새 PID의 자식을 만드는 시스템 콜.
  • exec() : 새 프로세스를 만들지 않고, 현재 프로세스의 실행 코드만 다른 프로그램으로 갈아끼우는 시스템 콜. PID는 그대로다.
  • wait() : 부모가 자식의 종료 코드를 거둬 흔적을 지우는 시스템 콜. 이걸 안 하면 좀비가 생긴다.
  • 좀비(defunct) : 자식은 죽었는데 부모가 회수하지 않아 Z 상태로 PID 슬롯만 차지하고 있는 프로세스.
  • 고아(orphan) : 부모가 먼저 죽어 PID 1번에 입양된, 아직 살아 있는 자식 프로세스.

📝 연습 문제

선택지를 클릭하면 정답·해설이 펼쳐집니다.

문제 1

데몬(daemon) 프로세스에 대한 설명으로 옳지 않은 것은?

문제 2

포그라운드에서 실행 중인 작업에 Ctrl+Z를 입력했을 때의 결과로 옳은 것은?

문제 3

새 프로그램을 실행하는 fork-exec 모델에 대한 설명으로 옳은 것은?

문제 4

좀비(zombie) 프로세스가 발생하는 원인으로 가장 정확한 것은?

문제 5

고아(orphan) 프로세스에 대한 설명으로 옳은 것은?

문제 6

좀비 프로세스를 제거하기 위한 가장 올바른 방법은?

문제 7

로그아웃한 뒤에도 백그라운드 작업이 SIGHUP에 죽지 않고 계속 실행되도록 하려는 명령은?

이전프로세스 관리: PID부터 시그널·우선순위까지Week 6 · Day 1다음 시스템 초기화: init·런레벨에서 systemd·target까지Week 6 · Day 3

참고 공식 자료

  • 리눅스마스터 1급 공식 출제 기준(새 탭에서 열림)

이 페이지

  • 데몬이란 무엇인가
  • 포그라운드와 백그라운드
  • fork와 exec — 프로세스 탄생의 원리
  • 좀비 프로세스 — 회수되지 않은 시체
  • 고아 프로세스 — 부모를 잃은 자식
  • 용어
  • 연습 문제