Do You Coding?

[function] fork ํ•จ์ˆ˜ ์•Œ์•„๋ณด๊ธฐ ๋ณธ๋ฌธ

CS & Engineering/C

[function] fork ํ•จ์ˆ˜ ์•Œ์•„๋ณด๊ธฐ

๐Ÿ“Œ ๋งค๋‰ด์–ผ (Linux)

๋”๋ณด๊ธฐ

NAME
       fork - create a child process
: ํ•˜์œ„ ํ”„๋กœ์„ธ์Šค ์ƒ์„ฑํ•˜๊ธฐ


SYNOPSIS
       #include <sys/types.h>
       #include <unistd.h>
       pid_t fork(void);

DESCRIPTION
       fork()  creates a new process by duplicating the calling process.  The new process is referred
       to as the child process.  The calling process is referred to as the parent process.

       The child process and the parent process run in separate memory spaces.  At the time of fork()
       both  memory spaces have the same content.  Memory writes, file mappings (mmap(2)), and unmapโ€
       pings (munmap(2)) performed by one of the processes do not affect the other.

       The child process is an exact duplicate of the parent process except for the following points:
       *  The child has its own unique process ID, and this PID does not match the ID of any existing
          process group (setpgid(2)) or session.
       *  The child's parent process ID is the same as the parent's process ID.
       *  The child does not inherit its parent's memory locks (mlock(2), mlockall(2)).
       *  Process  resource utilizations (getrusage(2)) and CPU time counters (times(2)) are reset to
          zero in the child.
       *  The child's set of pending signals is initially empty (sigpending(2)).
       *  The child does not inherit semaphore adjustments from its parent (semop(2)).
       *  The child does not inherit process-associated record locks from its parent (fcntl(2)).  (On
          the  other  hand,  it  does inherit fcntl(2) open file description locks and flock(2) locks
          from its parent.)
       *  The child does not inherit timers  from  its  parent  (setitimer(2),  alarm(2),  timer_creโ€
          ate(2)).
       *  The  child  does  not  inherit  outstanding  asynchronous  I/O  operations  from its parent
          (aio_read(3), aio_write(3)), nor does it inherit any asynchronous  I/O  contexts  from  its
          parent (see io_setup(2)).

       The  process  attributes  in  the preceding list are all specified in POSIX.1.  The parent and
       child also differ with respect to the following Linux-specific process attributes:

       *  The child does not inherit directory change notifications (dnotify) from  its  parent  (see
          the description of F_NOTIFY in fcntl(2)).
       *  The  prctl(2) PR_SET_PDEATHSIG setting is reset so that the child does not receive a signal
          when its parent terminates.
       *  The default timer slack value is set to the parent's current timer slack  value.   See  the
          description of PR_SET_TIMERSLACK in prctl(2).
       *  Memory mappings that have been marked with the madvise(2) MADV_DONTFORK flag are not inherโ€
          ited across a fork().
       *  Memory in address ranges that have been marked with the madvise(2) MADV_WIPEONFORK flag  is
          zeroed  in  the  child  after  a fork().  (The MADV_WIPEONFORK setting remains in place for
          those address ranges in the child.)
       *  The termination signal of the child is always SIGCHLD (see clone(2)).
       *  The port access permission bits set by ioperm(2) are not inherited by the child; the  child
          must turn on any bits that it requires using ioperm(2).

       Note the following further points:
       *  The  child  process is created with a single thread—the one that called fork().  The entire
          virtual address space of the parent is replicated in the child, including the states of muโ€
          texes, condition variables, and other pthreads objects; the use of pthread_atfork(3) may be
          helpful for dealing with problems that this can cause.
       *  After a fork() in a multithreaded program, the child can safely call only async-signal-safe
          functions (see signal-safety(7)) until such time as it calls execve(2).
       *  The child inherits copies of the parent's set of open file descriptors.  Each file descripโ€
          tor in the child refers to the same open file description (see open(2)) as the  correspondโ€
          ing  file  descriptor  in  the parent.  This means that the two file descriptors share open
          file status flags, file offset, and signal-driven I/O attributes (see  the  description  of
          F_SETOWN and F_SETSIG in fcntl(2)).

       *  The  child  inherits  copies  of  the  parent's  set of open message queue descriptors (see
          mq_overview(7)).  Each file descriptor in the child refers to the same open  message  queue
          description  as  the  corresponding file descriptor in the parent.  This means that the two
          file descriptors share the same flags (mq_flags).
       *  The child inherits copies of the parent's set of open directory streams  (see  opendir(3)).
          POSIX.1 says that the corresponding directory streams in the parent and child may share the
          directory stream positioning; on Linux/glibc they do not.

: fork()๋Š” ํ˜ธ์ถœ ํ”„๋กœ์„ธ์Šค๋ฅผ ๋ณต์ œํ•˜์—ฌ ์ƒˆ ํ”„๋กœ์„ธ์Šค๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.

์ƒˆ ํ”„๋กœ์„ธ์Šค๋ฅผ ์ž์‹ ํ”„๋กœ์„ธ์Šค(child process)๋ผ๊ณ  ํ•˜๋ฉฐ

