๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
๐Ÿ’ป ์šด์˜์ฒด์ œ

[Linux] ํ”„๋กœ์„ธ์Šค ์‹ค์Šต (C++) (์šด์˜์ฒด์ œ๐Ÿฆ– ๊ฐ•์˜2-Chpater3. Process ํ”„๋กœ์„ธ์Šค ๊ฐ„ ํ†ต์‹  ์ด๋ก ๊ณผ ์‹ค์Šต)

by ๋ถˆํƒ€๋Š” ์ฐธ์ƒˆ 2025. 2. 22.

Process ํ”„๋กœ์„ธ์Šค ๊ฐ„ ํ†ต์‹  ์ด๋ก 

IPC: Inter-Process Communication

Cooperating ํ•˜๋Š” ํ”„๋กœ์„ธ์Šค๋“ค์€ IPC ๋ฉ”์ปค๋‹ˆ์ฆ˜(๋ฐ์ดํ„ฐ๋ฅผ ์ฃผ๊ณ  ๋ฐ›๋Š” ๊ฒƒ)์„ ํ†ตํ•ด ์„œ๋กœ ํ†ต์‹ ํ•จ

IPC์˜ ๋‘ ๊ฐ€์ง€ ๋ฐฉ๋ฒ•

  • ๋ฉ”๋ชจ๋ฆฌ ๊ณต์œ (a)
  • ๋ฉ”์‹œ์ง€ ์ „๋‹ฌ(b)

์ƒ์‚ฐ์ž ์†Œ๋น„์ž ๋ฌธ์ œ

์ƒ์‚ฐ์ž๋Š” ์ •๋ณด๋ฅผ ์ƒ์‚ฐ, ์†Œ๋น„์ž๋Š” ์ •๋ณด๋ฅผ ์†Œ๋น„ (์˜ˆ๋ฅผ ๋“ค์–ด ์›น ์„œ๋ฒ„๊ฐ€ HTML ํŒŒ์ผ์„ ์ƒ์‚ฐ, ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ์†Œ๋น„ ๋“ฑ)

shared-memory ํ†ตํ•œ ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•

  • ์ƒ์‚ฐ์ž์™€ ์†Œ๋น„์ž ๋™์‹œ์— ์‹คํ–‰, buffer๋ฅผ ์‚ฌ์šฉํ•ด ์ƒ์‚ฐ์ž๋ฅผ buffer๋ฅผ ์ฑ„์šฐ๊ณ , ์†Œ๋น„์ž๋Š” buffer๋ฅผ ๋น„์›€. buffer๊ฐ€ ๊ฐ€๋“ ์ฐจ๋ฉด wait, ๋น„์›Œ์ง€๋ฉด ์ฑ„์šฐ๊ธฐ ์‹œ์ž‘
  • ๋ฌธ์ œ์ : ํ”„๋กœ๊ทธ๋ž˜๋จธ๊ฐ€ ์•Œ์•„์„œ ์ฝ”๋“œ๋ฅผ ์งœ์„œ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ share ํ•ด์•ผ

