프로그래밍/etc

[C++] simple IPC, pthread example for ubuntu

인썸니아 2024. 7. 18. 10:43

우분투에서 동작하는 message queue 방식의 IPC 예제 프로그램을 작성 하였다.

client에서 char를 보내고 server에서 이를 받아 1초마다 출력하는 아주 간단한 코드이다.

 

server.cpp

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <unistd.h>
#include <pthread.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>

#define MAX_TEXT 100

struct msg_buffer {
    long msg_type;
    char msg_text[MAX_TEXT];
};

volatile bool g_aborted = false;
volatile bool g_print = false;
int msgid;
char output_char = 'A';  // Default output character

void *message_receiver(void *arg);

int main() {
    key_t key;
    pthread_t tid;

    std::cout << "start test server !!" << std::endl;

    // Generate unique key for IPC
    if ((key = ftok(".", 173)) == -1) {
        perror("ftok");
        exit(1);
    }

    // Create message queue
    if ((msgid = msgget(key, 0666 | IPC_CREAT)) == -1) {
        perror("msgget");
        exit(1);
    }

    // Create thread to handle message receiving
    if (pthread_create(&tid, NULL, message_receiver, NULL) != 0) {
        perror("pthread_create");
        exit(1);
    }

    // Main thread: Output the current char every second
    while (not g_aborted) {
        if (g_print)
            std::cout << output_char << std::endl;
        sleep(1);
    }

    std::cout << "exit test server !!" << std::endl;

    return 0;
}

void *message_receiver(void *arg) {
    struct msg_buffer msg {};

    while (true) {
        // Receive message from client
        if (msgrcv(msgid, &msg, sizeof(msg.msg_text), 1, 0) == -1) {
            perror("msgrcv");
            exit(1);
        }

        // Update output character
        output_char = msg.msg_text[0];

        if (output_char == 'Z') {
            g_aborted = true;
            break;
        }
        else if (output_char == 'P') {
            g_print = not g_print;
        }
    }

    pthread_exit(nullptr);
}

char 출력은 main loop에서 처리하고, ipc message 수신을 위한 thread를 생성하였다. 'P' char를 받으면 출력 여부를 toggle 하고, 'Z' char를 받으면 종료한다.

 

반응형

 

client.cpp

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>

#define MAX_TEXT 100

struct msg_buffer {
    long msg_type;
    char msg_text[MAX_TEXT];
};

int main(int argc, char *argv[]) {
    int msgid;
    struct msg_buffer msg {};

    if (argc != 2) {
        fprintf(stderr, "Usage: %s <character>\n", argv[0]);
        exit(1);
    }

    key_t key;
    if ((key = ftok(".", 173)) == -1) {
        perror("ftok");
        exit(1);
    }

    if ((msgid = msgget(key, 0666 | IPC_CREAT)) == -1) {
        perror("msgget");
        exit(1);
    }

    strncpy(msg.msg_text, argv[1], MAX_TEXT);
    msg.msg_text[MAX_TEXT - 1] = '\0'; // ensure null-terminated string
    msg.msg_type = 1;

    if (msgsnd(msgid, &msg, sizeof(msg.msg_text), 0) == -1) {
        perror("msgsnd");
        exit(1);
    }

    std::cout << "sent to server: " << msg.msg_text[0] << std::endl;

    return 0;
}

실행시 argument로 char를 받는다.

 

태그는 C++을 달았지만, cout을 제외하면 사실상 C 코드이다.

 

각각을 빌드하여 먼서 server를 background에서 실행하고, client를 통해 char를 전달하면 의도한 대로 잘 동작한다.

 

ipcs 명령으로 message queue를 확인해 볼 수 있다.

 

 

다음번엔 이걸 systemd 에 등록하여 service로 동작시켜볼까 한다.

 

 

반응형