inotify
파일 시스템 이벤트를 커널레벨로부터 받을 수 있는 방법임.
리눅스 커널 2.6.13 이상부터 가능함. (그 이전엔 dnotify)



굉장히 간단함.

inotify_init() 로 fd를 얻어서,
inotify_add_watch()로 감시자를 붙임.
inotify_rm_watch()로 감시자 해제.




완전 간단한 예제소스

/*
출처 : http://www.ibm.com/developerworks/kr/library/l-ubuntu-inotify/index.html
*/
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/inotify.h>

#define EVENT_SIZE  ( sizeof (struct inotify_event) )
#define BUF_LEN     ( 1024 * ( EVENT_SIZE + 16 ) )

int main( int argc, char **argv )
{
  int length, i = 0;
  int fd;
  int wd;
  char buffer[BUF_LEN];

  fd = inotify_init();

  if ( fd < 0 ) {
    perror( "inotify_init" );
  }

  wd = inotify_add_watch( fd, "/home/strike",
                         IN_MODIFY | IN_CREATE | IN_DELETE );
  length = read( fd, buffer, BUF_LEN ); 

  if ( length < 0 ) {
    perror( "read" );
  } 

  while ( i < length ) {
    struct inotify_event *event = ( struct inotify_event * ) &buffer[ i ];
    if ( event->len ) {
      if ( event->mask & IN_CREATE ) {
        if ( event->mask & IN_ISDIR ) {
          printf( "The directory %s was created.\n", event->name );      
        }
        else {
          printf( "The file %s was created.\n", event->name );
        }
      }
      else if ( event->mask & IN_DELETE ) {
        if ( event->mask & IN_ISDIR ) {
          printf( "The directory %s was deleted.\n", event->name );      
        }
        else {
          printf( "The file %s was deleted.\n", event->name );
        }
      }
      else if ( event->mask & IN_MODIFY ) {
        if ( event->mask & IN_ISDIR ) {
          printf( "The directory %s was modified.\n", event->name );
        }
        else {
          printf( "The file %s was modified.\n", event->name );
        }
      }
    }
    i += EVENT_SIZE + event->len;
  }

  ( void ) inotify_rm_watch( fd, wd );
  ( void ) close( fd );

  exit( 0 );
}







event 구조체

struct inotify_event
{

    int wd; /* watch descriptor */
    uint32_t mask; /* event tag */
    uint32_t cookie; /* 두 event(IN_MOVED_FROM, IN_MOVED_TO)를 하나로 묶는 쿠키 */
    uint32_t len; /* name 필드에 들어있는 파일 이름 길이 */
    char name __flexarr; /* 파일이름, NULL terminated */
}





발생 이벤트

IN_ACCESS : 파일에 접근했음 (read)
IN_ATTRIB : 권한, 시간 등의 메타데이터가 변했음
IN_CLOSE_WRITE : 쓰기(write)를 위해 열린 파일이 닫혔음 (close)
IN_CLOSE_NOWRITE : 쓰기(write)가 아닌 모드로 열린 파일이 닫혔음 (close)
IN_CREATE : 감시하고 있던 디렉토리에 파일/디렉토리가 생성됨
IN_DELETE : 감시하고 있던 디렉토리에서 파일/디렉토리가 삭제됨
IN_DELETE_SELF : 감시하고 있던 파일/디렉토리 자체가 삭제됨
IN_MODIFY : 파일이 변경되었음
IN_MOVE_SELF : 감시하고 있던 파일/디렉토리가 이동함 (move)
IN_MOVED_FROM : 감시하고 있던 디렉토리에서 파일이 이동해 나갔음 (move)
IN_MOVED_TO : 감시하고 있던 디렉토리에 파일이 이동해 들어왔음 (move)
IN_OPEN : 파일이 열렸음

IN_ALL_EVENTS : 상단에 열거한 모든 이벤트들을 모두 지정함

IN_MOVE : IN_MOVED_FROM | IN_MOVED_TO
IN_CLOSE : IN_CLOSE_WRITE | IN_CLOSE_NOWRITE

IN_DONT_FOLLOW : 심볼릭 링크를 dereference 하지 않음
IN_MASK_ADD : 감시하고 있던 경로에 이미 이벤트가 지정되어 있다면 mask를 교체하지 않고 이벤트를 추가함.
IN_ONESHOT : 단 한번의 이벤트만을 감시하고 이벤트 발생시 감시리스트에서 삭제
IN_ONLYDIR : 감시경로가 디렉토리일 경우 경로만을 감시함.


아래의 Bit들은 read 에서 리턴된 다음에만 지정이 가능함.

IN_IGNORED : 감시가 명시적(inotify_rm_watch()) 혹은 자동적(파일이 지워졌거나, 파일시스템이 unmount 되었을 경우)으로 제거됨.
IN_ISDIR : 디렉토리인가...(-_-)
IN_Q_OVERFLOW : 이벤트큐가 overflow 되었는가 (이 경우 wd = -1)
IN_UNMOUNT : 감시하고 있던 파일시스템이 unmouse 되었음.






[참고]
http://en.wikipedia.org/wiki/Inotify
http://www.ibm.com/developerworks/kr/library/l-ubuntu-inotify/index.html




Posted by bloodguy
,