首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

Linux C 信號發送機制:kill、raise、alarm、setitimer 完整解析

     編輯:關於C語言

核心系統呼叫總覽

#include <sys/types.h>
#include <signal.h>
#include <unistd.h>
#include <sys/time.h>

int kill(pid_t pid, int signum);           // 向指定進程/群組發送信號
int raise(int signum);                     // 向自身發送信號
unsigned int alarm(unsigned int seconds);  // 秒級定時器,送 SIGALRM
int setitimer(int which, const struct itimerval *value, struct itimerval *oldvalue); // 微秒級間隔定時器

權限模型

  • 發送進程的實際/有效 UID 必須匹配目標進程的實際/有效 UID,或具備 CAP_KILL 權限
  • 特例:SIGKILL、SIGSTOP 僅 root 可發送(防止濫用終止關鍵進程)
  • kill(0, sig):向同進程群組發送;kill(-1, sig):向所有可發送進程發送(root 除外)

raise():向自身發送信號

原型與行為

int raise(int sig);  // 等同於 kill(getpid(), sig)
回傳:成功 0,失敗 -1(設定 errno)

完整範例:互動式觸發 SIGINT

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

void handler(int sig) {
    printf("\n[Handler] Caught signal %d (SIGINT)\n", sig);
}

int main() {
    char buf[100];

    if (signal(SIGINT, handler) == SIG_ERR) {
        perror("signal");
        exit(1);
    }

    printf("PID: %ld\n", (long)getpid());
    printf("Type 'sigint' to raise SIGINT, Ctrl+C also works\n");

    while (1) {
        printf("> ");
        if (fgets(buf, sizeof(buf), stdin) == NULL) break;
        buf[strcspn(buf, "\n")] = '\0';  // 移除換行

        if (strcmp(buf, "sigint") == 0) {
            printf("[Main] Raising SIGINT...\n");
            raise(SIGINT);
        } else {
            printf("[Main] No match: '%s'\n", buf);
        }
    }
    return 0;
}

執行示意

$ ./raise_demo
PID: 12345
Type 'sigint' to raise SIGINT, Ctrl+C also works
> hello
[Main] No match: 'hello'
> sigint
[Main] Raising SIGINT...
[Handler] Caught signal 2 (SIGINT)
> ^C
[Handler] Caught signal 2 (SIGINT)
> exit
$

raise 範例執行截圖

alarm():簡易秒級定時器

  • 單進程唯一:後續呼叫會取消前一個 alarm
  • 回傳值:前一個 alarm 剩餘秒數(0 表示無)
  • 精度:秒級,實際觸發時間 ≥ 指定秒數
  • 常見用法:alarm(10); pause(); 但有競態風險(見 信號處理潛在危險)

setitimer():高精度間隔定時器

三種定時器類型

常數計時來源送出信號典型用途
ITIMER_REAL實牆鐘時間SIGALRM一般定時、超時控制
ITIMER_VIRTUAL進程用戶態 CPU 時間SIGVTALRM程式剖析、計算密集型任務計時
ITIMER_PROF進程用戶態+核心態 CPU 時間SIGPROF效能分析、採樣剖析

結構定義

struct itimerval {
    struct timeval it_interval;  // 間隔週期(0 = 單次觸發)
    struct timeval it_value;     // 首次觸發倒數
};

struct timeval {
    time_t      tv_sec;   // 秒
    suseconds_t tv_usec;  // 微秒
};

範例:每 500ms 觸發一次,共 5 次

#include <stdio.h>
#include <signal.h>
#include <sys/time.h>
#include <unistd.h>

volatile int count = 0;

void timer_handler(int sig) {
    printf("Timer tick %d\n", ++count);
    if (count >= 5) {
        struct itimerval zero = {{0,0}, {0,0}};
        setitimer(ITIMER_REAL, &zero, NULL);  // 停止定時器
    }
}

int main() {
    signal(SIGALRM, timer_handler);

    struct itimerval timer = {
        .it_interval = {0, 500000},  // 500ms 間隔
        .it_value = {0, 500000}      // 500ms 首次
    };

    setitimer(ITIMER_REAL, &timer, NULL);

    while (count < 5) pause();  // 等待信號
    printf("Done\n");
    return 0;
}

進階替代方案:timer_create() (POSIX.1b)

  • 支援多定時器、指定信號編號(SIGRTMIN+n)、傳遞資料指標
  • 適合高併發、精密控制場景
  • man 2 timer_create 參考

總結比較表

函數精度用途限制
kill()N/A進程間信號傳遞需權限、pid_t
raise()N/A自我觸發、測試處理器僅限自身
alarm()秒簡易單次/週期定時唯一、秒級、競態風險
setitimer()微秒高精度週期/單次定時三種類型共用 SIGALRM/VTALRM/PROF
timer_create()奈秒多定時器、即時信號、資料傳遞API 較複雜、需連結 -lrt
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved