[Computer Science][Operating System] ๐Ÿ–ฅ๏ธ ์‹œ์Šคํ…œ ํ˜ธ์ถœ๊ณผ ํ”„๋กœ์„ธ์Šค ๊ด€๋ฆฌ

๊น€์ƒ์šฑยท2024๋…„ 8์›” 11์ผ
post-thumbnail

๐Ÿ› ๏ธ System Call

์šด์˜์ฒด์ œ์—์„œ ์‚ฌ์šฉ์ž ํ”„๋กœ๊ทธ๋žจ์ด ์šด์˜์ฒด์ œ์˜ ์ปค๋„์—๊ฒŒ ํŠน์ • ์„œ๋น„์Šค๋ฅผ ์š”์ฒญํ•  ๋•Œ ์‚ฌ์šฉํ•˜๋Š” ์ธํ„ฐํŽ˜์ด์Šค์ž…๋‹ˆ๋‹ค. ๊ฐ„๋‹จํžˆ ๋งํ•ด, ์‹œ์Šคํ…œ ํ˜ธ์ถœ์€ ํ”„๋กœ๊ทธ๋žจ์ด ์šด์˜์ฒด์ œ์—๊ฒŒ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•ด ๋‹ฌ๋ผ๊ณ  ์š”์ฒญํ•˜๋Š” ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค.


fork(), exec(), wait()์™€ ๊ฐ™์€ ๊ฒƒ๋“ค์€ ํ”„๋กœ์„ธ์Šค ์ƒ์„ฑ๊ณผ ์ œ์–ด(์ฆ‰, ํ”„๋กœ์„ธ์Šค ๊ด€๋ฆฌ)๋ฅผ ์œ„ํ•œ ์‹œ์Šคํ…œ ํ˜ธ์ถœ์ž…๋‹ˆ๋‹ค.

  • fork๋Š” ์ƒˆ๋กœ์šด ํ”„๋กœ์„ธ์Šค๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.
  • exec๋Š” ์ƒˆ๋กœ์šด ํ”„๋กœ๊ทธ๋žจ์„ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.
  • wait๋Š” ๋ถ€๋ชจ ํ”„๋กœ์„ธ์Šค๊ฐ€ ์ƒ์„ฑํ•œ ์ž์‹ ํ”„๋กœ์„ธ์Šค๊ฐ€ ์ข…๋ฃŒ๋  ๋•Œ๊นŒ์ง€ ๋Œ€๊ธฐํ•ฉ๋‹ˆ๋‹ค. ์ฆ‰, ์ž์‹ ํ”„๋กœ์„ธ์Šค๊ฐ€ ์ข…๋ฃŒ๋  ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ฆฌ๋Š” ๋ช…๋ น์–ด์ž…๋‹ˆ๋‹ค.
  • exit()๋Š” ํ”„๋กœ์„ธ์Šค๋ฅผ ์ข…๋ฃŒํ•˜๋Š” ์—ญํ• ์„ ํ•ฉ๋‹ˆ๋‹ค.

๐Ÿด Fork

์ƒˆ๋กœ์šด ํ”„๋กœ์„ธ์Šค๋ฅผ ์ƒ์„ฑํ•  ๋•Œ ์‚ฌ์šฉ๋˜๋ฉฐ, ํ˜„์žฌ ํ”„๋กœ์„ธ์Šค(๋ถ€๋ชจ)๋ฅผ ๋ณต์ œํ•˜์—ฌ ์ƒˆ๋กœ์šด ํ”„๋กœ์„ธ์Šค(์ž์‹)๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. ์ด ํ•จ์ˆ˜๊ฐ€ ํ˜ธ์ถœ๋˜๋ฉด ๋‘ ๊ฐœ์˜ ๊ฑฐ์˜ ๋™์ผํ•œ ํ”„๋กœ์„ธ์Šค๊ฐ€ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค.

  • ๋ถ€๋ชจ ํ”„๋กœ์„ธ์Šค: fork()๊ฐ€ ์„ฑ๊ณต์ ์œผ๋กœ ํ˜ธ์ถœ๋˜๋ฉด ์ž์‹ ํ”„๋กœ์„ธ์Šค์˜ PID๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
  • ์ž์‹ ํ”„๋กœ์„ธ์Šค: fork()์˜ ๋ฐ˜ํ™˜ ๊ฐ’์œผ๋กœ 0์„ ๋ฐ›์Šต๋‹ˆ๋‹ค.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main(int argc, char *argv[]) {
    printf("pid : %d\n", (int) getpid()); // pid : 29146
    
    int rc = fork(); // ์ฃผ๋ชฉ
    
    if (rc < 0) { // (1) fork ์‹คํŒจ
        exit(1);
    }
    else if (rc == 0) { // (2) child์ธ ๊ฒฝ์šฐ (fork ๊ฐ’์ด 0)
        printf("child (pid : %d)\n", (int) getpid());
    }
    else { // (3) parent case
        printf("parent of %d (pid : %d)\n", rc, (int)getpid());
    }
}

