ํ‹ฐ์Šคํ† ๋ฆฌ ๋ทฐ

728x90
๋ฐ˜์‘ํ˜•
IPC(Inter-Process Cmmuniciation)๋Š” ํ”„๋กœ์„ธ์Šค๋“ค ์‚ฌ์ด์— ๋ฐ์ดํ„ฐ๋ฅผ ์ฃผ๊ณ ๋ฐ›๋Š” ํ–‰์œ„, ๊ทธ์— ๋Œ€ํ•œ ๋ฐฉ๋ฒ• ๋˜๋Š” ๊ฒฝ๋กœ๋ฅผ ์˜๋ฏธํ•œ๋‹ค.

 

pipe์˜ ์ข…๋ฅ˜

pipe vs named pipe

 pipe๋Š” ์œ„์˜ ๊ทธ๋ฆผ๊ณผ ๊ฐ™์ด ํ”„๋กœ์„ธ์Šค์— ๋”ฐ๋ผ write, read๋ฅผ ํ•  ์ˆ˜ ์žˆ๋‹ค. ๋˜ํ•œ ๊ด€๋ จ๋œ ํ”„๋กœ์„ธ์Šค๊ฐ€ ์‚ฌ์šฉํ•˜๋Š” pipe์™€ ๊ด€๋ จ ์—†๋Š” ํ”„๋กœ์„ธ์Šค ๊ฐ„์—๋„ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ named pipe๋กœ ๋‚˜๋‰œ๋‹ค.

 

pipe

int process_pipe(pid_t pid, int *pipe_p, char *buf)
{
    int status;
    
    if (pid == 0) {
    	/* child process */
        close(pipe_p[1]);
        read(pipe_p[0], buf, sizeof(buf));
        printf("%d get msg %s\n", pid, buf);
        close(pipe_p[0]);
        return 0;
    } else if (pid > 0) {
    	/* parent process */
        close(pipe_p[0]);
        strncpy(buf, "input some data...", sizeof(buf) - 1);
        printf("%d send msg %s\n", pid, buf);
        write(pipe_p[1], buf, strlen(buf));
        close(pipe_p[1]);
        pid = wait(&status);
        return 0;
    }
    
    return -1;
}
  •  pipe ๋””์Šคํฌ๋ฆฝํ„ฐ 0๋ฒˆ์€ read, 1๋ฒˆ์€ write์ด๋‹ค.
  • ์œ„์˜ ์˜ˆ์‹œ๋Š” ๋ถ€๋ชจ ํ”„๋กœ์„ธ์˜ ๊ฒฝ์šฐ write๋ฅผ ํ•˜๊ณ , ์ž์‹ ํ”„๋กœ์„ธ์Šค๋Š” read๋ฅผ ํ•œ๋‹ค.
  • ์—ฐ๊ด€๋œ ํ”„๋กœ์„ธ์Šค, ์ฆ‰ pipe ๋””์Šคํฌ๋ฆฝํ„ฐ๋ฅผ ์•Œ๊ณ  ์žˆ๋Š” ํ”„๋กœ์„ธ์Šค ๋ผ๋ฆฌ ์ƒํ˜ธ ๊ฐ„์˜ ์ •๋ณด๋ฅผ ๊ตํ™˜ํ•  ์ˆ˜ ์žˆ๋‹ค.

 

named pipe

#define FILENAME	"./test"

static int reader()
{
    int fd;
    char buf[128];
    
    unlink(FILENAME);
    
    fd = open(FILENAME, O_RDONLY);
    
    if (fd < 0) {
    	perror("open()");
        return -1;
    }
    
    read(fd, buf, sizeof(buf));
    close(fd);
    
    return 0;
}

static int writer()
{
    int fd;
    char buf[128];
    
    unlink(FILENMAE);
    
    if (mkfifo(FILENAME, 0644)) {
    	perror("mkfifo()");
        return -1;
    }
    
    fd = open(FILENAME, O_WRONLY);
    
    if (fd < 0) {
    	perror("open()");
        return -1;
    }
    
    strcpy(buf, "test write", sizeof(buf));
    write(fd, buf, strlen(buf));
    close(fd);
    
    return 0;
}