ํ˜ธ์ถœ ํ”„๋กœ์„ธ์Šค๋ฅผ ๋ถ€๋ชจ ํ”„๋กœ์„ธ์Šค(parent process)๋ผ๊ณ  ํ•ฉ๋‹ˆ๋‹ค.

์ž์‹ ํ”„๋กœ์„ธ์Šค์™€ ๋ถ€๋ชจ ํ”„๋กœ์„ธ์Šค๋Š” ๋ณ„๋„์˜ ๋ฉ”๋ชจ๋ฆฌ ๊ณต๊ฐ„์—์„œ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค.

fork() ์‹œ์ ์—์„œ ๋‘ ๋ฉ”๋ชจ๋ฆฌ ๊ณต๊ฐ„์€ ๋ชจ๋‘ ๋™์ผํ•œ ๋‚ด์šฉ์„ ๊ฐ–์Šต๋‹ˆ๋‹ค.

ํ”„๋กœ์„ธ์Šค ์ค‘ ํ•˜๋‚˜์— ์˜ํ•ด ์ˆ˜ํ–‰๋˜๋Š” ๋ฉ”๋ชจ๋ฆฌ ์“ฐ๊ธฐ, ํŒŒ์ผ ๋งคํ•‘(mmap(2)) ๋ฐ ๋งคํ•‘ ํ•ด์ œ(munmap(2))๋Š”

๋‹ค๋ฅธ ํ”„๋กœ์„ธ์Šค์— ์˜ํ–ฅ์„ ๋ฏธ์น˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

์ž์‹ ํ”„๋กœ์„ธ์Šค๋Š” ๋‹ค์Œ ์‚ฌํ•ญ์„ ์ œ์™ธํ•˜๊ณ  ๋ถ€๋ชจ ํ”„๋กœ์„ธ์Šค๋ฅผ ์ •ํ™•ํžˆ ๋ณต์ œํ•œ ๊ฒƒ์ž…๋‹ˆ๋‹ค:
* ์ž์‹์—๋Š” ๊ณ ์œ ํ•œ ํ”„๋กœ์„ธ์Šค ID๊ฐ€ ์žˆ์œผ๋ฉฐ ์ด PID๋Š” ๊ธฐ์กด ํ”„๋กœ์„ธ์Šค ๊ทธ๋ฃน(setpgid(2)) ๋˜๋Š” ์„ธ์…˜์˜ ID์™€ ์ผ์น˜ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
* ์ž๋…€์˜ ๋ถ€๋ชจ ํ”„๋กœ์„ธ์Šค ID๋Š” ๋ถ€๋ชจ ํ”„๋กœ์„ธ์Šค ID์™€ ๋™์ผํ•ฉ๋‹ˆ๋‹ค.
* ์ž์‹์€ ๋ถ€๋ชจ์˜ ๋ฉ”๋ชจ๋ฆฌ ์ž ๊ธˆ(mlock(2), mlockall(2))์„ ์ƒ์†๋ฐ›์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
* ํ”„๋กœ์„ธ์Šค ๋ฆฌ์†Œ์Šค ์‚ฌ์šฉ๋ฅ (getrassage(2)) ๋ฐ CPU ์‹œ๊ฐ„ ์นด์šดํ„ฐ(time(2))๋Š” ํ•˜์œ„ ํ•ญ๋ชฉ์—์„œ 0์œผ๋กœ ์žฌ์„ค์ •๋ฉ๋‹ˆ๋‹ค.
* ์ž์‹์˜ ๋ณด๋ฅ˜ ์‹ ํ˜ธ ์„ธํŠธ๊ฐ€ ์ฒ˜์Œ์—๋Š” ๋น„์–ด ์žˆ์Šต๋‹ˆ๋‹ค(sigpending(2)).
* ์ž์‹์€ ๋ถ€๋ชจ๋กœ๋ถ€ํ„ฐ ์„ธ๋งˆํฌ์–ด ์กฐ์ •์„ ์ƒ์†๋ฐ›์ง€ ์•Š์Šต๋‹ˆ๋‹ค(semop(2)).
* ์ž์‹์€ ๋ถ€๋ชจ๋กœ๋ถ€ํ„ฐ ํ”„๋กœ์„ธ์Šค ๊ด€๋ จ ๋ ˆ์ฝ”๋“œ ์ž ๊ธˆ์„ ์ƒ์†๋ฐ›์ง€ ์•Š์Šต๋‹ˆ๋‹ค(fcntl(2)).

(๋ฐ˜๋ฉด ๋ถ€๋ชจ๋กœ๋ถ€ํ„ฐ fcntl(2) ์—ด๋ฆฐ ํŒŒ์ผ ์„ค๋ช… ์ž ๊ธˆ๊ณผ flock(2) ์ž ๊ธˆ์„ ์ƒ์†๋ฐ›์Šต๋‹ˆ๋‹ค.)
* ์ž์‹์€ ๋ถ€๋ชจ๋กœ๋ถ€ํ„ฐ ํƒ€์ด๋จธ๋ฅผ ์ƒ์†๋ฐ›์ง€ ์•Š์Šต๋‹ˆ๋‹ค(setitimer(2), alarm(2), timer_create(2)).
* ์ž์‹์€ ์ƒ์œ„(aio_read(3), aio_write(3))์—์„œ ๋ฏธ๊ฒฐ ๋น„๋™๊ธฐ I/O ์ž‘์—…์„ ์ƒ์†ํ•˜์ง€ ์•Š์œผ๋ฉฐ,