Message-Passing

  • OS๊ฐ€ cooperating process๋“ค์„ ์œ„ํ•œ ์ˆ˜๋‹จ์„ ์ œ๊ณต
  • send(message), receive(messsage) ๋‘ ๊ฐœ์˜ system call๋งŒ ํ•„์š”
  • ์•„๋ž˜์™€ ๊ฐ™์€ ๋‹ค์–‘ํ•œ Message-Passing ๋ฐฉ๋ฒ• ์กด์žฌ
  1. ์ง์ ‘/๊ฐ„์ ‘
  • ์ง์ ‘ ์†Œํ†ต: ์ˆ˜๋ น์ž์™€ ๋ณด๋‚ด๋Š” ์ž์˜ ์ด๋ฆ„ ๋ช…ํ™•ํ•˜๊ฒŒ ์ œ์‹œ. ์ž๋™์ ์œผ๋กœ communication link ์ƒ์„ฑ. ํ•˜๋‚˜์˜ link๋งŒ ๋งŒ๋“ค์–ด์ง (ex: send(P, message), receive(Q, message)-P๊ฐ€ ๋ณด๋‚ด๊ณ  Q๊ฐ€ ๋ฐ›๊ณ )
  • ๊ฐ„์ ‘ ์†Œํ†ต: mailbox ๋˜๋Š” port๋กœ๋ถ€ํ„ฐ ๋ฉ”์‹œ์ง€ ๋ณด๋‚ด๊ณ  ๋ฐ›์Œ. ํ•œ ์Œ์˜ process๋“ค ์‚ฌ์ด์—์„œ link ๋งŒ๋“ค์–ด์ง. ๋‘ ๊ฐœ ์ด์ƒ์˜ process๋“ค ์‚ฌ์ด์—์„œ link๊ฐ€ ์กด์žฌํ•  ์ˆ˜ ์žˆ์Œ. O/S๊ฐ€ mailbox ์ƒ์„ฑ/message ์ „์†ก,์ „๋‹ฌ/mailbox ์‚ญ์ œ ์ œ๊ณตํ•˜๋ฉด ๋จ (ex: send(A, message), receive(A, message)-๋ฉ”์ผ ๋ฐ•์Šค์— ๋ณด๋‚ด๊ณ  ๋ฉ”์ผ ๋ฐ•์Šค๋กœ๋ถ€ํ„ฐ ๋ฐ›๊ณ )
  1. ๋™๊ธฐํ™”(synchronous)/๋น„๋™๊ธฐํ™”(asynchronous)
  • Blocking send: ๋ฉ”์‹œ์ง€๋ฅผ ๋ฐ›์„ ๋•Œ๊นŒ์ง€ sender๊ฐ€ block ๋˜์–ด ์žˆ์Œ
  • Non-blocking send: ๋ฉ”์‹œ์ง€๋ฅผ ๋ณด๋‚ด๊ณ  ํ•˜๋˜ ์ผ ํ•จ
  • Blocking receive: ๋ฉ”์‹œ์ง€ ๋ฐ›์„ ๋•Œ๊นŒ์ง€ receiver๊ฐ€ block ๋˜์–ด ์žˆ์Œ
  • Non-blocking receive: ๊ฐ€๋Šฅํ•œ ๋ฉ”์‹œ์ง€๋ฅผ ๋ฐ›๊ฑฐ๋‚˜ ์•„๋ฌด ๋ฉ”์‹œ์ง€๋„ ๋ฐ›์ง€ ์•Š๊ฑฐ๋‚˜ ๋‘˜ ์ค‘์— ํ•˜๋‚˜.๋™๊ธฐํ™”: Blocking, ๋‹ค ๋ณด๋‚ด๊ณ  ๋‹ค ๋ฐ›์„ ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ฆผ
    ๋น„๋™๊ธฐํ™”: Non-blocking, ๋‹ค ๋ฐ›์•˜๋Š”์ง€ ํ™•์‹ ํ•  ์ˆ˜ ์—†์Œ. ์ผ๋‹จ ์ž๊ธฐ ์ผ ํ•จ
  1. ๊ทธ ์™ธ์—๋„ ์ž๋™/๋ช…์‹œ์  ๋ฒ„ํผ๋ง ๋“ฑ ๋‹ค์–‘ํ•œ ๋ฐฉ๋ฒ• ์กด์žฌ

ํ”„๋กœ์„ธ์Šค ๊ฐ„ ํ†ต์‹  ์‹ค์Šต

Shared Memory: POSIX Shared Memory

POSIX Shared Memory๋ž€

POSIX๋Š” Portavle Operating System Interface(for Unix)์˜ ์•ฝ์ž. meomoru-mapped file์„ ์ด์šฉํ•ด์„œ Shared Memory ์˜์—ญ์„ ๋งŒ๋“ฆ.