named pipe๋Š” ํŒŒ์ผ์— ์ ‘๊ทผ ๊ฐ€๋Šฅํ•œ ๊ฒฝ์šฐ, ํ”„๋กœ์„ธ์Šค ๊ฐ„์˜ ์ •๋ณด๋ฅผ ๊ณต์œ ํ•  ์ˆ˜ ์žˆ๋‹ค. ์ฃผ์˜ํ•  ์ ์€ open์— O_NONBLOCK flag๋ฅผ ์„ค์ •ํ•˜์ง€ ์•Š์œผ๋ฉด, ์–‘๋ฐฉํ–ฅ(read/write)์œผ๋กœ ์—ด๋ฆด ๋•Œ blocking ๋œ๋‹ค๋Š” ์ ์ด๋‹ค.

 

Message Queue

๋ฉ”์‹œ์ง€ ํ๋Š” ์œ„ ํ‘œ์™€ ๊ฐ™์ด SysV์™€ POSIX ๋ฐฉ์‹์œผ๋กœ ๋‚˜๋‰œ๋‹ค.

  • POSIX ๋ฐฉ์‹์€ File I/O ๊ธฐ๋ฐ˜์œผ๋กœ ๋™์ž‘ํ•˜๋ฏ€๋กœ, I/O Multiplexing์ด ๊ฐ€๋Šฅํ•˜๋‹ค.
  • SysV๋Š” ๋ฉ”์‹œ์ง€ ํƒ€์ž…์„ ๊ตฌ๋ถ„ํ•˜๋ฏ€๋กœ, ํ•˜๋‚˜์˜ write์™€ ๋‹ค์ˆ˜์˜ reader๋กœ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•˜๋‹ค.
  • pipe์™€ ๋‹ฌ๋ฆฌ byte stream์ด ์•„๋‹Œ ๋ฉ”์‹œ์ง€ ๋‹จ์œ„๋กœ ์ฒ˜๋ฆฌ ๋œ๋‹ค.
  • FIFO๋กœ ์ฒ˜๋ฆฌ๋˜๋ฉฐ, MQ์— ์ ‘๊ทผ ๊ฐ€๋Šฅํ•˜๋‹ค๋ฉด ์—ฐ๊ด€์ด ์—†๋Š” ํ”„๋กœ์„ธ์Šค๋„ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•˜๋‹ค.

 

#define MQ_NAME "/test_mq"
// MQ ์ด๋ฆ„์€ /๋กœ ์‹œ์ž‘ํ•˜์—ฌ์•ผ ํ•จ.
#define BUF_SIZE 8192
 
static int init_mq()
{
    mqd_t mqd;
    struct mq_attr attr;
 
    mqd = mq_open(MQ_NAME, O_RDWR | O_CREAT, 0644, NULL);
 
    if (mqd == -1) {
        perror("mq_open()");
        return -1;
    }
 
    memset(&attr, 0, sizeof(attr));
    if (mq_getattr(mqd, &attr) == -1) {
        close(mqd);
        return -1;
    }
 
    return mqd;
}
 
static int sender()
{
    int mqd = init_mq();
    char buf[BUF_SIZE];
 
    if (mqd == -1) {
        perror("init_mq()");
        return -1;
    }
 
    memset(buf, 0, sizeof(buf));
    sprintf(buf, sizeof(buf), "TEST...");
 
    if (mq_send(mqd, buf, sizeof(buf), 0) == -1) {
        perror("sender()");
        return -1;
    }
 
    return 0;
}
 
static int receiver()
{
    int mqd;
    char buf[BUF_SIZE];
 
    mqd = init_mq();
     
    if(mqd == -1) {
        perror("init_mq()");
        return -1;
    }
 
    memset(buf, 0, sizeof(buf));
     
    if (mq_receive(mqd, buf, sizeof(buf), NULL) == -1) {
        perror("receiver()");
        return -1;
    }
 
    printf("recv msg %s\n", buf);
 
    return 0;
}