์ƒ์œ„์—์„œ ๋น„๋™๊ธฐ I/O ์ปจํ…์ŠคํŠธ๋ฅผ ์ƒ์†ํ•˜์ง€๋„ ์•Š์Šต๋‹ˆ๋‹ค(io_setup(2) ์ฐธ์กฐ).
์ด์ „ ๋ชฉ๋ก์˜ ํ”„๋กœ์„ธ์Šค ํŠน์„ฑ์€ ๋ชจ๋‘ POSIX.1์— ์ง€์ •๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.

 

๋ถ€๋ชจ์™€ ์ž์‹์€ ๋˜ํ•œ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋ฆฌ๋ˆ…์Šค ๊ณ ์œ ์˜ ํ”„๋กœ์„ธ์Šค ํŠน์„ฑ๊ณผ ๊ด€๋ จํ•˜์—ฌ ๋‹ค๋ฆ…๋‹ˆ๋‹ค:
* ์ž์‹์ด ๋ถ€๋ชจ๋กœ๋ถ€ํ„ฐ ๋””๋ ‰ํ† ๋ฆฌ ๋ณ€๊ฒฝ ์•Œ๋ฆผ(dnotify)์„ ์ƒ์†๋ฐ›์ง€ ์•Š์Šต๋‹ˆ๋‹ค(fcntl(2)์˜ F_NOTIFY ์„ค๋ช… ์ฐธ์กฐ).
* prctl(2) PR_SET_PDESSIG ์„ค์ •์€ ๋ถ€๋ชจ๊ฐ€ ์ข…๋ฃŒ๋  ๋•Œ ์ž์‹์ด ์‹ ํ˜ธ๋ฅผ ๋ฐ›์ง€ ์•Š๋„๋ก ์žฌ์„ค์ •๋ฉ๋‹ˆ๋‹ค.
* ๊ธฐ๋ณธ ํƒ€์ด๋จธ ์Šฌ๋ž™ ๊ฐ’์€ ๋ถ€๋ชจ์˜ ํ˜„์žฌ ํƒ€์ด๋จธ ์Šฌ๋ž™ ๊ฐ’์œผ๋กœ ์„ค์ •๋ฉ๋‹ˆ๋‹ค.

prctl(2)์˜ PR_SET_TIMERSLACK์— ๋Œ€ํ•œ ์„ค๋ช…์„ ์ฐธ์กฐํ•˜์‹ญ์‹œ์˜ค.
* madvise(2) MADV_DONTFORK ํ”Œ๋ž˜๊ทธ๋กœ ํ‘œ์‹œ๋œ ๋ฉ”๋ชจ๋ฆฌ ๋งคํ•‘์€ ํฌํฌ()์—์„œ ์ƒ์†๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
* madvise(2) MADV_WIPEONFORK ํ”Œ๋ž˜๊ทธ๋กœ ํ‘œ์‹œ๋œ ์ฃผ์†Œ ๋ฒ”์œ„์˜ ๋ฉ”๋ชจ๋ฆฌ๋Š” ํฌํฌ() ์ดํ›„ ์ž์‹์—์„œ ์˜์ ์œผ๋กœ ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค.(MADV_WIPEONFORK ์„ค์ •์€ ์ž์‹์˜ ํ•ด๋‹น ์ฃผ์†Œ ๋ฒ”์œ„์— ๋Œ€ํ•ด ๊ทธ๋Œ€๋กœ ์œ ์ง€๋ฉ๋‹ˆ๋‹ค.)
* ์ž์‹์˜ ์ข…๋ฃŒ ์‹ ํ˜ธ๋Š” ํ•ญ์ƒ SIGCHLD์ž…๋‹ˆ๋‹ค(clone(2) ์ฐธ์กฐ).

* ioperm(2)์—์„œ ์„ค์ •ํ•œ ํฌํŠธ ์•ก์„ธ์Šค ๊ถŒํ•œ ๋น„ํŠธ๋Š” ์ž์‹์—๊ฒŒ ์ƒ์†๋˜์ง€ ์•Š์œผ๋ฉฐ,

์ž์‹์€ ioperm(2)์„ ์‚ฌ์šฉํ•˜์—ฌ ํ•„์š”ํ•œ ๋ชจ๋“  ๋น„ํŠธ๋ฅผ ์ผœ์•ผ ํ•ฉ๋‹ˆ๋‹ค.

 

๋‹ค์Œ ์‚ฌํ•ญ์— ์ฃผ์˜ํ•˜์‹ญ์‹œ์˜ค:
* ์ž์‹ ํ”„๋กœ์„ธ์Šค๋Š” fork()๋ผ๋Š” ๋‹จ์ผ ์Šค๋ ˆ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค. ๋ถ€๋ชจ์˜ ์ „์ฒด ๊ฐ€์ƒ ์ฃผ์†Œ ๊ณต๊ฐ„์€ ์Œ์†Œ๊ฑฐ ์ƒํƒœ,