POSIX Shared Memory์˜ Producer ๊ตฌํ˜„

Shared Memory ๊ณต๊ฐ„์„ ๋งŒ๋“ค๊ณ  ๊ฑฐ๊ธฐ์— ๋ฉ”์‹œ์ง€๋ฅผ ์ž‘์„ฑํ•˜๋Š” ์ฝ”๋“œ

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <sys/shm.h>
#include <sys/stat.h>
#include <sys/mman.h>

int main()
{
    const int SIZE = 4096;
    const char *name = "OS";
    const char *message_0 = "Hello";
    const char *message_1 = "Shared Memory!\n";

    int shm_fd; //file discreptor
    char *ptr;

    /*shared memory ์ƒ์„ฑ*/
    shm_fd = shm_open(name, O_CREAT | O_RDWR, 0666);
    
    /*shared memory ์‚ฌ์ด์ฆˆ ๊ตฌ์„ฑ*/
    ftruncate(shm_fd, SIZE);

    /*map the shared memory object*/
    ptr = (char *)mmap(0, SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0);

    /*write to the shared memory*/
    sprintf(ptr, "%s", message_0);
    ptr += strlen(message_0);
    sprintf(ptr, "%s", message_1);
    ptr += strlen(message_1);

    return 0;
}

 

๐Ÿ“Œ์ฝ”๋“œ ์„ค๋ช…

 

(1) ๊ณต์œ  ๋ฉ”๋ชจ๋ฆฌ ๊ฐ์ฒด ์ƒ์„ฑ

shm_fd = shm_open(name, O_CREAT | O_RDWR, 0666);

  • shm_open(name, flags, mode)๋ฅผ ์ด์šฉํ•ด์„œ ๊ณต์œ  ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ๋งŒ๋“ฆ.
    -name์€ ๊ณต์œ  ๋ฉ”๋ชจ๋ฆฌ์˜ ์‹๋ณ„์ž ์—ญํ• ์„ ํ•จ ("OS"๋ผ๋Š” ์ด๋ฆ„ ์‚ฌ์šฉ).
  • O_CREAT | O_RDWR: ๊ณต์œ  ๋ฉ”๋ชจ๋ฆฌ๊ฐ€ ์—†์œผ๋ฉด ์ƒˆ๋กœ ๋งŒ๋“ค๊ณ , ์ฝ๊ธฐ/์“ฐ๊ธฐ ๋ชจ๋“œ(O_RDWR)๋กœ ์—ผ.
  • 0666: ํŒŒ์ผ ๊ถŒํ•œ์„ ์„ค์ • (์ฝ๊ธฐ/์“ฐ๊ธฐ ํ—ˆ์šฉ).

 

(2) ๊ณต์œ  ๋ฉ”๋ชจ๋ฆฌ ํฌ๊ธฐ ์ƒ์„ฑ

ftruncate(shm_fd, SIZE);

  • ๊ณต์œ  ๋ฉ”๋ชจ๋ฆฌ ํฌ๊ธฐ๋ฅผ SIZE = 4096 (4KB)๋กœ ์„ค์ •.
  • ์ƒ์„ฑ๋œ ๋ฉ”๋ชจ๋ฆฌ์˜ ํฌ๊ธฐ๋ฅผ ftruncate()๋กœ ๋ณ€๊ฒฝํ•˜์ง€ ์•Š์œผ๋ฉด ๊ธฐ๋ณธ๊ฐ’ 0๋ฐ”์ดํŠธ๋ผ ์“ธ ์ˆ˜ ์—†์Œ.

 

(3) ๊ณต์œ  ๋ฉ”๋ชจ๋ฆฌ ๋งคํ•‘