POSIX MQ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ์‹์„ ๊ฐ„๋‹จํžˆ ๊ตฌํ˜„ํ•˜๋ฉด ์œ„์™€ ๊ฐ™๋‹ค.

  • MQ ๊ด€๋ฆฌ์— ๊ด€๋ จ๋œ ํ•จ์ˆ˜๋Š” mq_open, mq_close, mq_unlink๊ฐ€ ์žˆ๋‹ค.
  • ์†ก์ˆ˜์‹ ์„ ์œ„ํ•ด์„œ๋Š” mq_send, mq_receive๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.
  • ์ด ์™ธ์— mq_setarr, mq_getarr, mq_notify๊ฐ€ ์žˆ๋‹ค.
  • mq_open, mq_send, mq_receive๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” struct mq_attr์„ ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ์‚ฌ์šฉํ•œ๋‹ค.
  • ๋งŒ์•ฝ MQ์— ๋‚ด์šฉ์ด ์—†๋Š”๋ฐ receive๋ฅผ ํ•˜๊ฒŒ ๋˜๋ฉด blocking ๋œ๋‹ค.
  • ์‚ฌ์šฉ๋˜๋Š” MQ๋Š” `/dev/mqueue`์˜ ํ•˜์œ„ ๋””๋ ‰ํ† ๋ฆฌ์— ์ƒ์„ฑ๋œ๋‹ค.

 

Socket

 ๋„๋ฉ”์ธ์„ ํ†ตํ•ด ์†Œ์ผ“์„ ๊ตฌ๋ถ„ํ•˜๋ฉฐ, 3๊ฐ€์ง€๋กœ ์ •์˜ํ•  ์ˆ˜ ์žˆ๋‹ค.

  1. Unix Domain Socket
    • Host-only socket
    • file path๋ฅผ address๋กœ ์‚ฌ์šฉํ•œ๋‹ค.
  2. IPv4 Socket
  3. IPv6 Socket

 

Socket type

  Socket์˜ ํƒ€์ž…์€ 2๊ฐ€์ง€๋กœ ๊ตฌ๋ถ„๋œ๋‹ค.

  • Stream
    • ์–‘๋ฐฉํ–ฅ์œผ๋กœ ์—ฐ๊ฒฐ(Connect-Orient)๋˜์–ด์•ผ ํ•œ๋‹ค.
    • ์ „์†ก ๋‹จ์œ„๋Š” byte stream์ด๋‹ค.
    • TCP์˜ ํŠน์„ฑ์„ ๊ฐ€์ง„๋‹ค๊ณ  ์ƒ๊ฐํ•˜๋ฉด ๋œ๋‹ค.
    • ๊ทธ๋ฆผ ์ƒ์—์„œ ๋ณด๋ฉด Socket ์ƒ์„ฑ ํ›„, ์—ฐ๊ฒฐ ๊ณผ์ •์ด ํ•„์š”ํ•˜๋‹ค.
  • Datagram
    • ์ƒํ˜ธ ์—ฐ๊ฒฐ(Connectionless)๋˜์ง€ ์•Š์•„๋„ ๋œ๋‹ค.
    • ์ „์†ก ๋‹จ์œ„๋Š” Message์ด๋‹ค.
    • UDP์˜ ํŠน์„ฑ์„ ๊ฐ€์ง„๋‹ค๊ณ  ์ƒ๊ฐํ•˜๋ฉด ๋œ๋‹ค.
    • ๊ทธ๋ฆผ ์ƒ์—์„œ ๋ณด๋ฉด, Socket ์ƒ์„ฑ ํ›„, ๋ณ„๋„์˜ ์—ฐ๊ฒฐ ๊ณผ์ •์ด ํ•„์š” ์—†๋‹ค.

 

Server side

// Socket(Stream) Server Side
#define SOCK_PATH "test"
 