์กฐ๊ฑด ๋ณ€์ˆ˜ ๋ฐ ๊ธฐํƒ€ pthread ๊ฐœ์ฒด๋ฅผ ํฌํ•จํ•˜์—ฌ ์ž์‹์—์„œ ๋ณต์ œ๋ฉ๋‹ˆ๋‹ค. pthread_atfork(3)์„ ์‚ฌ์šฉํ•˜๋ฉด

์ด๋Ÿฌํ•œ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋Š” ๋ฐ ๋„์›€์ด ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
* ๋ฉ€ํ‹ฐ ์Šค๋ ˆ๋“œ ํ”„๋กœ๊ทธ๋žจ์—์„œ ํฌํฌ()๋ฅผ ์‚ฌ์šฉํ•œ ํ›„, ์•„์ด๋Š” execve(2)๋ฅผ ํ˜ธ์ถœํ•  ๋•Œ๊นŒ์ง€

๋น„๋™๊ธฐ ์‹ ํ˜ธ ์•ˆ์ „ ๊ธฐ๋Šฅ(signal-safety(7))๋งŒ ์•ˆ์ „ํ•˜๊ฒŒ ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
* ์ž์‹์€ ๋ถ€๋ชจ์˜ ์˜คํ”ˆ ํŒŒ์ผ ๋””์Šคํฌ๋ฆฝํ„ฐ ์ง‘ํ•ฉ์˜ ๋ณต์‚ฌ๋ณธ์„ ์ƒ์†ํ•ฉ๋‹ˆ๋‹ค. ์ž์‹์˜ ๊ฐ ํŒŒ์ผ ๋””์Šคํฌ๋ฆฝํ„ฐ๋Š”

๋ถ€๋ชจ์˜ ํ•ด๋‹น ํŒŒ์ผ ๋””์Šคํฌ๋ฆฝํ„ฐ์™€ ๋™์ผํ•œ ์˜คํ”ˆ ํŒŒ์ผ ๋””์Šคํฌ๋ฆฝํ„ฐ(open(2))๋ฅผ ์ฐธ์กฐํ•ฉ๋‹ˆ๋‹ค.

์ด๋Š” ๋‘ ํŒŒ์ผ ๋””์Šคํฌ๋ฆฝํ„ฐ๊ฐ€ ์˜คํ”ˆ ํŒŒ์ผ ์ƒํƒœ ํ”Œ๋ž˜๊ทธ, ํŒŒ์ผ ์˜คํ”„์…‹ ๋ฐ ์‹ ํ˜ธ ๊ธฐ๋ฐ˜ I/O ์†์„ฑ์„

๊ณต์œ ํ•œ๋‹ค๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค(fcntl(2)์˜ F_SETOWN ๋ฐ F_SETSIG ์„ค๋ช… ์ฐธ์กฐ).
* ์ž์‹์€ ๋ถ€๋ชจ์˜ ์—ด๋ฆฐ ๋ฉ”์‹œ์ง€ ํ ๋””์Šคํฌ๋ฆฝํ„ฐ ์ง‘ํ•ฉ์˜ ๋ณต์‚ฌ๋ณธ์„ ์ƒ์†ํ•ฉ๋‹ˆ๋‹ค(mq_overview(7)).

์ž์‹์˜ ๊ฐ ํŒŒ์ผ ๋””์Šคํฌ๋ฆฝํ„ฐ๋Š” ๋ถ€๋ชจ์˜ ํ•ด๋‹น ํŒŒ์ผ ๋””์Šคํฌ๋ฆฝํ„ฐ์™€ ๋™์ผํ•œ ์—ด๋ฆฐ ๋ฉ”์‹œ์ง€ ํ ๋””์Šคํฌ๋ฆฝํ„ฐ๋ฅผ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.

์ด๋Š” ๋‘ ํŒŒ์ผ ๋””์Šคํฌ๋ฆฝํ„ฐ๊ฐ€ ๋™์ผํ•œ ํ”Œ๋ž˜๊ทธ(mq_flags)๋ฅผ ๊ณต์œ ํ•œ๋‹ค๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.
* ์ž์‹์€ ๋ถ€๋ชจ์˜ ์—ด๋ฆฐ ๋””๋ ‰ํ„ฐ๋ฆฌ ์ŠคํŠธ๋ฆผ ์ง‘ํ•ฉ์˜ ๋ณต์‚ฌ๋ณธ์„ ์ƒ์†ํ•ฉ๋‹ˆ๋‹ค(opendir(3) ์ฐธ์กฐ).
POSIX.1์€ ๋ถ€๋ชจ ๋ฐ ์ž์‹์˜ ํ•ด๋‹น ๋””๋ ‰ํ† ๋ฆฌ ์ŠคํŠธ๋ฆผ์ด ๋””๋ ‰ํ† ๋ฆฌ ์ŠคํŠธ๋ฆผ ํฌ์ง€์…”๋‹์„ ๊ณต์œ ํ•  ์ˆ˜ ์žˆ์ง€๋งŒ

Linux/glibc์—์„œ๋Š” ๊ณต์œ ํ•˜์ง€ ์•Š๋Š”๋‹ค๊ณ  ๋งํ•ฉ๋‹ˆ๋‹ค.

 

