[linux]dnotify 內核中監視文件系統上一個目錄中的情況

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檢測/更改當前信號的屏蔽字.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章