Process

리눅스

목록 보기
4/8
post-thumbnail

1. Program에서 Process로

Program이란?

  • Program은 disk에 저장된 sequence of instructions
  • code + data + metadata (loading & execution 정보)

Process란?

  • Process = running program
  • program이 memory에 load되고 CPU에서 실행되면 process가 된다
  • Linux에서 command 하나 실행할 때마다 new process 생성

예:

$ pwd

pwd program이 실행되며 하나의 process가 생성됨


2. Process ID (PID)

  • Linux는 모든 process를 PID (Process ID) 로 관리
  • PID는 unique
  • 종료된 process의 PID는 재사용 가능

3. fork system call

  • parent process → 기존 process
  • child process → 새로 생성된 process
pid_t pid = fork();

return value of fork()

  • 실패 → -1 (parent)

  • 성공:

    • child process → 0
    • parent process → child의 PID

  • fork 이후 parent와 child는 동시에 실행
  • 변수는 복사되지만, 서로 다른 address space

5. Process Descriptor: task_struct

Linux kernel에서 process는 task로 관리됨
kernel은 circular doubly linked list (the task list) 로 모든 task를 관리

  • 모든 process는 struct task_struct로 표현

  • 정의 위치: <linux/sched.h>

  • task_truct 내부에:

    • parent
    • children (list)
    • sibling (형제 task)

7. Process States (Linux)

Linux에서 process 상태는 task->state로 표현됨

TASK_RUNNING

  • runnable 상태
  • CPU에서 실행 중이거나 runqueue에서 대기 중

TASK_INTERRUPTIBLE

  • sleeping 상태
  • event 발생 또는 signal 수신 시 TASK_RUNNING으로 변경

TASK_UNINTERRUPTIBLE

  • sleeping 상태
  • signal로도 wake up 불가
  • I/O 대기 등 반드시 기다려야 하는 상황

TASK_STOPPED

  • execution이 중단된 상태
  • 예: SIGSTOP 수신

8. Process State 변경

Kernel에서 process state 변경 함수:

  • set_current_state(state)
  • set_task_state(task, state)

9. Example (Producer–Consumer)

Producer

  • event를 생성하고 consumer를 깨운다

Consumer

  • event가 있는지 확인한다
  • event가 있다면, 리스트에 쌓인 모든 pending event를 처리한다
  • 그렇지 않으면, producer가 consumer를 깨울 때까지 잠든다

10. Linux에서 Task 생성 절차

fork() vs clone()

fork()

  • parent task의 모든 state를 copy
  • 완전히 독립적인 process 생성

clone()

  • parent와 일부 state를 공유
  • thread 생성의 기반

12. clone flags

clone()은 어떤 자원을 공유할지 flag로 결정

Linux thread는 사실상 clone() + flags 조합

CLONE_VM 설정 여부Memory Space 동작
CLONE_VM = set호출한 process와 child process가 같은 memory space를 공유
CLONE_VM = not setchild process가 clone() 호출 시점의 호출한 process memory space를 복사한 별도의 공간에서 실행

13. _do_fork() 핵심 역할


15. State Sharing vs Copying

  • flag가 set → share (reference count 증가)
  • flag가 unset → copy (새 구조체 생성)

예:

  • CLONE_FILES set → files_struct 공유
  • unset → files_struct 복사

16. fork와 Memory: Copy-on-Write (COW)

문제

  • fork 시 memory 전체 copy → 매우 비효율적

해결: Copy-on-Write

  • 자원을 복사하기 위한 최적화 기법
    실제 copy 작업은 자원의 소유자 중 하나가 그 자원을 수정할 때까지 지연됨
    write가 발생하면 그때 자원을 copy한 뒤 수정함

즉,

  • read-only → 공유
  • write 발생 → 그 순간 copy


do_fork()가 호출될 때는 page frame(실제 memory 내용)는 복사하지 않고, page table만 복사


Parent든 Child든 처음으로 write를 시도하는 순간에만 그 page frame을 복사

👉 fork() 직후에는 memory를 안 복사하고,
👉 실제로 수정하려고 할 때 그 page만 복사


  1. 새로운 task를 생성한다. 새로 생성된 task의 parent task는 _do_fork()를 실행 중인 현재 task이다.
  2. 새로운 task는 parent task의 data structure를 복사하여 생성되며, 어떤 clone flag를 사용하느냐에 따라 일부는 공유되고 일부는 새로 생성되어 사용된다.
  3. copy_process()는 생성된 task의 task_struct 구조체를 반환한다.