RETURN VALUE
       On success, the PID of the child process is returned in the parent, and 0 is returned  in  the
       child.   On  failure,  -1 is returned in the parent, no child process is created, and errno is
       set appropriately.

์„ฑ๊ณต ์‹œ ์ž์‹ ํ”„๋กœ์„ธ์Šค์˜ PID๋Š” ๋ถ€๋ชจ์—์„œ ๋ฐ˜ํ™˜๋˜๊ณ  0์€ ์ž์‹์—์„œ ๋ฐ˜ํ™˜๋ฉ๋‹ˆ๋‹ค.

์‹คํŒจ ์‹œ -1์€ ๋ถ€๋ชจ์—์„œ ๋ฐ˜ํ™˜๋˜๊ณ  ์ž์‹ ํ”„๋กœ์„ธ์Šค๋Š” ์ƒ์„ฑ๋˜์ง€ ์•Š์œผ๋ฉฐ errno๋Š” ์ ์ ˆํ•˜๊ฒŒ ์„ค์ •๋ฉ๋‹ˆ๋‹ค.

๐Ÿ“Œ ํ•จ์ˆ˜ ์„ค๋ช…

fork ํ•จ์ˆ˜๋Š” ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•œ ํ”„๋กœ์„ธ์Šค๋ฅผ ๋ณต์‚ฌํ•˜๋Š” ๊ธฐ๋Šฅ์„ ๊ฐ€์ง€๋ฉฐ,

์›๋ž˜ ์ง„ํ–‰๋˜๋˜ ํ”„๋กœ์„ธ์Šค๋ฅผ '๋ถ€๋ชจ ํ”„๋กœ์„ธ์Šค' (parent), ๋ณต์‚ฌ๋œ ํ”„๋กœ์„ธ์Šค๋ฅผ '์ž์‹ ํ”„๋กœ์„ธ์Šค' (child) ๋ผ ํ•œ๋‹ค.

 

(ํ”„๋กœ์„ธ์Šค์— ๋Œ€ํ•œ ์ถ”๊ฐ€ ๋‚ด์šฉ : 2024.06.02 - [ํ”„๋กœ๊ทธ๋ž˜๋ฐ/C] - [study] ํ”„๋กœ์„ธ์Šค (Process))

ํ”„๋กœ์„ธ์Šค์˜ id๋ฅผ pid๋ผ ํ•˜๋ฉฐ, fork ํ•จ์ˆ˜๊ฐ€ ๋ฐ˜ํ™˜ํ•˜๋Š” ๊ฐ’์ด ์ด pid์ด๋‹ค.

๋ถ€๋ชจ ํ”„๋กœ์„ธ์Šค๋Š” ์ž์‹ pid๋ฅผ ๋ฐ˜ํ™˜ํ•˜๊ณ , ์ž์‹ ํ”„๋กœ์„ธ์Šค๋Š” 0 ๋ฐ˜ํ™˜, ํ•จ์ˆ˜ ์‹คํ–‰ ์‹คํŒจ ์‹œ -1 ๋ฐ˜ํ™˜์ด๋‹ค.

 

๊ทธ๋ฆผ์„ ํ†ตํ•ด ๋ณด๋ฉด, fork๋Š” ๊ธฐ์กด Parent Process๋ฅผ Parent Process์˜ ์ง„ํ–‰๊ณผ ํ•จ๊ป˜

ํ•ด๋‹น ํ”„๋กœ์„ธ์Šค๋ฅผ ๋ณต์‚ฌํ•œ Child Process๋ฅผ ๋งŒ๋“ค์–ด์ฃผ๋Š” ํ•จ์ˆ˜๋กœ ์“ฐ์ธ๋‹ค.

์ฝ”๋“œ๋ฅผ ํ†ตํ•ด ํ™•์ธํ•ด๋ณด๋ฉด ๋”์šฑ ์‰ฝ๊ฒŒ ์•Œ ์ˆ˜ ์žˆ๋‹ค.


 

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>

int main()
{
	fork();
	printf("hello\n");
	return 0;
}

 

์ž, fork()๋ฅผ ํ•œ๋ฒˆ ์‹คํ–‰ํ•œ๋‹ค๊ณ  ํ–ˆ์„ ๋•Œ, ์ง„ํ–‰์ƒํ™ฉ์„ ์‚ดํŽด๋ณด๋„๋ก ํ•˜๊ฒ ๋‹ค.

์ด ํ”„๋กœ๊ทธ๋žจ์ด ์‹œ์ž‘ํ•˜์—ฌ ํ”„๋กœ์„ธ์Šค๊ฐ€ ๋งŒ๋“ค์–ด์ง€๋ฉด, main๋ฌธ์ด ์‹คํ–‰์ด ๋œ๋‹ค.

๊ทธ๋Ÿฌํ•˜์—ฌ, fork()๋ฅผ ์ฒ˜์Œ ๋งŒ๋‚˜๊ฒŒ ๋˜๋Š”๋ฐ, ์ด ์ƒํ™ฉ์—์„œ ๊ธฐ์กด ํ”„๋กœ์„ธ์Šค๋Š” ๋ถ€๋ชจ ํ”„๋กœ์„ธ์Šค๊ฐ€ ๋˜์–ด, ์ž์‹ ํ”„๋กœ์„ธ์Šค๋ฅผ ๋ณต์‚ฌํ•œ๋‹ค.