ptr = (char *)mmap(0, SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0);

  • PROT_READ | PROT_WRITE: ์ฝ๊ธฐ/์“ฐ๊ธฐ ๊ฐ€๋Šฅ.
  • MAP_SHARED: ๋‹ค๋ฅธ ํ”„๋กœ์„ธ์Šค์™€ ๊ณต์œ  ๊ฐ€๋Šฅ.
    (๐Ÿค”๋งคํ•‘ ๋ถ€๋ถ„์ด ์ข€ ์•„๋ฆฌ์†ก ํ•ด์„œ ์ฐพ์•„๋ณธ ๊ฐ ์ธ์ž์˜ ๊ตฌ์ฒด์  ์—ญํ• ...์ฐธ๊ณ  ๋ฐ”๋žŒ)

 

(4) ๊ณต์œ  ๋ฉ”๋ชจ๋ฆฌ์— ๋ฐ์ดํ„ฐ ์“ฐ๊ธฐ

sprintf(ptr, "%s", message_0); ptr += strlen(message_0); sprintf(ptr, "%s", message_1); ptr += strlen(message_1);

  • sprintf(ptr, "%s", message_0);: "Hello" ์ €์žฅ.
  • ptr += strlen(message_0): ํฌ์ธํ„ฐ ์ด๋™.
  • sprintf(ptr, "%s", message_1);: "Shared Memory!\n" ์ €์žฅ.

POSIX Shared Memory์˜ Consumer ๊ตฌํ˜„

์ž‘์„ฑ๋œ Shared Memory์˜ ๋ฌธ์ž์—ด์„ ์ฝ๋Š” Consumer ๊ตฌํ˜„ ์ฝ”๋“œ

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <sys/shm.h>
#include <sys/stat.h>
#include <sys/mman.h>

int main()
{
    const int SIZE = 4096;
    const char *name = "OS";
    const char *message_0 = "Hello";
    const char *message_1 = "Shared Memory!\n";

    int shm_fd; //file discreptor
    char *ptr;

    /*shared memory ์ƒ์„ฑ*/
    shm_fd = shm_open(name, O_RDONLY, 0666);

    /*map the shared memory object*/
    ptr = (char *)mmap(0, SIZE, PROT_READ, MAP_SHARED, shm_fd, 0);

    /*read from the shared memory*/
    printf("%s", (char *)ptr);

    /*remove the shared memory*/
    shm_unlink(name);

    return 0;
}

๐Ÿ“Œ ์ฝ”๋“œ ์„ค๋ช…

(1) ๊ณต์œ  ๋ฉ”๋ชจ๋ฆฌ ์—ด๊ธฐ

shm_fd = shm_open(name, O_RDONLY, 0666);;

  • shm_open("OS", O_RDONLY, 0666);๋ฅผ ์ด์šฉํ•ด์„œ ์ด๋ฏธ ์กด์žฌํ•˜๋Š” ๊ณต์œ  ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์ฝ๊ธฐ ๋ชจ๋“œ๋กœ ์—ผ.

 

(2) ๊ณต์œ  ๋ฉ”๋ชจ๋ฆฌ ๋งคํ•‘

ptr = (char *)mmap(0, SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0);

  • mmap()์„ ์‚ฌ์šฉํ•ด ํ”„๋กœ์„ธ์Šค์˜ ๋ฉ”๋ชจ๋ฆฌ์— ๊ณต์œ  ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ๋งคํ•‘.

 

(3) ๊ณต์œ  ๋ฉ”๋ชจ๋ฆฌ ๋ฐ์ดํ„ฐ ์ถœ๋ ฅ

printf("%s", (char *)ptr);

  • ๊ณต์œ  ๋ฉ”๋ชจ๋ฆฌ์— ์ €์žฅ๋œ ๋ฌธ์ž์—ด์„ ์ฝ์–ด์„œ ์ถœ๋ ฅ.

 

(4) ๊ณต์œ  ๋ฉ”๋ชจ๋ฆฌ ์‚ญ์ œ

