SIGALRM信號是操作系統中的其中一個信號。他的作用是設置進程隔多久後會收到一個SIGALRM信號。下面我們看一下他的實現原理。
alarm系統調用是設置多久觸發SIGALRM信號的函數。下面是他的聲明。
#include <unistd.h>
unsigned alarm(unsigned seconds);
我們看看實現。
int sys_alarm(long seconds)
{
int old = current->alarm;
// 算出原來的時間
if (old)
old = (old - jiffies) / HZ;
/*
系統每隔n秒觸發一次時鐘中斷。jiffies是系統發生時鐘中斷的次數。
1秒等於HZ個jiffies,這裏就是算出jiffies數,即時鐘中斷髮生多少次後觸發SIGALRM信號
*/
current->alarm = (seconds>0)?(jiffies+HZ*seconds):0;
// 返回舊的
return (old);
}
我們看到PCB中使用alarm字段記錄了SIGALRM信號觸發的時間。我們再來看一下觸發的時機。
*/
void schedule(void)
{
int i,next,c;
struct task_struct ** p;
// 遍歷進程
for(p = &LAST_TASK ; p > &FIRST_TASK ; --p)
if (*p) {
/*
判斷是否設置了alarm並且過期了
alarm < jiffies說明過期了。設置alarm信號,清除設置標記
*/
if ((*p)->alarm && (*p)->alarm < jiffies) {
(*p)->signal |= (1<<(SIGALRM-1));
(*p)->alarm = 0;
}
}
...
}
在進程調度的時候,系統會處理SIGALRM信號的邏輯,判斷是否可以觸發SIGALRM信號了。是的話在PCB中打上標記。但是這時候如果該進程沒有被調度執行,那SIGALRM信號的函數會被延遲執行。即這裏只是記錄信息的時機,不一定是執行的時機。
另外在父進程創建子進程的時候(fork),子進程不會進程父進程的alarm信息(重置爲0),但是如果一個進程設置了SIGALRM然後通過execve系列函數執行新的程序時,alarm信息會被繼承下來。最後我們看一下用法。
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
void handle_alarm()
{
exit(0);
}
int main(int argc, char *argv[])
{
signal(SIGALRM, handle_alarm);
alarm(10);
while(1) {}
}
進程在10秒或10秒之後觸發SIGALRM信號,然後執行信號處理函數,最後退出。