C Academy · レッスン

シグナル

非同期通知です。

レッスン 4/413 ステップ

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

シグナルとは

シグナルは、イベントが発生したことをプロセスに知らせるために送られる非同期通知です。たとえば、ユーザーが Ctrl-C を押した場合や、子プロセスが終了した場合に発生します。シグナルは軽量な IPC の一種です。

よく使うシグナル

よく扱うシグナルには、次のようなものがあります。

  • SIGINT 割り込み(Ctrl-C)
  • SIGTERM 丁寧な終了要求
  • SIGKILL 強制終了(捕捉できません)
  • SIGCHLD 子プロセスの状態が変化した
  • SIGSEGV 不正なメモリアクセス

デフォルトの処理

各シグナルには、終了、コアダンプを出力して終了、無視、停止、継続のいずれかのデフォルト動作があります。ほとんどの場合、ハンドラーでこれらを上書きできます。

ハンドラーの設定

ハンドラーを設定する現代的で移植性の高い方法はsigactionです。ハンドラーはシグナル番号を受け取る関数です。

#include <signal.h>
#include <stdio.h>

void on_signal(int sig) {
    /* note: printf is not async-signal-safe; for demo only */
    write(1, "caught\n", 7);
}

int install(void) {
    struct sigaction sa = {0};
    sa.sa_handler = on_signal;
    return sigaction(SIGINT, &sa, NULL);
}

signal()を使わない理由

古いsignal()関数は、システムによって動作(ハンドラーのリセットやSA_RESTARTの制御)が一貫しません。仕様が明確で移植性の高いsigactionを使用してください。

非同期シグナル安全関数

ハンドラーはコードの任意の箇所で割り込む可能性があるため、writeのような非同期シグナル安全関数だけを呼び出せます。ハンドラーからprintfやmallocを呼び出すと、デッドロックやデータ破損が発生するおそれがあります。

volatileフラグの使用

安全なパターンは、ハンドラーでvolatile sig_atomic_t型のフラグを設定し、メインループでそのフラグを確認する方法です。これにより、ハンドラーを小さく安全に保てます。

#include <signal.h>

volatile sig_atomic_t stop = 0;

void handler(int sig) {
    stop = 1; /* only set a flag */
}
/* main loop: while (!stop) { do_work(); } */

シグナルの送信

kill(pid, sig)を使うと別のプロセスにシグナルを送信でき、raise(sig)を使うと自分自身に送信できます。名前に反して、killは致命的なシグナルだけでなく、任意のシグナルを送信します。

#include <signal.h>

int notify(int pid) {
    return kill(pid, SIGTERM); /* ask process to terminate */
}

シグナルのブロック

クリティカルセクションを保護するには、sigprocmaskとシグナルセットを使って一時的にシグナルをブロックします。ブロックされたシグナルは保留中になり、ブロックを解除すると配信されます。

#include <signal.h>

void block_int(void) {
    sigset_t set;
    sigemptyset(&set);
    sigaddset(&set, SIGINT);
    sigprocmask(SIG_BLOCK, &set, NULL);
}

SIGCHLDによる子プロセスの回収

子プロセスが終了すると、カーネルはSIGCHLDを送信します。waitpidを呼び出すハンドラーで子プロセスを回収すると、プロセステーブルに残り続けるゾンビプロセスを防げます。

#include <signal.h>
#include <sys/wait.h>

void reap(int sig) {
    while (waitpid(-1, NULL, WNOHANG) > 0)
        ; /* reap all finished children */
}

捕捉できないシグナル

2つのシグナルには例外がありません。SIGKILLは必ずプロセスを終了させ、SIGSTOPは必ずプロセスを停止させます。これらは捕捉、ブロック、無視のいずれもできないため、システムはプロセスを確実に制御できます。

理解度チェック

シグナルについての理解度を確認しましょう。

まとめ

非同期通知に使うシグナルについて学びました。

  • 古いsignalではなくsigactionでハンドラーを設定する
  • ハンドラーは非同期シグナル安全でなければならないため、フラグの設定を優先する
  • kill/raiseで送信し、sigprocmaskでブロックする
  • SIGCHLDを受け取ったら子プロセスを回収する。SIGKILLとSIGSTOPは捕捉できない
無料で開始

AI チューターと学ぶ C — 無料

ブラウザでリアルコードを書いて実行し、24/7 の AI チューターから瞬時にサポートを受け、ウェブまたはアプリで続きから学習できます。

コース
39
レッスン
144

よくある質問

「シグナル」レッスンは無料ですか?

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

「シグナル」で何を学びますか?

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

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

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

「シグナル」レッスンにはどのくらい時間がかかりますか?

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

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

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

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

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