int receiver(int sock, void *buf, size_t buflen, int flag)
{
    int ret;
    int cur_read = 0;
 
    while (cur_read < buflen) {
        ret = recv(sock, (char *)buf + cur_read, buflen, flag);
 
        if (ret == -1) {
            return ret;
        }
 
        cur_read += ret;
    }
 
    return 0;
}
 
static int server()
{
    int sock;
    int peer;
    int ret;
    struct sockaddr_un addr;
    char buf[1024];
 
    sock = socket(AF_UNIX, SOCK_STREAM, 0);
 
    if (sock == -1) {
        perror("socket()");
        return -1;
    }
 
    /* addr init */
    memset(&addr, 0, sizeof(addr));
    addr.sun_familiy = AF_UNIX;
    strncpy(addr.sun_path, SOCK_PATH, sizeof(addr.sun_path) - 1);
 
    if bind(sock, (struct sockaddr *)&addr, sizeof(struct sockaddr_un) == -1) {
        perror("bind()");
        goto err;
    }
 
    listen(sock, 3);
 
    peer = accept(sock, NULL, NULL);
    if (peer < 0) {
        perror("accept()");
        goto err;
    }
 
    ret = receiver(peer, buf, sizeof(buf), 0);
 
    if (ret == -1) {
        perror("recv()");
        goto err;
    }
 
    printf("from to client %s\n", buf);
 
    close(sock);
     
    return 0;
 
err:
    close(sock);
    return -1;
}

 

Host side

// Socket(Stream) Client Side
#define SOCKET_PATH "test"
 
int sender(int sock, void *buf, size_t buflen, int flag)
{
    int ret;
    int cur_write = 0;
     
    while (cur_write < buflen) {
        ret = send(sock, (char *)buf + cur_write, buflen, flag);
 
        if (ret == -1) {
            return ret;
        }
 
        cur_write += ret;
    }  
 
    return 0;
 
}
 
static int client()
{
    int sock;
    int ret;
    char buf[64];
    struct sockaddr_un addr;
 
    sock = socket(AF_UNIX, SOCK_STREAM, 0);
    if (sock < 0) {
        perror("socket()");
        return -1;
    }  
 
    /* addr init */
    memset(&addr, 0, sizeof(addr));
    addr.sun_family = AF_UNIX;
    strncpy(addr.sun_path, SOCK_PATH, sizeof(addr.sun_path) - 1);
 
    if (connect(sock, (struct sockaddr *)&addr, sizeof(struct sockaddr_un)) == -1) {
        perror("connect()");
        goto err;
    }  
 
    memset(buf, 0, sizeof(buf));
    sprintf(buf, sizeof(buf), "Send TEST..");
    ret = sender(sock, buf, sizeof(buf), 0);
 
    if (ret < 0) {
        perror("send()");
        goto err;
    }  
 
    close(sock);
 
    return 0;
 
err:
    close(sock);
    return -1;
}

 

Shared Memory

pipe, MQ, Socket์€ ๋ฐ์ดํ„ฐ๋ฅผ ์ „๋‹ฌํ•˜์—ฌ ํ”„๋กœ์„ธ์Šค ๊ฐ„์˜ ์ •๋ณด๋ฅผ ์ฃผ๊ณ ๋ฐ›๋Š” ํ˜•์‹์ด๋‹ค. ์ด์™€ ๋‹ฌ๋ฆฌ SHM์€ ํ”„๋กœ์„ธ์Šค ๊ฐ„ ๋ฉ”๋ชจ๋ฆฌ ์˜์—ญ์„ ๊ณต์œ ํ•˜์—ฌ ๋ฐ์ดํ„ฐ๋ฅผ ์ฃผ๊ณ ๋ฐ›๋Š”๋‹ค.

 

file mapping

#define FILE_NAME "test"
 
