1
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++:signalを使う

1
Posted at

シグナルとは

プロセスに対して非同期に通知を送る仕組み。
ソフトウェアの割り込み機能。

強制終了、再起動、一時停止など

C++での使用

ライブラリ

csignal

signal()

signal(int signum, void (*handler)(int));
  • signum: シグナル番号
  • handler: 受信時に実行される関数

シグナルをキャッチすると関数が実行される。

signal()の挙動は環境依存な部分がある。
後述のsigaction()の使用が推奨されている

ハンドラ関数の制約

  • void
  • int型の引数を持つ(この引数にはシグナル番号が格納される)

async-signal-safeな処理のみ使用できる。

使用例

#include <iostream>
#include <csignal>

void signal_handler(int signum){
  // 処理
}

int main() {
  std::signal(SIGINT, signal_handler);
  //...
  return 0;
}

sigaction()

sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);
  • signum: シグナル番号
  • act: 新しく設定するシグナル動作
  • oldact: 以前の設定を受け取る

actoldactにはnullptrを設定できる。(前の設定を引き継ぐ)

signal()よりも詳細な制御が可能な関数。(推奨)
またsignal()同様、async-signal-safeな処理のみ使用できる。

struct sigaction

struct sigaction {
    void     (*sa_handler)(int);
    void     (*sa_sigaction)(int, siginfo_t*, void*);
    sigset_t   sa_mask;
    int        sa_flags;
};

sa_handler()

void (*sa_handler)(int);

通常のシグナルハンドラ。
signal()のハンドラ関数と同じ。

sa_sigaction()

void (*sa_sigaction)(int, siginfo_t*, void*);

拡張のシグナルハンドラ。
sa_flagsSA_SIGINFOを指定した場合に使用される。

  • 第一引数: シグナル番号
  • siginfo_t*: 送信元PID、シグナルの原因など
  • 第三引数: ユーザーコンテキスト

sa_mask

sigset_t sa_mask;

ハンドラ実行中にブロックするシグナル集合を指定する。

sigemptyset(&act.sa_mask);
sigaddset(&act.sa_mask, signum);

ハンドラ実行中signumが無効化される。

sa_flags

int sa_flags;

シグナル処理のオプションを指定する。

主に

  • SA_RESTART
    シグナルで中断されたシステムコールを自動再開する
  • SA_SIGINFO
    sa_sigactionを使用する
  • SA_NODEFER
    自分自身のシグナルをブロックしない(デフォルトではブロックされる)

使用例

#include <csignal>
#include <cstring>

void handler(int sig) {
    // 処理
}

int main() {
    struct sigaction act;
    std::memset(&act, 0, sizeof(act));// 未初期化フィールドによる未定義動作を防ぐため

    act.sa_handler = handler;
    sigemptyset(&act.sa_mask);
    act.sa_flags = 0;

    sigaction(SIGINT, &act, nullptr);
}

raise()

raise(int signum);
  • signum: シグナル番号

シグナルを意図的に送信する。

使用例

#include <csignal>

int main() {
  std::raise(SIGINT);
}
1
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
1
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?