核心系統呼叫總覽
#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
$

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 |