C のプロセスにシグナルを送信する

胡金庫 2023年10月12日
  1. kill 関数を使用して、C のプロセスにシグナルを送信する
  2. C 言語で kill 関数とヌルシグナルを使用してのプロセスの存在を確認する
C のプロセスにシグナルを送信する

この記事では、C のプロセスに信号を送信する方法のいくつかの方法について説明します。

kill 関数を使用して、C のプロセスにシグナルを送信する

シグナルは、特定のイベントを示す可能性のある割り込みスタイルの通知であり、プロセスに送信できます。最初のプロセスに適切な権限がある場合、1つのプロセスが別のプロセスにシグナルを送信できます。シグナルは、さまざまなプログラム、子プロセス、またはスレッドと対話するために利用できるプロセス間通信の一種です。kill 関数を使用して、さまざまなシグナルをプロセスに送信できます。配信されるプロセス ID とシグナル番号の 2つの引数を取ります。信号番号は、SIG___ タイプのマクロとして定義されている定数整数であることに注意してください。

次の例では、fork 呼び出しを使用して子プロセスを作成し、整数をインクリメントする無限ループを実行するプログラムを示します。一方、親プロセスは子プロセスを終了する SIGTERM シグナルを発行し、waitpid 呼び出しを使用して子ステータスコードを受信した後、メイン関数は終了します。

#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <unistd.h>

int main(int argc, char *argv[]) {
  int wstatus;

  pid_t c_pid = fork();
  if (c_pid == -1) {
    perror("fork");
    exit(EXIT_FAILURE);
  }

  if (c_pid == 0) {
    printf("printed from child process - %d\n", getpid());

    int count = 0;

    while (1) {
      count += 1;
    }

    exit(EXIT_SUCCESS);
  } else {
    printf("printed from parent process - %d\n", getpid());
    int ret;

    ret = kill(c_pid, SIGTERM);
    if (ret == -1) {
      perror("kill");
      exit(EXIT_FAILURE);
    }

    if (waitpid(c_pid, &wstatus, WUNTRACED | WCONTINUED) == -1) {
      perror("waitpid");
      exit(EXIT_FAILURE);
    }
  }

  exit(EXIT_SUCCESS);
}

C 言語で kill 関数とヌルシグナルを使用してのプロセスの存在を確認する

kill 関数のもう 1つの使用例は、プロセスの存在を確認することです。この方法で何らかのプロセスの存在を確認しようとしても、取得したステータスが正しくない場合があります。これは、監視対象のプロセスがすでに終了していて、オペレーティングシステムで識別番号の再利用が許可されているため、別のプログラムが同じ ID を使用している場合に発生する可能性があります。

kill にはシグナル番号(ゼロ)を渡す必要があり、関数の戻りコードは errno コードについてテストする必要があります。つまり、kill-1 エラーコードを返し、errnoESRCH に設定されている場合、指定されたプロセスは存在しません。errnoEPERM 値でエラーコードが返された場合-プログラムは存在しますが、呼び出し元のプロセスにはシグナルを送信する権限がありません。ゼロが返された場合、プロセスは存在し、呼び出し元のプロセスはそれに他のシグナルを送信できます。

次のコードサンプルは、上記のステータスチェックステートメントを実装し、対応するメッセージを出力します。

#include <errno.h>
#include <signal.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <unistd.h>

int main(int argc, char *argv[]) {
  int wstatus;

  pid_t c_pid = fork();
  if (c_pid == -1) {
    perror("fork");
    exit(EXIT_FAILURE);
  }

  if (c_pid == 0) {
    printf("printed from child process - %d\n", getpid());

    int count = 10;

    while (count >= 0) {
      count -= 1;
      sleep(1);
    }

    exit(EXIT_SUCCESS);
  } else {
    printf("printed from parent process - %d\n", getpid());
    int ret;

    errno = 0;
    ret = kill(c_pid, 0);
    if (ret == -1) {
      if (errno == EPERM)
        printf(
            "Process exists, but we don't have "
            "permission to send it a signal\n");
      else if (errno == ESRCH)
        printf("Process does not exist\n");
      else
        perror("kill");
      exit(EXIT_FAILURE);
    } else {
      printf("Process exists and we can send it a signal\n");
    }

    if (waitpid(c_pid, &wstatus, WUNTRACED | WCONTINUED) == -1) {
      perror("waitpid");
      exit(EXIT_FAILURE);
    }
  }

  exit(EXIT_SUCCESS);
}
著者: 胡金庫
胡金庫 avatar 胡金庫 avatar

DelftStack.comの創設者です。Jinku はロボティクスと自動車産業で8年以上働いています。自動テスト、リモートサーバーからのデータ収集、耐久テストからのレポート作成が必要となったとき、彼はコーディングスキルを磨きました。彼は電気/電子工学のバックグラウンドを持っていますが、組み込みエレクトロニクス、組み込みプログラミング、フロントエンド/バックエンドプログラミングへの関心を広げています。

LinkedIn Facebook

関連記事 - C Signal