static int prosumer()
{
    int fd;
    int *maped;
    int i;
     
    fd = open(FILE_NAME, O_RDWR | O_CREATE, 0644);
     
    if (fd == -1) {
        perror("open()");
        return -1;
    }
     
    // ํŒŒ์ผ์„ ์ƒ์„ฑํ•˜์—ฌ์•ผ ํ•˜๋ฏ€๋กœ fruncate๋ฅผ ํ˜ธ์ถœ.
    if (ftruncate(fd, 4096) == -1) {
        perror("fruncate()");
        goto err;
    }
     
    maped = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
     
    if (maped == MAP_FAILED) {
        perror("mmap()");
        goto err;
    }
     
    for (i = 0; i < 100; i++) {
        maped[i] = i + 1;
    }
     
    munmap(maped, 4096);
    close(fd);
    
    return 0;
err:
    close(fd);
    return -1;
}
#define FILE_NAME "test"
 
static int consumer()
{
    int fd;
    int maped;
    int i;
     
    fd = open(FILE_NAME, O_RDWR);
     
    if (fd == -1) {
        perror("open()");
        return -1;
    }
     
    maped = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
     
    if (maped == MAP_FAILED) {
        perror("mmap()");
        close(fd);
        return -1;
    }
     
   for (i = 0; i < 100; i++) {
        printf("%d\n", maped[i]);
    }
     
    munmap(maped, 4096);
    close(fd);
}

 ์œ„์˜ ์ฝ”๋“œ๋Š” mmap์„ ํ†ตํ•ด ๋™์ผํ•œ ํŒŒ์ผ์„ 2๊ฐœ์˜ ํ”„๋กœ์„ธ์Šค์˜ ๋ฉ”๋ชจ๋ฆฌ ๊ณต๊ฐ„์— ํ• ๋‹นํ•˜๋Š” ๊ฒƒ์ด๋‹ค.

  • prosumer
    • ํŒŒ์ผ์„ ์ƒ์„ฑํ•˜์—ฌ์•ผ ํ•˜๋ฏ€๋กœ, open ํ›„ ftruncate๋ฅผ ํ˜ธ์ถœํ•œ๋‹ค.
    • mmap์— ์„ฑ๊ณตํ•˜๋ฉด, ๊ฐ’์„ ๊ธฐ๋กํ•˜์—ฌ ๋‹ค๋ฅธ ํ”„๋กœ์„ธ์Šค์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•œ๋‹ค.
  • consumer
    • ํŒŒ์ผ ์ƒ์„ฑ์ด ํ•„์š” ์—†๊ณ , open์„ ํ†ตํ•ด ์ ‘๊ทผํ•˜๋ฉด ๋œ๋‹ค.
    • mmap์— ์„ฑ๊ณตํ•˜๋ฉด, ๊ฐ’์„ ์ฝ์–ด ์˜จ๋‹ค.
  • mmap์„ ํ†ตํ•ด ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ํ• ๋‹นํ•˜๋Š” ๊ฒฝ์šฐ, munmap์„ ํ†ตํ•ด ํ• ๋‹น ํ•ด์ œํ•ด์ฃผ์–ด์•ผ ํ•œ๋‹ค.

 

SysV SHM

 ๋‘˜ ์ด์ƒ์˜ ํ”„๋กœ์„ธ์Šค๊ฐ€ ํŠน์ •ํ•œ ๋ฉ”๋ชจ๋ฆฌ ์˜์—ญ์„ ๊ณต์œ ํ•˜๋Š” ๊ฒƒ์„ ๋งํ•œ๋‹ค. ๋ฉ”๋ชจ๋ฆฌ ์˜์—ญ์— ๋™์‹œ์— ์ ‘๊ทผํ•˜๋Š” ๊ฒฝ์šฐ, ๋ฐ์ดํ„ฐ์˜ ์ผ๊ด€์„ฑ์ด ๋ณด์žฅ๋˜์ง€ ์•Š์„ ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ ๋™๊ธฐํ™”๊ฐ€ ํ•„์š”ํ•˜๋‹ค.

(์•„๋ž˜์˜ ์ฝ”๋“œ๋“ค์€ ๋ณ„๋„์˜ ๋™๊ธฐํ™” ๊ณผ์ •์ด ํ•„์š” ์—†๋Š” ์ฝ”๋“œ์ด๋‹ค.)

 

#define SHMKEY "test"
 