get_task_pid()의 두 번째 인자로 PIDTYPE_PID가 전달되면, 해당 task의 pid를 나타내는 pid 구조체를 반환한다.


새로 생성된 task를 run-queue에 넣는다.



files_struct

  1. child를 위해 열린 파일 정보를 관리하는 files_struct 구조체를 생성한다.
  2. parent의 files_struct 내용을 child의 것으로 복사한다.
  3. CLONE_FILES flag를 사용하면 복사하지 않고, 구조체를 공유하며 reference count를 증가시킨다.

fs_struct

  1. child를 위해 파일 시스템 정보(예: root directory, current directory)를 관리하는 fs_struct 구조체를 생성한다.
  2. parent의 fs_struct 내용을 child의 것으로 복사한다.
  3. CLONE_FS flag를 사용하면 복사하지 않고, 구조체를 공유하며 reference count를 증가시킨다.

sighand_struct

  1. child를 위해 등록된 signal handler 정보를 관리하는 sighand_struct 구조체를 생성한다.
  2. parent의 sighand_struct 내용을 child의 것으로 복사한다.
  3. CLONE_SIGHAND flag를 사용하면 복사하지 않고, 구조체를 공유하며 reference count를 증가시킨다.

signal_struct

  1. child를 위해 처리해야 할 signal 정보를 관리하는 signal_struct 구조체를 생성한다.
  2. parent의 signal_struct 내용을 child의 것으로 복사한다.
  3. CLONE_THREAD flag를 사용하면 복사하지 않고, 구조체를 공유한다.

mm_struct

  1. child를 위해 address space를 관리하는 mm_struct 구조체를 생성한다.

  2. parent의 mm_struct 내용을 child의 것으로 복사한다.

  3. CLONE_VM flag를 사용하면 복사하지 않고, 구조체를 공유하며 mm_structmm_users 필드를 증가시킨다.


Signal

이건 한마디로 말하면
👉 fork() 할 때 Linux kernel이 각종 자원들을 “어떻게 복사하거나 공유하는지”를 코드 기준으로 설명한 슬라이드 묶음이야.

아래에서 주제별로 정리해서 설명할게.


Signal이란?

  • process에게 보내는 비동기 이벤트

    • SIGINT (2) : interrupt
    • SIGKILL (9) : 강제 종료
    • SIGALRM (14) : alarm
    • SIGCHLD (20) : child 상태 변화 알림

1️⃣ Ctrl + C 예제 코드

  • Ctrl + C를 누르면 SIGINT 발생
  • signal(SIGINT, handler)custom handler 등록
  • handler에서 원하는 동작 수행 후 exit()

👉 signal은 process 제어 메커니즘


2️⃣ copy_files() – 열린 파일 복사

  • parent process의 open file 정보를 child로 처리

  • parent의 files_struct복사

  • CLONE_FILES flag가 있으면:

    • 복사 안 함
    • 구조체 공유
    • reference count 증가

👉 thread는 보통 open file을 공유함


3️⃣ files_struct → fdtable → file 구조

  • files_struct : process 단위 open files
  • fdtable : fd 배열
  • file : 실제 open file object

중요한 포인트

  • fd 배열은 복사됨
  • file object 자체는 공유 (ref count 증가)

4️⃣ copy_fs() – 파일 시스템 정보

fs_struct가 관리하는 것

  • root directory
  • current working directory
  • umask 등

동작

  • CLONE_FS 없으면:

    • fs_struct 복사
  • CLONE_FS 있으면:

    • 복사 안 함
    • 공유

👉 같은 process의 thread들은 보통 cwd를 공유


5️⃣ copy_fs_struct() 내부

  1. slab allocator로 새 fs_struct 할당
  2. parent의 root / pwd 복사
  3. 각각에 대해 reference count 증가

👉 directory path도 reference-counted resource


6️⃣ copy_sighand() – signal handler

sighand_struct란?

  • signal handler 함수 정보 관리

  • 기본:

    • sighand_struct 복사
  • CLONE_SIGHAND 있으면:

    • 복사 안 함
    • 공유
    • ref count 증가

👉 thread들은 보통 signal handler 공유


요약

fork()는 단순 복사가 아니다

  • 자원별로:

    • 복사할지
    • 공유할지를
    • flag로 결정
  • kernel은:

    • reference count
    • Copy-on-Write로 성능 최적화

0개의 댓글