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

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

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

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

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

在下面的示例中,我們演示了一個程式,該程式使用 fork 呼叫建立一個子程序,然後執行遞增整數的無限迴圈。同時,父程序發出 SIGTERM 訊號,終止子程序,並且在使用 waitpid 呼叫接收到子狀態程式碼後,主函式退出。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <signal.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 <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <signal.h>
#include <errno.h>
#include <stdbool.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);
}
Author: Jinku Hu
Jinku Hu avatar Jinku Hu avatar

Founder of DelftStack.com. Jinku has worked in the robotics and automotive industries for over 8 years. He sharpened his coding skills when he needed to do the automatic testing, data collection from remote servers and report creation from the endurance test. He is from an electrical/electronics engineering background but has expanded his interest to embedded electronics, embedded programming and front-/back-end programming.

LinkedIn

相關文章 - C Signal