๊ทธ๋Ÿผ fork() ์ดํ›„์— ์‹คํ–‰๋  ์ฝ”๋“œ๋“ค์„ ๊ฐ€์ง„ ๋‘ ๊ฐœ์˜ ํ”„๋กœ์„ธ์Šค๊ฐ€ ์ƒ๊ธฐ๊ฒŒ ๋œ ๊ฒƒ์ด๊ณ , printf()๊ฐ€ ๊ฐ๊ฐ ํ•œ๋ฒˆ์”ฉ ์‹คํ–‰ ๋˜๋Š” ๊ฒƒ์ด๋‹ค.

 

์ฝ”๋“œ์˜ ์ง„ํ–‰์„ ๊ทธ๋ฆผ์œผ๋กœ ๋ณด๋ฉด ์ด๋Ÿฐํ˜•ํƒœ๋ฅผ ๋Œ ์ˆ˜ ์žˆ๋‹ค.

fork ์ดํ›„ ๋ถ€ํ„ฐ์˜ ์ฝ”๋“œ๊ฐ€ ์ง„ํ–‰๋˜๋Š” ํ”„๋กœ์„ธ์Šค๊ฐ€ 2๊ฐ€์ง€๊ฐ€ ์ƒ๊ฒจ๋‚œ ๊ฒƒ์ด๋‹ค.

(ํ•˜๋‚˜๋Š” parent process์˜ ๊ธฐ์กด ์ง„ํ–‰, ํ•˜๋‚˜๋Š” ๋ณต์‚ฌ๋œ Child Process์˜ ์ง„ํ–‰)

 

๊ฒฐ๊ณผ - std_output)

hello
hello

 

์ด๋ ‡๊ฒŒ ๋‘ ํ”„๋กœ์„ธ์Šค๊ฐ€ ์‹คํ–‰๋˜์–ด ๊ฒฐ๊ณผ๊ฐ€ 2๊ฐœ์˜ hello๋ฅผ ์ถœ๋ ฅํ•˜๋Š” ์ƒํ™ฉ์ด ๋‚˜์˜จ๋‹ค.

์ด ๋‘ ํ”„๋กœ์„ธ์Šค๋Š” pid๋กœ ๊ตฌ๋ถ„์ด ๊ฐ€๋Šฅํ•˜๊ณ  (๋ถ€๋ชจ๋Š” ์ž์‹์˜ pid, ์ž์‹์€ 0) pid์˜ ๊ฐ’์„ ์ €์žฅํ•˜์—ฌ forkํ•œ๋‹ค๋ฉด,

๊ทธ ๊ฐ’์— ๋”ฐ๋ผ ๊ตฌ๋ถ„ํ•˜์—ฌ ์›ํ•˜๋Š” ์‹คํ–‰ ๊ฒฐ๊ณผ๋ฅผ ์–ป์„ ์ˆ˜๋„ ์žˆ๋‹ค. ๋‹ค์Œ ์ฝ”๋“œ๊ฐ€ ๊ทธ๋Ÿฌํ•œ ์ƒํ™ฉ์„ ๋ณด์—ฌ์ค€๋‹ค.


#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>

int main(void)
{
    pid_t pid = fork();
    if (pid == -1) {
        perror("fork failed");
        return (0);
    }
    else if (pid == 0) {
        printf("Hello from the child process!\n");
        return (0);
    }
    else {
        printf("Hello from the parent process!\n");
        return (0);
	}
    return (0);
}

 

๊ฒฐ๊ณผ - std_output)

Hello from the parent process!
Hello from the child process!

 

pid์˜ ๊ฐ’์ด 0์ด ๋œ ์ƒํ™ฉ์—์„œ๋Š” child ํ”„๋กœ์„ธ์Šค์ด๋ฏ€๋กœ, child์˜ ๊ฒฐ๊ณผ๊ฐ’์ด ๋‚˜์˜ค๋„๋ก ํ–ˆ๊ณ ,

pid์˜ ๊ฐ’์ด 0์ด๋‚˜ -1์ด ์•„๋‹ˆ๋ฉด, child ํ”„๋กœ์„ธ์Šค์˜ pid๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” parent ํ”„๋กœ์„ธ์Šค์ด๋ฏ€๋กœ parent์˜ ๊ฒฐ๊ณผ๊ฐ’์ด ๋‚˜์˜ค๋„๋ก ํ–ˆ๋‹ค.

 

์ด ์‹คํ–‰ ์ˆœ์„œ์— ๊ด€ํ•ด์„œ๋Š” '์Šค์ผ€์ค„๋ง'์— ๋”ฐ๋ผ OS๊ฐ€ ํŒ๋ณ„ํ•˜์—ฌ ๋‘˜ ์ค‘ ํ•˜๋‚˜๋“  ๋จผ์ € ์‹คํ–‰๋  ์ˆ˜ ์žˆ๋‹ค.

