0Pricing
C Academy · レッスン

パイプ

親子プロセス間通信です。

「パイプ」はCoddyKit上の無料C Academyレッスンです。 これはレッスン1/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはC Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 C Academyコースには全4レッスンが含まれています。

パイプとは

パイプは、関連するプロセス間で一方向の通信を行うチャネルです。一方のプロセスがバイトを書き込み、もう一方のプロセスがそれを読み取ります。データのベルトコンベアのようなものです。

2 つのファイルディスクリプタ

pipe() 呼び出しは 2 要素の配列を設定します。fd[0] は読み取り側、fd[1] は書き込み側です。fd[1] に書き込んだデータは fd[0] から読み取れます。

#include <unistd.h>
#include <stdio.h>

int make_pipe(int fd[2]) {
    if (pipe(fd) < 0) { perror("pipe"); return -1; }
    /* fd[0] read end, fd[1] write end */
    return 0;
}

fork との組み合わせ

fork() の後、親プロセスと子プロセスはパイプのディスクリプタを共有します。これにより、親プロセスと子プロセスの一方が書き込み、もう一方が読み取る通信が可能になります。

使わない側を閉じる

各プロセスは使用しない側を close する必要があります。読み取り側は書き込み側を閉じ、書き込み側は読み取り側を閉じます。そうしないと、読み取り側はファイル終端を検出できません。

#include <unistd.h>

void parent_as_writer(int fd[2]) {
    close(fd[0]);              /* parent will not read */
    write(fd[1], "hello", 5);  /* parent writes */
    close(fd[1]);              /* signal EOF to reader */
}

親子間通信の例

親プロセスがメッセージを書き込み、子プロセスがそれを読み取ります。それぞれ使用しない側を閉じます。

#include <unistd.h>
#include <stdio.h>

void demo(int fd[2]) {
    if (fork() == 0) {           /* child: reader */
        close(fd[1]);
        char buf[64];
        ssize_t n = read(fd[0], buf, sizeof buf - 1);
        buf[n] = 0;
        printf("child got: %s\n", buf);
        close(fd[0]);
    } else {                     /* parent: writer */
        close(fd[0]);
        write(fd[1], "hi child", 8);
        close(fd[1]);
    }
}

読み取りが EOF を返す場合

すべての書き込み側が閉じられると、read は0を返し、ファイル終端を示します。書き込み側が 1 つでも開いたままだと、読み取り側は追加データを待って永遠にブロックします。これはよくあるバグです。

パイプの容量とブロッキング

パイプには有限サイズのバッファがあります(多くの場合 64 KB)。バッファがいっぱいになると、読み取り側がデータを取り出すまで write はブロックします。空の場合、データが到着するまで read がブロックします。このフロー制御によって、2 つのプロセスが同期されます。

dup2 によるリダイレクト

dup2 を使うと、プロセスの stdin または stdout をパイプの一端に置き換えられます。これにより、シェルは cmd1 | cmd2 を実装し、一方のコマンドの出力を次のコマンドの入力に接続します。

#include <unistd.h>

void stdout_to_pipe(int fd[2]) {
    close(fd[0]);
    dup2(fd[1], STDOUT_FILENO); /* writes to stdout go into pipe */
    close(fd[1]);
}

名前付きパイプ(FIFO)

通常のパイプで接続できるのは、関連するプロセスだけです。名前付きパイプ(FIFO)は mkfifo で作成され、ファイルシステム上に存在するため、無関係なプロセスでもパスを指定して開き、通信できます。

#include <sys/stat.h>

int make_fifo(const char *path) {
    return mkfifo(path, 0666); /* creates a FIFO file */
}

SIGPIPE の危険性

読み取り側が閉じられたパイプに書き込むと SIGPIPE が発生し、デフォルトではプロセスが終了します。シグナルを無視するか、write から返される EPIPE エラーを確認してください。

パイプを使う場面

パイプは、親プロセスと子プロセスの間で単純な一方向ストリーミングを行う場合や、プログラムを連結する場合に適しています。双方向通信や無関係なプロセス間の通信には、FIFO、ソケット、共有メモリを検討してください。

理解度チェック

パイプについての理解度を確認しましょう。

まとめ

親子間通信にパイプを使う方法を学びました。

  • pipe() は fd[0](読み取り)と fd[1](書き込み)を返します
  • fork と組み合わせ、使わない側を閉じます
  • すべての書き込み側が閉じられると、EOF で read は 0 を返します
  • FIFO は無関係なプロセスを接続します。SIGPIPE に注意してください

よくある質問

「パイプ」レッスンは無料ですか?

はい。「パイプ」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、C Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 C Academyコースには全4レッスンが含まれています。

「パイプ」で何を学びますか?

親子プロセス間通信です。 ブラウザで直接実行するハンズオンコードでC Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

C Academyを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのC Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン1/4です。

「パイプ」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このC Academyレッスンでコードを書いて実行できますか?

はい。すべてのC Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. パイプ
  2. 共有メモリ
  3. メッセージキュー
  4. シグナル
← C Academyに戻る