shm_unlink(name);

  • shm_unlink("OS");๋ฅผ ํ˜ธ์ถœํ•ด์„œ ๊ณต์œ  ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์ œ๊ฑฐ.
  • ๊ณต์œ  ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์ œ๊ฑฐํ•˜์ง€ ์•Š์œผ๋ฉด, ํ”„๋กœ์„ธ์Šค๊ฐ€ ์ข…๋ฃŒ๋˜์–ด๋„ ๋‚จ์•„ ์žˆ์„ ์ˆ˜ ์žˆ์Œ.

cf) ์ฐธ๊ณ ๋กœ ์ฝ”๋“œ ์‹คํ–‰์€ gcc [producer ํŒŒ์ผ ์ด๋ฆ„.c] -lrt-> ./a.out-> gcc [consumer ํŒŒ์ผ ์ด๋ฆ„.c] -lrt-> ./a.out ํ•ด์ฃผ๋ฉด ์ž‘์„ฑํ•œ ๋ฌธ์ž์—ด์ด ์ถœ๋ ฅ๋œ๋‹ค.

Message Passing: Pipes

Pipes๋ž€

UNIX์—์„œ ์•„์ฃผ ์ดˆ์ฐฝ๊ธฐ์— ์‚ฌ์šฉํ•˜๋˜ ๋งค์ปค๋‹ˆ์ฆ˜. shared-memory์—์„œ ๋งŒ๋“ค๊ณ , ์“ฐ๊ณ , ์ฝ๊ณ , ์‚ญ์ œํ•˜๋Š” ๊ท€์ฐฎ์€ ๊ณผ์ •์— ๋Œ€ํ•œ ํ•ด๊ฒฐ์ฑ…. ์ผ๋ฐฉํ–ฅ. ๋„คํŠธ์›Œํฌ์—์„œ๋Š” ์‚ฌ์šฉํ•˜์ง€ ์•Š์Œ. ๋„คํŠธ์›Œํฌ์—์„œ๋Š” ๋Œ€์‹  socket ์‚ฌ์šฉ. Ordinary pipes, Named pipes๊ฐ€ ์žˆ์Œ. Ordinary pipes์—๋งŒ parent์™€ child ์—ญํ•  ์žˆ์œผ๋ฉฐ ์ด๋ฒˆ ์‹ค์Šต๋„ Ordinary ๋ฒ„์ „. ๋‘ ๊ฐœ์˜ pipe์ด ํ•„์š”. Parent์—์„œ Child, Child์—์„œ Parent.
๋‘ ๊ฐœ์˜ ํŒŒ์ดํ”„ pipe(int fd[])

  • fd[0]: ์ฝ๋Š” ๊ธฐ๋Šฅ์„ ๊ฐ€์ง„ ํŒŒ์ดํ”„
  • fd[1]: ์“ฐ๋Š” ๊ธฐ๋Šฅ์„ ๊ฐ€์ง„ ํŒŒ์ดํ”„

Pipes ๊ตฌํ˜„

Pipe๋ฅผ ํ†ตํ•ด ํ”„๋กœ์„ธ์Šค๋“ค์ด "read Greeting"์„ ์ ๊ณ  ์ฝ๋Š” ์ฝ”๋“œ ๊ตฌํ˜„

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

#define BUFFER_SIZE 25
#define READ_END 0
#define WRITE_END 1

int main()
{
    char write_msg[BUFFER_SIZE] = "Greetings";
    char read_msg[BUFFER_SIZE];
    int fd[2];
    pid_t pid;

    /*ํŒŒ์ดํ”„ ์ƒ์„ฑ*/
    pipe(fd);
    
    pid = fork();

    if (pid > 0) { //๋ถ€๋ชจ ํ”„๋กœ์„ธ์Šค์Šค
        close(fd[READ_END]);
        /*ํŒŒ์ดํ”„์— ์“ฐ๊ธฐ*/
        write(fd[WRITE_END], write_msg, strlen(write_msg) +1);
        close(fd[WRITE_END]);
    }
    else if (pid == 0) { //์ž์‹ ํ”„๋กœ์„ธ์Šค์Šค
        close(fd[WRITE_END]);
        /*ํŒŒ์ดํ”„ ์ฝ๊ธฐ*/
        read(fd[READ_END], read_msg, BUFFER_SIZE);
        printf("read %s\n", read_msg);
        close(fd[READ_END]);
    }

    return 0;
}

๐Ÿ“Œ ์ฝ”๋“œ ์„ค๋ช…

(1) ํŒŒ์ดํ”„ ์ƒ์„ฑ

pipe(fd);

  • fd[0]: ํŒŒ์ดํ”„์˜ ์ฝ๊ธฐ(read) ๋
  • fd[1]: ํŒŒ์ดํ”„์˜ ์“ฐ๊ธฐ(write) ๋
  • pipe()๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด ๋‘ ๊ฐœ์˜ ํŒŒ์ผ ๋””์Šคํฌ๋ฆฝํ„ฐ(fd ๋ฐฐ์—ด)๊ฐ€ ์ƒ์„ฑ๋จ

(2) ํ”„๋กœ์„ธ์Šค ์ƒ์„ฑ fork()

  • fork()๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ ๋ถ€๋ชจ์™€ ์ž์‹ ํ”„๋กœ์„ธ์Šค๋ฅผ ์ƒ์„ฑ
  • ๋ถ€๋ชจ ํ”„๋กœ์„ธ์Šค์™€ ์ž์‹ ํ”„๋กœ์„ธ์Šค๋Š” ๋™์ผํ•œ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ๋ณต์ œํ•˜์—ฌ ์‹คํ–‰๋˜์ง€๋งŒ, ๊ฐ๊ฐ ๋…๋ฆฝ์ ์ธ ์‹คํ–‰ ํ๋ฆ„์„ ๊ฐ€์ง

(3) ๋ถ€๋ชจ ํ”„๋กœ์„ธ์Šค (๋ฐ์ดํ„ฐ ์“ฐ๊ธฐ)

  • close(fd[READ_END]); ๋ถ€๋ชจ ํ”„๋กœ์„ธ์Šค๋Š” ์“ฐ๊ธฐ ์ „์šฉ์ด๋ฏ€๋กœ, ์ฝ๊ธฐ ๋์„ ๋‹ซ์Œ.
  • write(fd[WRITE_END], write_msg, strlen(write_msg) + 1); "Greetings" ๋ฌธ์ž์—ด์„ ํŒŒ์ดํ”„์— ์”€ (+1์€ ๋ฌธ์ž์—ด ์ข…๋ฃŒ ๋ฌธ์ž \0 ํฌํ•จ)
  • close(fd[READ_WRITE_END]); ๋ฐ์ดํ„ฐ๋ฅผ ๋‹ค ์ผ์œผ๋ฉด ํŒŒ์ดํ”„ ๋‹ซ๊ธฐ

(4) ์ž์‹ ํ”„๋กœ์„ธ์Šค (๋ฐ์ดํ„ฐ ์ฝ๊ธฐ)

  • close(fd[WRITE_END]); ์ž์‹ ํ”„๋กœ์„ธ์Šค๋Š” ์ฝ๊ธฐ ์ „์šฉ์ด๋ฏ€๋กœ, ์“ฐ๊ธฐ ๋์„ ๋‹ซ์Œ.
  • read(fd[READ_END], read_msg, BUFFER_SIZE); ๋ถ€๋ชจ ํ”„๋กœ์„ธ์Šค๊ฐ€ ๋ณด๋‚ธ "Greetings"์„ ์ฝ์–ด read_msg์— ์ €์žฅ
  • close(fd[READ_END]); ๋ฐ์ดํ„ฐ๋ฅผ ๋‹ค ์ฝ์—ˆ์œผ๋ฉด ํŒŒ์ดํ”„ ๋‹ซ๊ธฐ