[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检测/更改当前信号的屏蔽字.

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