์œ„ ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ถœ๋ ฅ์ด ๋‚˜์˜ต๋‹ˆ๋‹ค:

pid:29146
parent of 29147 (pid:29146)
child (pid:29147)

์ถœ๋ ฅ ์ˆœ์„œ๋Š” ๋น„๊ฒฐ์ •์ ์ž…๋‹ˆ๋‹ค. ์ฆ‰, ๋ถ€๋ชจ์™€ ์ž์‹ ํ”„๋กœ์„ธ์Šค์˜ ์‹คํ–‰ ์ˆœ์„œ๋Š” ์šด์˜์ฒด์ œ์˜ ์Šค์ผ€์ค„๋Ÿฌ์— ๋”ฐ๋ผ ๋‹ฌ๋ผ์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

ํ•ด์„: PID๋Š” ํ”„๋กœ์„ธ์„œ ์‹๋ณ„์ž๋กœ, UNIX ์‹œ์Šคํ…œ์—์„œ๋Š” PID๋ฅผ ํ†ตํ•ด ํ”„๋กœ์„ธ์Šค์— ๋ช…๋ น์„ ๋‚ด๋ฆฝ๋‹ˆ๋‹ค. fork()๊ฐ€ ์‹คํ–‰๋˜๋Š” ์ˆœ๊ฐ„, ์ƒˆ๋กœ์šด ํ”„๋กœ์„ธ์Šค(์ž์‹)๊ฐ€ ์ƒ์„ฑ๋˜๋ฉฐ, ์ด๋•Œ ์ƒ์„ฑ๋œ ํ”„๋กœ์„ธ์Šค๋Š” ๋ถ€๋ชจ ํ”„๋กœ์„ธ์Šค์™€ ๊ฑฐ์˜ ๋™์ผํ•œ ๋ณต์‚ฌ๋ณธ์„ ๊ฐ–๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ์ด ์‹œ์ ์—์„œ ์šด์˜์ฒด์ œ๋Š” ๋‘ ๊ฐœ์˜ ํ”„๋กœ๊ทธ๋žจ์ด ๋™์‹œ์— ๋™์ž‘ํ•œ๋‹ค๊ณ  ์ธ์‹ํ•˜๋ฉฐ, ๋ณต์‚ฌ ์ดํ›„์˜ ๋™์ž‘์€ fork()์—์„œ ๋ฐ˜ํ™˜๋œ ์ˆœ์„œ๋ผ๊ณ  ์ธ์‹ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ ์ดํ›„๋Š” ์ด fork()์— ๋ฐ˜ํ™˜๊ฐ’์„ ํ†ตํ•ด ๊ตฌ๋ถ„๋ฉ๋‹ˆ๋‹ค.

์ฆ‰, Parent์˜ fork()๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด์„œ Child๊ฐ€ ๋ณต์‚ฌ๋˜๊ณ  Parent์™€ Child ๋‘˜ ๋‹ค์—์„œ ๋ฐฉ๊ธˆ ์‹คํ–‰๋œ ํ•œ๋ฒˆ์˜ fork ํ–‰์œ„์— ๋Œ€ํ•ด์„œ ๊ฐ๊ฐ ๋‹ค๋ฅธ ๋ฐ˜ํ™˜๊ฐ’์„ ๋‚ด๋ณด๋‚ด rc์— ์ €์žฅ๋œ๋‹ค. ๊ทธ๋ž˜์„œ Parent์˜ fork()์—๋Š” child์˜ pid ๊ฐ’์ด ๋ฐ˜ํ™˜๋˜๊ณ  Child๋Š” 0์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค.
Parent์™€ child์˜ fork ๊ฐ’์ด ๋‹ค๋ฅด๋‹ค๋Š” ์ ์€ ๋งค์šฐ ์œ ์šฉํ•œ ๋ฐฉ์‹์ด๋‹ค.

ํ•˜์ง€๋งŒ ์Šค์ผ€์ค„๋Ÿฌ๊ฐ€ ๋ถ€๋ชจ๋ฅผ ๋จผ์ € ์‹คํ–‰ํ• ์ง€ ์•„๋‹์ง€ ํ™•์‹ ํ•  ์ˆ˜ ์—†๊ธฐ ๋•Œ๋ฌธ์— ์ถœ๋ ฅ ๊ฒฐ๊ณผ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋‹ฌ๋ผ์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:

pid:29146
child (pid:29147)
parent of 29147 (pid:29146)

โณ Wait

wait()๋Š” ์ž์‹ ํ”„๋กœ์„ธ์Šค๊ฐ€ ์ข…๋ฃŒ๋  ๋•Œ๊นŒ์ง€ ๋ถ€๋ชจ ํ”„๋กœ์„ธ์Šค๊ฐ€ ๋ธ”๋ก ์ƒํƒœ๋กœ ๋Œ€๊ธฐํ•˜๊ฒŒ ๋งŒ๋“œ๋Š” ์ž‘์—…์ž…๋‹ˆ๋‹ค. ์ฆ‰, ์ž์‹ ํ”„๋กœ์„ธ์Šค๊ฐ€ ์ข…๋ฃŒ๋  ๋•Œ๊นŒ์ง€ ๋ถ€๋ชจ ํ”„๋กœ์„ธ์Šค๋Š” CPU ์ž์›์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ  ๋Œ€๊ธฐํ•ฉ๋‹ˆ๋‹ค.

์ž์‹ ํ”„๋กœ์„ธ์Šค๊ฐ€ ์ข…๋ฃŒ๋˜๋ฉด wait()๋Š” ์ข…๋ฃŒ๋œ ์ž์‹ ํ”„๋กœ์„ธ์Šค์˜ PID๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ์œ„์˜ ์˜ˆ์‹œ์— int wc = wait(NULL);์„ ์ถ”๊ฐ€ํ•˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ฝ”๋“œ๊ฐ€ ๋ฉ๋‹ˆ๋‹ค.

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>

int main(int argc, char *argv[]) {
    printf("pid : %d\n", (int) getpid()); // pid : 29146
    
    int rc = fork(); // ์ฃผ๋ชฉ
    
    if (rc < 0) { // (1) fork ์‹คํŒจ
        exit(1);
    }
    else if (rc == 0) { // (2) child์ธ ๊ฒฝ์šฐ (fork ๊ฐ’์ด 0)
        printf("child (pid : %d)\n", (int) getpid());
    }
    else { // (3) parent case
        int wc = wait(NULL); // ์ถ”๊ฐ€๋œ ๋ถ€๋ถ„
        printf("parent of %d (wc : %d / pid : %d)\n", wc, rc, (int)getpid());
    }
}

์œ„ ์ฝ”๋“œ์˜ ์‹คํ–‰ ๊ฒฐ๊ณผ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค:

pid:29146
child (pid:29147)
parent of 29147 (wc:29147 / pid:29146)

wait()๋ฅผ ํ†ตํ•ด ์ž์‹์˜ ์‹คํ–‰์ด ๋๋‚  ๋•Œ๊นŒ์ง€ ๋Œ€๊ธฐํ•จ์œผ๋กœ์จ, ๋ถ€๋ชจ๊ฐ€ ๋จผ์ € ์‹คํ–‰๋˜๋”๋ผ๋„ wait()๋Š” ์ž์‹์ด ์ข…๋ฃŒ๋˜๊ธฐ ์ „์—๋Š” ๋ฐ˜ํ™˜ํ•˜์ง€ ์•Š์œผ๋ฏ€๋กœ ๋ฐ˜๋“œ์‹œ ์ž์‹์ด ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค.

๐Ÿš€ Exec

exec()๋Š” ํ˜„์žฌ ํ”„๋กœ์„ธ์Šค์˜ ๋ฉ”๋ชจ๋ฆฌ ๊ณต๊ฐ„์„ ์ƒˆ๋กœ์šด ํ”„๋กœ๊ทธ๋žจ์œผ๋กœ ์™„์ „ํžˆ ๋ฎ์–ด์”Œ์šฐ๋Š” ์‹œ์Šคํ…œ ํ˜ธ์ถœ์ž…๋‹ˆ๋‹ค. ์ด ํ•จ์ˆ˜๊ฐ€ ํ˜ธ์ถœ๋˜๋ฉด ํ˜„์žฌ ํ”„๋กœ์„ธ์Šค์˜ ์ฝ”๋“œ, ๋ฐ์ดํ„ฐ, ํž™, ์Šคํƒ ๋“ฑ์ด ๋ชจ๋‘ ์ƒˆ๋กœ์šด ํ”„๋กœ๊ทธ๋žจ์œผ๋กœ ๋Œ€์ฒด๋ฉ๋‹ˆ๋‹ค.

์ค‘์š”ํ•œ ์ ์€ exec() ํ•จ์ˆ˜๊ฐ€ ์„ฑ๊ณต์ ์œผ๋กœ ํ˜ธ์ถœ๋˜๋ฉด ๊ธฐ์กด์˜ ํ”„๋กœ์„ธ์Šค ์ฝ”๋“œ๋Š” ๋” ์ด์ƒ ์‹คํ–‰๋˜์ง€ ์•Š์œผ๋ฉฐ, ์ฆ‰ exec() ์ดํ›„์˜ ์ฝ”๋“œ๋Š” ์‹คํ–‰๋˜์ง€ ์•Š๊ณ  ์ƒˆ๋กœ์šด ํ”„๋กœ๊ทธ๋žจ์ด ์‹œ์ž‘๋ฉ๋‹ˆ๋‹ค.

๋‹จ์ˆœ fork()๋Š” ๋™์ผํ•œ ํ”„๋กœ์„ธ์Šค์˜ ๋‚ด์šฉ์„ ์—ฌ๋Ÿฌ ๋ฒˆ ๋™์ž‘ํ•  ๋•Œ ์‚ฌ์šฉํ•˜๋ฉฐ, ์ž์‹ ํ”„๋กœ์„ธ์Šค์—์„œ ๋ถ€๋ชจ์™€ ๋‹ค๋ฅธ ๋™์ž‘์„ ํ•˜๊ณ  ์‹ถ์„ ๋•Œ๋Š” exec()๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. exec() ์ดํ›„์—๋Š” ์‹คํ–‰ํ•œ ํ”„๋กœ์„ธ์Šค๊ฐ€ ์ข…๋ฃŒ๋ฉ๋‹ˆ๋‹ค.

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>

int main(int argc, char *argv[]) {
    printf("pid : %d\n", (int) getpid()); // pid : 29146
    
    int rc = fork(); // ์ฃผ๋ชฉ
    
    if (rc < 0) { // (1) fork ์‹คํŒจ
        exit(1);
    }
    else if (rc == 0) { // (2) child์ธ ๊ฒฝ์šฐ (fork ๊ฐ’์ด 0)
        printf("child (pid : %d)\n", (int) getpid());
        char *myargs[3];
        myargs[0] = strdup("wc"); // ๋‚ด๊ฐ€ ์‹คํ–‰ํ•  ํŒŒ์ผ ์ด๋ฆ„
        myargs[1] = strdup("p3.c"); // ์‹คํ–‰ํ•  ํŒŒ์ผ์— ๋„˜๊ฒจ์ค„ argument
        myargs[2] = NULL; // end of array
        execvp(myargs[0], myargs); // wc ํŒŒ์ผ ์‹คํ–‰
        printf("this shouldn't print out\n"); // ์‹คํ–‰๋˜์ง€ ์•Š์Œ
    }
    else { // (3) parent case
        int wc = wait(NULL); // ์ถ”๊ฐ€๋œ ๋ถ€๋ถ„
        printf("parent of %d (wc : %d / pid : %d)\n", wc, rc, (int)getpid());
    }
}

exec()๊ฐ€ ์‹คํ–‰๋˜๋ฉด execvp(์‹คํ–‰ ํŒŒ์ผ, ์ „๋‹ฌ ์ธ์ž) ํ•จ์ˆ˜๋Š” ์ฝ”๋“œ ์„ธ๊ทธ๋จผํŠธ ์˜์—ญ์— ์‹คํ–‰ ํŒŒ์ผ์˜ ์ฝ”๋“œ๋ฅผ ์ฝ์–ด์™€์„œ ๋ฎ์–ด์”Œ์›๋‹ˆ๋‹ค.

