在 C 語言中傳送訊號到一個程序

Jinku Hu 2023年10月12日
  1. 使用 kill 函式將訊號傳送到 C 語言中的程序
  2. 使用 kill 函式和空訊號來檢查 C 語言中程序的存在
在 C 語言中傳送訊號到一個程序

本文將解釋幾種如何在 C 語言中將訊號傳送到程序的方法。

使用 kill 函式將訊號傳送到 C 語言中的程序

訊號是中斷樣式的通知,可以表示特定事件,並且可以將其傳送到程序。如果第一個程序具有正確的許可權,則一個程序可以向另一個程序傳送訊號。訊號是一種程序間通訊,可用於與不同程式,子程序或執行緒進行互動。kill 功能可用於向過程傳送各種訊號。它帶有兩個引數-要傳遞的程序 ID 和訊號號。請注意,訊號號是常量整數,定義為 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);
}

使用 kill 函式和空訊號來檢查 C 語言中程序的存在

kill 功能的另一個用例是檢查程序的存在。即使你嘗試使用此方法驗證某些程序的存在,在某些情況下,檢索到的狀態也不正確。這可能是由於觀察到的過程已經終止並且不同的程式使用了相同的 ID 而引起的,因為作業系統允許重複使用標識號。

需要向 kill 傳遞一個訊號編號-0,並且應對函式的返回碼進行 errno 碼的測試。也就是說,如果 kill 返回 -1 錯誤程式碼,並且將 errno 設定為 ESRCH,則給定的程序不存在。如果錯誤程式碼返回並帶有 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);
}
作者: Jinku Hu
Jinku Hu avatar Jinku Hu avatar

DelftStack.com 創辦人。Jinku 在機器人和汽車行業工作了8多年。他在自動測試、遠端測試及從耐久性測試中創建報告時磨練了自己的程式設計技能。他擁有電氣/ 電子工程背景,但他也擴展了自己的興趣到嵌入式電子、嵌入式程式設計以及前端和後端程式設計。

LinkedIn Facebook

相關文章 - C Signal