dnotify就是指 directory notification,是c中的情況. 我
們可以在linux kernel的document下找到這個說明文檔
#define _GNU_SOURCE /* needed to get the defines */
#include <fcntl.h> /* in glibc 2.2 this has the needed
values defined */
#include <signal.h>
#include <stdio.h>
#include <unistd.h>
static volatile int event_fd;
// 信號處理例程
static void handler(int sig,siginfo_t *si,void *data)
{
event_fd = si->si_fd;
}
int main(void)
{
struct sigaction act;
int fd;
// 登記信號處理例程
act.sa_sigaction = handler;
sigemptyset(&act.sa_mask);
act.sa_flags = SA_SIGINFO;
sigaction(SIGRTMIN,&act,NULL);
// 需要了解當前目錄"."的情況
fd = open(".",O_RDONLY);
fcntl(fd,F_SETSIG,SIGRTMIN);
// 默認下是SIGIO被髮送,所以這裏用SIGRTMIN,這樣內核發送數據的
// 時候,siginfo structure作爲參數被發出去.
// 最好是採用SIGRTMIN(real time signals)+n作爲信號,這樣可以
// 被隊列化. 注意SIGRTMIN進程被阻塞,最好使用SIGRTMIN+1
fcntl(fd,F_NOTIFY,DN_MODIFY|DN_CREATE|DN_MULTISHOT);
/* we will now be notified if any of the files
in "." is modified or new files are created,
原本每一次處理了modify和create之後,就必須重新註冊
所以這裏用mutilshot(多次觸發)來保證我們不需要重新註冊
這裏的fcntl對應內核驅動的dir_notify,
不過這個調用僅對fs有用,和fcntl有關的還有check_flag系統調用*/
while (1) {
// 收到信號後,就會執行信號處理例程.
// 而 pause() 也就結束了.
pause();
printf("Got event on fd=%d/n",event_fd);
}
}
程序首先註冊一個信號處理例程,然後通知Kernel,我要觀察fd上的DN_MODIFY 和
DN_CREATE 和 DN_MULTISHOT 事件. Linux Kernel 收到這個請求後,把相應的fd的inode給
做上記號,然後Linux Kernel和用戶應用程序就自顧自去處理各自的別的事情去了. 等到
inode上發生了相應的事件,Linux Kernel就把信號發給用戶進程,於是開始執行信號處理例
程,用戶程序對文件系統上的變化也就可以及時的做出反應了.
"unix環境高級編程"P213中對信號的一些術語和語義進行了定義:
首先,當造成信號的事件發生時,爲進程產生了一個信號
(或者向一個進程發送了一個信號). 事件可以是硬件異常(/0),軟件條件(alarm),終端產
生信號或者kill. 當產生了信號時,內核通常在進程表中設置某種形式的一個標誌. 當對
信號做了這種動作(設置標誌),我們說向一個進程傳遞了一個信號. 在信號產生
(generation)和遞送(delivery)之間的時間間隔內,爲信號未決(pending).
// 其實一般我們delivery信號給一個進程之後一般就是直接處理了. 所以pending事實上
// 也可以定義爲信號發生和處理之間的那段時間間隔的那種進程狀態.
進程可以選用"進程遞送阻塞". 如果爲進程產生了一個選擇爲阻塞的信號,而且對該信號
的動作時系統默認動作或者捕捉該信號,則爲該進程將次信號保持爲未決狀態,知道該進程
對此信號解除了阻塞,或者對此信號的多做更改爲忽略. 當傳遞一個原來被阻塞的信號給
進程時(而不是產生信號時),內核纔會決定對他的處理方式. 於是進程在信號遞送給他之
前仍然可以改變對他的動. unix可以調用sigpending將指定的信號設置爲阻塞和未決.
每個進程都有一個信號屏蔽字,他規定了但前要阻塞遞送到該進程的信號集. 對於每種可
能的信號. 該屏蔽字都有一位與之對應. 對於某種信號,若對應位已經設置,但前是被阻塞
的,進程可以用sigprocmask檢測/更改當前信號的屏蔽字.