์”Œ์šด ์ดํ›„์—๋Š” ํž™, ์Šคํƒ ๋ฐ ๋‹ค๋ฅธ ๋ฉ”๋ชจ๋ฆฌ ์˜์—ญ์ด ์ดˆ๊ธฐํ™”๋˜๊ณ , ์šด์˜์ฒด์ œ๋Š” ์ƒˆ๋กœ์šด ํ”„๋กœ๊ทธ๋žจ์„ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค. ์ฆ‰, ์ƒˆ๋กœ์šด ํ”„๋กœ์„ธ์Šค๋ฅผ ์ƒ์„ฑํ•˜์ง€ ์•Š๊ณ  ํ˜„์žฌ ํ”„๋กœ๊ทธ๋žจ์— wc๋ผ๋Š” ํŒŒ์ผ์„ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋กœ ์ธํ•ด execvp() ์ดํ›„์˜ ๋ถ€๋ถ„์€ ์‹คํ–‰๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

๊ฒฐ๋ก ์ ์œผ๋กœ, ์ž์‹ ํ”„๋กœ์„ธ์Šค๋Š” exec()๋ฅผ ํ˜ธ์ถœํ•˜๊ณ  ์‹คํ–‰ํ•˜๋Š” ์ˆœ๊ฐ„ ์ข…๋ฃŒ๋˜๋ฉฐ, ๋ถ€๋ชจ ํ”„๋กœ์„ธ์Šค๋Š” ์œ ์ง€๋˜๋‹ค๊ฐ€ wait()์„ ํ†ตํ•ด ์ž์‹์ด ์ข…๋ฃŒ๋œ ํ›„ ๊ทธ ์ดํ›„์˜ ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.


[1] velog - [์šด์˜์ฒด์ œ] ์‹œ์Šคํ…œ ์ฝœ๊ณผ ์ปค๋„ ๋ชจ๋“œ (https://velog.io/@wejaan/%EC%9A%B4%EC%98%81%EC%B2%B4%EC%A0%9C-%EC%8B%9C%EC%8A%A4%ED%85%9C-%EC%BD%9C)
[2][ํ•œ๋น›๋ฏธ๋””์–ด] ํ˜ผ๊ณตํ•™์Šต๋‹จ - [์šด์˜์ฒด์ œ๋ž€?] ์ปค๋„์˜ ๊ฐœ๋…, ์ด์ค‘ ๋ชจ๋“œ์™€ ์‹œ์Šคํ…œ ํ˜ธ์ถœ (https://hongong.hanbit.co.kr/%EC%9A%B4%EC%98%81%EC%B2%B4%EC%A0%9C%EB%9E%80-%EC%BB%A4%EB%84%90%EC%9D%98-%EA%B0%9C%EB%85%90-%EC%9D%91%EC%9A%A9-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%A8-%EC%8B%A4%ED%96%89%EC%9D%84-%EC%9C%84%ED%95%9C/)
[3] Medium - ์šด์˜์ฒด์ œ ์ปค๋„๋ชจ๋“œ์™€ ์‚ฌ์šฉ์ž ๋ชจ๋“œ ๋ฐ ์‹œ์Šคํ…œ ํ˜ธ์ถœ (https://medium.com/@su_bak/%EC%9A%B4%EC%98%81%EC%B2%B4%EC%A0%9C-%EC%BB%A4%EB%84%90%EB%AA%A8%EB%93%9C%EC%99%80-%EC%82%AC%EC%9A%A9%EC%9E%90-%EB%AA%A8%EB%93%9C-%EB%B0%8F-%EC%8B%9C%EC%8A%A4%ED%85%9C-%ED%98%B8%EC%B6%9C-3631d24636a6)
[4] ํ‹ฐ์Šคํ† ๋ฆฌ - [์šด์˜์ฒด์ œ] ์šด์˜์ฒด์ œ(OS), ์‹œ์Šคํ…œ ์ฝœ(System Call) (https://brightstarit.tistory.com/13)

0๊ฐœ์˜ ๋Œ“๊ธ€