static int prosumer()
{
    int fd;
    key_t key;
    int *maped;
    int i;
 
    key = ftok(SHMKEY, SHMKEY_PROJID);
 
    if (key == -1) {
        perror("ftok()");
        return -1;
    }
 
    shm_id = shmget(key, 4096, IPC_CREAT | 0644);
     
    if (shm_id == -1)
    {
        perror("shmget()");
        return -1;
    }
 
    maped = shmat(shm_id, NULL, 0);
    if (maped == (void *)-1) {
        perror("shmat()");
        return -1;
    }
 
    for (i = 0; i < 100; i++) {
        maped[i] = i + 1;
    }
 
    shmdt(maped);
     
    return 0;
}
#define SHMKEY "test"
 
static int prosumer()
{
    int fd;
    key_t key;
    int *maped;
    int i;
 
    key = ftok(SHMKEY, SHMKEY_PROJID);
 
    if (key == -1) {
        perror("ftok()");
        return -1;
    }
 
    shm_id = shmget(key, 4096, IPC_CREAT | 0644);
     
    if (shm_id == -1)
    {
        perror("shmget()");
        return -1;
    }
 
    maped = shmat(shm_id, NULL, 0);
    if (maped == (void *)-1) {
        perror("shmat()");
        return -1;
    }
 
    for (i = 0; i < 100; i++) {
        maped[i] = i + 1;
    }
 
    shmdt(maped);
     
    return 0;
}

 ์œ„์™€ ๊ฐ™์ด ํ‚ค๋ฅผ ํ†ตํ•ด, ๋™์ผํ•œ ๋ฉ”๋ชจ๋ฆฌ ์˜์—ญ์— ์ ‘๊ทผํ•˜์—ฌ ํŠน์ • ํ”„๋กœ์„ธ์Šค์— ์ •๋ณด๋ฅผ ์“ฐ๊ฑฐ๋‚˜, ์ฝ์„ ์ˆ˜ ์žˆ๋‹ค.

  • File mapping๊ณผ ๋‹ฌ๋ฆฌ ํ‚ค๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ํ‚ค๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ SHM์„ attach ํ•œ๋‹ค.
  • ์‚ฌ์šฉ์ด ๋๋‚˜๋ฉด SHM์„ detatch ํ•œ๋‹ค.

 

POSIX SHM

 POSIX SHM์˜ ๊ฒฝ์šฐ, File mapping๊ณผ ์ฝ”๋“œ๊ฐ€ ์œ ์‚ฌํ•˜๋‹ค.

  • Prosumer์˜ ๊ฒฝ์šฐ, `fd = shm_open("/test", O_RDWR | O_CREATE, 0644)`๋กœ ๋ณ€๊ฒฝํ•˜๋ฉด ๋œ๋‹ค.
  • Consumer์˜ ๊ฒฝ์šฐ, `fd = shm_open("/test", O_RDWR)`๋กœ ๋ณ€๊ฒฝํ•˜๋ฉด ๋œ๋‹ค.
  • ์œ„์™€ ๊ฐ™์ด ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜๋ฉด, SHM์ด ์ƒ์„ฑ๋˜๋Š” ์œ„์น˜๋Š” `/dev/shm/test`๊ฐ€ ๋œ๋‹ค.

 

728x90
๋ฐ˜์‘ํ˜•

'๐Ÿ™‹โ€โ™‚๏ธ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์–ธ์–ด > C' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€

C: ํŒŒ์ผ ๋‹ค๋ฃจ๊ธฐ  (0) 2021.06.12
C: Signal  (0) 2021.06.11
C: thread safe and reentrant  (0) 2021.01.26
C: Memory Layout of C Programs  (0) 2021.01.26
C: Storage class specifier  (0) 2020.11.27
๋Œ“๊ธ€
๊ธ€ ๋ณด๊ด€ํ•จ
์ตœ๊ทผ์— ์˜ฌ๋ผ์˜จ ๊ธ€
์ตœ๊ทผ์— ๋‹ฌ๋ฆฐ ๋Œ“๊ธ€