๊ทธ๋ ‡๋‹ค๋ฉด ์ข…๋ฃŒ ์ˆœ์„œ๋Š”? ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ '์Šค์ผ€์ค„๋ง'์— ๋”ฐ๋ฅด๊ฒ ์ง€๋งŒ ์ผ๋ฐ˜์ ์œผ๋กœ๋Š” ์ž์‹ ํ”„๋กœ์„ธ์Šค๊ฐ€ ์ข…๋ฃŒ๋  ๋•Œ๊นŒ์ง€ ๋ถ€๋ชจ๊ฐ€ ๊ธฐ๋‹ค๋ฆฐ๋‹ค.


#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>

int main()
{
	printf("Line 0\n");
	fork();
	printf("Line 1\n");
	fork();
	printf("Line 2\n");
	fork();
	printf("Line 3\n");
	return 0;
}

 

๋” ์‰ฌ์šด ์ดํ•ด๋ฅผ ์œ„ํ•ด, ์ด๋ฒˆ์—๋Š” fork๋ฅผ ๋ฌด๋ ค 3๋ฒˆ ์“ด ์ฝ”๋“œ๊ฐ€ ๋‚˜์™”๋‹ค.

๊ทธ๋ฆฌ๊ณ  ์ค‘๊ฐ„์ค‘๊ฐ„ printf๊ฐ€ ์กด์žฌํ•˜๋Š”๋ฐ ์–ด๋–ป๊ฒŒ ๋™์ž‘ํ• ์ง€ ์˜ˆ์ธกํ•ด๋ณด์ž.

 

 

๊ทธ๋ฆผ์œผ๋กœ ๋ณด๋ฉด, printf("Line 0")์€ ์ฒซ parent process์—์„œ ํ•œ๋ฒˆ ์‹คํ–‰๋˜๊ณ  ๊ทธ ์ดํ›„์— fork๋ฅผ ํ•˜๋ฉด

ํ•˜์œ„์˜ ์ฝ”๋“œ๋“ค๋กœ ์ด๋ค„์ง„ process๊ฐ€ ๋‘˜์ด ์ƒ๊ธฐ๊ณ , ๊ทธ๋Ÿผ printf("Line 1") ์€ ์ด ๋‘ ๋ฒˆ ์‹คํ–‰์ด ๋œ๋‹ค. ๊ทธ ์ดํ›„ ๊ฐ™์€ ๊ณผ์ •์œผ๋กœ

fork ๋˜๊ณ  printf("Line 2")๊ฐ€ ์žˆ๋Š” 4๊ฐœ์˜ ํ”„๋กœ์„ธ์Šค๊ฐ€ ์ƒ๊ธฐ๊ณ , ๊ทธ๋ ‡๊ฒŒ ๊ผฌ๋ฆฌ์— ๊ผฌ๋ฆฌ๋ฅผ ๋ฌผ์–ด, 1 + 2 + 4 + 8, 15๊ฐœ์˜ ์ค„์ด ์ƒ๊ธธ ๊ฒƒ์ด๋‹ค.

 

๊ฒฐ๊ณผ - std_output)

 

์–ธ๊ธ‰ํ–ˆ๋˜ ๋Œ€๋กœ, ์Šค์ผ€์ค„๋ง์— ์˜ํ•ด ์‹คํ–‰ ๋•Œ๋งˆ๋‹ค ํ”„๋กœ์„ธ์Šค ์‹คํ–‰ ์ˆœ์„œ๊ฐ€ ๋ฐ”๋€ ์ƒํ™ฉ์ด๋‹ค. 

ํ•˜์ง€๋งŒ ๋‹น์—ฐํ•˜๊ฒŒ๋„, Line 2๊ฐ€ ํ•œ๋ฒˆ๋„ ๋‚˜์˜ค์ง€ ์•Š์•˜๋Š”๋ฐ Line 3์ด ๋‚˜์˜ค๋Š” ๊ฒฝ์šฐ๋Š” ๋ฐœ์ƒํ•˜์ง€ ์•Š๋Š”๋‹ค.

์ด์™€ ๊ฐ™์ด ๊ฒฐ๊ณผ๋กœ ๋‚˜์˜ฌ ์ˆ˜ ์—†๋Š” ๋ถˆ๊ฐ€๋Šฅํ•œ ๊ฒฝ์šฐ๋Š” 'Infeasible output' ์ด๋ผ ํ•˜๊ณ ,

์‚ฌ์ง„๊ณผ ๊ฐ™์ด ์ •์ƒ์ ์œผ๋กœ ๋‚˜์˜ฌ ์ˆ˜ ์žˆ๋Š” ๊ฐ€๋Šฅํ•œ ๊ฒฝ์šฐ๋Š” 'Feasible output' ์ด๋ผ ํ•œ๋‹ค.


 

์ด fork์— ๋Œ€ํ•ด ์ถ”๊ฐ€์ ์ธ ์„ค๋ช…์„ ๋ง๋ถ™์ด๋„๋ก ํ•˜๊ฒ ๋‹ค.

 

[ fork์˜ ์šฉ๋„ ]

1. ๊ฐ™์€ ํ”„๋กœ๊ทธ๋žจ์—์„œ ์ƒˆ๋กœ์šด ์ œ์–ด ํ๋ฆ„์„ ๋งŒ๋“œ๋Š” ์šฉ๋„

