0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

四日では覚えられないC++言語【Day 10: メモリ・並行処理・通信の仕組み】

0
Posted at

はじめに

【C++言語】 は、C言語を拡張して1980年代に登場したプログラミング言語です。

特徴としては、C言語の「速さ・低レベル制御」を残しつつ、「オブジェクト指向」「例外処理」「標準ライブラリの拡充」などが加わりました。

【注意】このメモは、C++言語を全くしらない人間が、ChatGPTに聞いて適当に書いている、C++言語の基本的な記載方法のまとめです。

(内容は確認しながら書いているつもりですが、間違ってたらごめんなさい)


🟦 1 メモリの裏側(ヒープとグローバル変数)


1.1 メモリの構造

プログラムのメモリは大きく分けて:

・スタック(関数呼び出し)
・ヒープ(動的確保)
・グローバル領域

👉 それぞれ役割が違う


1.2 ヒープ領域とは

int* p = new int(10);
delete p;

🔹 特徴

・実行中に確保される
・手動で解放が必要
・ミスるとバグになる


1.3 グローバル変数とは

int g_value = 10;

🔹 特徴

・プログラム開始時に生成
・終了時に自動破棄
・どこからでもアクセス可能


1.4 ❗危険な組み合わせ(重要)
ヒープ × グローバル変数

👉 よくある事故

二重解放(double free)
解放後アクセス
メモリ破壊


1.5 なぜ問題になるのか

class A {
    int* p;
public:
    A() { p = new int(10); }
    ~A() { delete p; }
};

A g_obj;


👉 グローバルは終了時に自動で破棄される

👉 ライブラリや複数定義が絡むと

💥 同じメモリを2回解放 → クラッシュ


1.6 💡 実務ポイント

・グローバル変数は極力使わない
・使うなら namespace / static でスコープ制限
・ヒープは std::vector や std::string に任せる

👉 「手動deleteを減らす」


🟦 2 データの流れ(FIFO)


2.1 FIFOとは

👉 First In First Out

A → B → C(入れる)

A → B → C(取り出す)


2.2 何に使うか

・メッセージキュー
・バッファ
・プロセス間通信

👉 順番保証が目的


2.3 OSでの実体

mkfifo /tmp/myfifo

👉 名前付きパイプ(FIFOファイル)


2.4 イメージ

FIFO = データの通り道

👉 「プロセス間のパイプ」


2.5 💡 挙動のポイント

・書き込み側だけだとブロックする
・読み手がいないと詰まる
・サイズ制限あり(バッファサイズ)

👉 ストリーム(流れるデータ)として扱う


🟦 3 処理の制御(セマフォ)


3.1 セマフォとは

👉 同時に使える数を制御する仕組み


3.2 イメージ
リソース数 = 2

A → OK
B → OK
C → 待ち


3.3 なぜ必要か

❌ FIFOだけだと

同時書き込み → データ破壊

👉 セマフォで制御する


3.4 実際の動き

sem_wait(sem); // ロック
// 処理
sem_post(sem); // 解放

👉 クリティカルセクションを守る


3.4 💡 実務ポイント
・mutex とほぼ同じ用途(バイナリセマフォ)
・複数許可できるのが強み(カウントセマフォ)

👉 「同時に何人OK?」を制御する


🟦 4 通信の考え方(ロングポーリング)


4.1 通常のポーリング

👉 定期的に「ある?」確認


4.2 ロングポーリング

👉 データが来るまで待つ


4.3 流れ
クライアント → リクエスト
サーバー → 待機
データ到着 → レスポンス


4.4 目的

・擬似リアルタイム通信
・無駄な通信削減


4.5 💡 実務での立ち位置

・WebSocketの前世代的技術
・サーバープッシュの簡易版

👉 「リアルタイムっぽく見せる技術」


🟦 5 実践:FIFO+セマフォでメッセージ通信


🟩 事前準備(1回だけ)
mkfifo /tmp/myfifo


🟨 Writer(送信側)

#include <iostream>
#include <fcntl.h>
#include <unistd.h>
#include <semaphore.h>

int main() {
    const char* fifoPath = "/tmp/myfifo";
    const char* semName = "/mysem";

    sem_t* sem = sem_open(semName, O_CREAT, 0666, 1);

    int fd = open(fifoPath, O_WRONLY);

    std::string msg = "Hello from Writer\n";

    sem_wait(sem);

    write(fd, msg.c_str(), msg.size());

    std::cout << "送信: " << msg;

    sem_post(sem);

    close(fd);
    sem_close(sem);

    return 0;
}


🟪 Reader(受信側)

#include <iostream>
#include <fcntl.h>
#include <unistd.h>

int main() {
    const char* fifoPath = "/tmp/myfifo";

    int fd = open(fifoPath, O_RDONLY);

    char buffer[128];

    while (true) {
        int n = read(fd, buffer, sizeof(buffer) - 1);
        if (n > 0) {
            buffer[n] = '\0';
            std::cout << "受信: " << buffer;
        }
    }

    close(fd);
    return 0;
}


🟧 実行手順

① Reader起動(先に!)

g++ reader.cpp -o reader
./reader

② Writer起動(別ターミナル)

g++ writer.cpp -o writer -pthread
./writer


🧠 ポイント解説

🟩 セマフォ

sem_wait(sem);
sem_post(sem);

👉 同時書き込み防止
👉 順番制御ではなく「人数制御」


🟦 FIFO

open("/tmp/myfifo", O_WRONLY);

👉 プロセス間通信
👉 カーネル経由のストリーム


🟨 データの流れ(全体像)
Writer → FIFO → Reader

セマフォで制御

👉 流れ(FIFO)+制御(セマフォ)


⚠️ 注意(超重要)

❗ 1. Readerが先に起動

👉 Writerがブロックする


❗ 2. メッセージ設計

今回は

\n 区切り

👉 実務では

・ヘッダ(長さ)
・固定長
・バイナリ構造

が必要


❗ 3. セマフォ後片付け

sem_unlink("/mysem");

👉 ゴミが残るのを防ぐ


❗ 4. 完全ではない(重要)

この構成は「簡易版」

足りないもの:

・メッセージ境界保証
・耐障害性
・再送制御

👉 本格的には

・メッセージキュー(mq)
・Redis / Kafka

などを使う


🟪 これでできること

・複数プロセス安全通信
・簡易メッセージキュー
・非同期処理の基礎


💬 最後に

👉 今日の本質はこれ

FIFO = データの流れ
セマフォ = 制御
ヒープ = メモリ管理
ロングポーリング = 通信モデル

👉 全部組み合わさると

「実システムになる」



💠ゼロから始めるプログラム学習(C++)💠


💠C++まとめ💠









💠Cまとめ💠








0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?