2. ๋‹ค๋ฅธ ํ”„๋กœ๊ทธ๋žจ์„ ์‹คํ–‰ํ•˜๋Š” ์ƒˆ ํ”„๋กœ์„ธ์Šค๋ฅผ ๋งŒ๋“œ๋Š” ์šฉ๋„

๋Œ€๊ฐœ 2๋ฒˆ์˜ ์šฉ๋„๋กœ ์‚ฌ์šฉํ•˜๋Š”๋ฐ, ์‰˜์—์„œ ๋ช…๋ น์–ด๋ฅผ ํ†ตํ•ด ํ”„๋กœ์„ธ์Šค๋ฅผ ์‹คํ–‰ํ•˜๋Š” ๊ฒฝ์šฐ์ด๋‹ค.

 

๊ทธ๋ฆฌ๊ณ , ์ž์‹ ํ”„๋กœ์„ธ์Šค๊ฐ€ ์ƒ์„ฑ๋˜๋ฉด ๋ถ€๋ชจ ํ”„๋กœ์„ธ์Šค์˜ Stack, Heap, Data ๋ฅผ ๋ณต์‚ฌํ•˜๊ณ ,

๋ถ€๋ชจ ํ”„๋กœ์„ธ์Šค์˜ PCB(Process Control Block)๋„ ๋ณต์‚ฌํ•œ๋‹ค. Text ์˜์—ญ์€ ๋ณต์‚ฌ๋Œ€์‹  ๊ณต์œ ํ•œ๋‹ค.

์ด PCB์—๋Š” CPU์—์„œ ์ˆ˜ํ–‰๋˜๋˜ ๋ ˆ์ง€์Šคํ„ฐ ๊ฐ’๋“ค๊ณผ Program Counter ์ •๋ณด๊ฐ€ ์กด์žฌํ•˜๋ฏ€๋กœ

fork ์ดํ›„์˜ ์‹คํ–‰์ƒํƒœ๋ฅผ ๊ทธ๋Œ€๋กœ ๋ณต์‚ฌํ•˜์—ฌ ์‹คํ–‰๋œ๋‹ค.

 

๊ทธ๋ฆฌ๊ณ , COW(Copy On Write) ์ •์ฑ… ์ด๋ผ๋Š” '์“ฐ๊ธฐ ์ž‘์—… ์‹œ ๋ณต์‚ฌ'๊ฐ€ ์ผ์–ด๋‚˜๋Š” ์ตœ์ ํ™” ๊ธฐ์ˆ ์„ ์‚ฌ์šฉํ•˜๋Š”๋ฐ,

๋ง ๊ทธ๋Œ€๋กœ ์ด Resource๋ฅผ ์ˆ˜์ •ํ•  ๋•Œ๋งŒ ์‹ค์ œ๋กœ Copy๋ฅผ ํ•˜๊ณ ,

์ˆ˜์ •ํ•˜์ง€ ์•Š๊ณ  ์‚ฌ์šฉํ•  ๋•Œ๋Š” ๊ทธ๋ƒฅ ๊ณต์œ ํ•ด์„œ ์“ฐ๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•œ๋‹ค.

 

๊ทธ๋ฆฌํ•˜์—ฌ ๋ณต์‚ฌํ•œ ์ž์‹ ํ”„๋กœ์„ธ์Šค์˜ ๋ฉ”๋ชจ๋ฆฌ ๊ฐ€์ƒ ์ฃผ์†Œ๊ฐ€ ๋™์ผํ•˜๋ฉฐ,

๋‚ด์šฉ์ด ๋ณ€๊ฒฝ๋  ์‹œ ์ƒˆ๋กœ์šด ๋ฌผ๋ฆฌ ๋ฉ”๋ชจ๋ฆฌ ์ฃผ์†Œ๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋Š” ์ƒํ™ฉ์ด ์ƒ๊ธด๋‹ค.

 

๊ฒฐ๊ตญ, ๋ชจ๋“  ๋ฐ์ดํ„ฐ๋ฅผ ์ƒˆ๋กญ๊ฒŒ ๋ณต์‚ฌํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๊ธฐ ๋•Œ๋ฌธ์— ๋ณต์ œ ๋น„์šฉ์ด ๊ฑฐ์˜ ๋“ค์ง€ ์•Š๊ณ , ๊ด€๋ฆฌ๊ฐ€ ์šฉ์ดํ•˜๋‹ค.

ํ”„๋กœ์„ธ์Šค๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๊ฒƒ๋ณด๋‹ค fork๋ฅผ ํ†ตํ•ด ๋ณต์‚ฌํ•˜๋Š” ๊ฒƒ์— ๋Œ€ํ•œ ์˜์˜๊ฐ€ ๋ฐ”๋กœ ์ด๋Ÿฐ ๊ฒƒ์ด๋‹ค.


์ฐธ๊ณ )

https://velog.io/@jungbumwoo/fork-%EB%A5%BC-%EC%95%8C%EC%95%84%EB%B3%B4%EC%9E%90

https://code-lab1.tistory.com/39

https://wslog.dev/fork-exec